{"id":32435341,"url":"https://github.com/hackwaly/task","last_synced_at":"2026-01-20T17:50:53.033Z","repository":{"id":319856516,"uuid":"1079853597","full_name":"hackwaly/task","owner":"hackwaly","description":"A lightweight turborepo like task runner","archived":false,"fork":false,"pushed_at":"2025-10-20T15:33:30.000Z","size":13,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-20T15:35:27.677Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hackwaly.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-20T13:41:24.000Z","updated_at":"2025-10-20T15:33:35.000Z","dependencies_parsed_at":"2025-10-20T15:35:32.447Z","dependency_job_id":null,"html_url":"https://github.com/hackwaly/task","commit_stats":null,"previous_names":["hackwaly/task"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/hackwaly/task","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hackwaly%2Ftask","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hackwaly%2Ftask/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hackwaly%2Ftask/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hackwaly%2Ftask/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hackwaly","download_url":"https://codeload.github.com/hackwaly/task/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hackwaly%2Ftask/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281185458,"owners_count":26457747,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-26T02:00:06.575Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-25T22:51:26.672Z","updated_at":"2025-10-26T23:01:47.741Z","avatar_url":"https://github.com/hackwaly.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @hackwaly/task\n\nA lightweight, TypeScript-native task runner inspired by Turborepo. Define your build pipeline with code, not configuration files.\n\n## Features\n\n- 🚀 **TypeScript-first**: Define tasks in TypeScript with full type safety\n- 📦 **Dependency management**: Automatic task dependency resolution and execution\n- 👀 **Watch mode**: File watching with intelligent task re-execution\n- ⚡ **Parallel execution**: Run independent tasks concurrently\n- 🎯 **Persistent tasks**: Support for long-running processes (servers, watchers)\n- 🔄 **Interruptible tasks**: Graceful handling of task interruption\n- 📁 **Input/Output tracking**: File-based change detection for efficient rebuilds\n\n## Installation\n\n```bash\nnpm install @hackwaly/task\n# or\npnpm add @hackwaly/task\n# or\nyarn add @hackwaly/task\n```\n\n## Quick Start\n\n1. Create a `taskfile.js` in your project root:\n\n```javascript\nimport { configInit } from \"@hackwaly/task\";\n\nconst { defineTask } = configInit(import.meta);\n\nexport const build = defineTask({\n  name: \"build\",\n  command: \"tsc --build\",\n  inputs: [\"src/**/*.ts\", \"tsconfig.json\"],\n  outputs: [\"dist/**/*.js\"],\n});\n\nexport const test = defineTask({\n  name: \"test\",\n  command: \"vitest run\",\n  dependsOn: [build],\n});\n\nexport const dev = defineTask({\n  name: \"dev\",\n  command: \"tsc --watch\",\n  persistent: true,\n});\n\nexport default build;\n```\n\n2. Run tasks:\n\n```bash\n# Run a single task\nnpx task run build\n\n# Run multiple tasks\nnpx task run build test\n\n# Run with watch mode\nnpx task run build --watch\n\n# List available tasks\nnpx task list\n```\n\n## Task Configuration\n\nTasks are defined using the `defineTask` function with the following options:\n\n```typescript\ninterface TaskConfig {\n  name: string;              // Task name (required)\n  description?: string;      // Task description for help text\n  command?: string | string[] | { program: string; args?: string[] };\n  env?: Record\u003cstring, string\u003e;  // Environment variables\n  cwd?: string;              // Working directory (defaults to taskfile location)\n  inputs?: string[];         // Input file patterns (for change detection)\n  outputs?: string[];        // Output file patterns\n  persistent?: boolean;      // Whether task runs continuously (like servers)\n  interruptible?: boolean;   // Whether task can be interrupted safely\n  dependsOn?: TaskDef[];     // Task dependencies\n}\n```\n\n### Command Formats\n\nCommands can be specified in multiple formats:\n\n```javascript\n// String (parsed with shell-like parsing)\ncommand: \"tsc --build --verbose\"\n\n// Array\ncommand: [\"tsc\", \"--build\", \"--verbose\"]\n\n// Object\ncommand: {\n  program: \"tsc\",\n  args: [\"--build\", \"--verbose\"]\n}\n```\n\n### Dependencies\n\nTasks can depend on other tasks. Dependencies are resolved automatically:\n\n```javascript\nexport const generateTypes = defineTask({\n  name: \"generate-types\",\n  command: \"generate-types src/schema.json\",\n  outputs: [\"src/types.ts\"],\n});\n\nexport const build = defineTask({\n  name: \"build\",\n  command: \"tsc --build\",\n  inputs: [\"src/**/*.ts\"],\n  dependsOn: [generateTypes],  // Runs generateTypes first\n});\n```\n\n### Persistent Tasks\n\nFor long-running processes like development servers:\n\n```javascript\nexport const server = defineTask({\n  name: \"server\",\n  command: \"node server.js\",\n  persistent: true,        // Runs continuously\n  interruptible: true,     // Can be stopped gracefully\n});\n```\n\n## Watch Mode\n\nWatch mode automatically re-runs tasks when their input files change:\n\n```bash\nnpx task run build --watch\n```\n\nFeatures:\n- Monitors all input patterns defined in tasks\n- Ignores `node_modules` by default\n- Propagates changes through the dependency graph\n- Only reruns tasks that are affected by changes\n\n## Commands\n\n### `run \u003ctasks...\u003e`\n\nRun one or more tasks:\n\n```bash\n# Single task\nnpx task run build\n\n# Multiple tasks\nnpx task run lint test build\n\n# With watch mode\nnpx task run build --watch\n```\n\n### `list` / `ls`\n\nList all available tasks:\n\n```bash\nnpx task list\n```\n\nShows task names and descriptions in a formatted table.\n\n## Examples\n\n### Basic Build Pipeline\n\n```javascript\nimport { configInit } from \"@hackwaly/task\";\n\nconst { defineTask } = configInit(import.meta);\n\nexport const lint = defineTask({\n  name: \"lint\",\n  description: \"Lint TypeScript files\",\n  command: \"eslint src/**/*.ts\",\n  inputs: [\"src/**/*.ts\", \".eslintrc.json\"],\n});\n\nexport const typecheck = defineTask({\n  name: \"typecheck\",\n  description: \"Type check TypeScript files\",\n  command: \"tsc --noEmit\",\n  inputs: [\"src/**/*.ts\", \"tsconfig.json\"],\n});\n\nexport const build = defineTask({\n  name: \"build\",\n  description: \"Build the project\",\n  command: \"tsc --build\",\n  inputs: [\"src/**/*.ts\", \"tsconfig.json\"],\n  outputs: [\"dist/**/*.js\"],\n  dependsOn: [lint, typecheck],\n});\n\nexport const test = defineTask({\n  name: \"test\",\n  description: \"Run tests\",\n  command: \"vitest run\",\n  dependsOn: [build],\n});\n```\n\n### Development Workflow\n\n```javascript\nexport const generateSchema = defineTask({\n  name: \"generate-schema\",\n  command: \"generate-schema api.yaml\",\n  inputs: [\"api.yaml\"],\n  outputs: [\"src/generated/schema.ts\"],\n});\n\nexport const dev = defineTask({\n  name: \"dev\",\n  description: \"Start development server\",\n  command: \"vite dev\",\n  persistent: true,\n  interruptible: true,\n  dependsOn: [generateSchema],\n});\n\nexport const buildWatch = defineTask({\n  name: \"build:watch\",\n  description: \"Build in watch mode\",\n  command: \"tsc --watch\",\n  persistent: true,\n  dependsOn: [generateSchema],\n});\n```\n\n## Advanced Usage\n\n### Monorepo Support\n\nEach package can have its own `taskfile.js`:\n\n```javascript\n// packages/ui/taskfile.js\nimport { configInit } from \"@hackwaly/task\";\n\nconst { defineTask } = configInit(import.meta);\n\nexport const build = defineTask({\n  name: \"build:ui\",\n  command: \"rollup -c\",\n  inputs: [\"src/**/*\", \"rollup.config.js\"],\n  outputs: [\"dist/**/*\"],\n});\n\n// packages/app/taskfile.js\nimport { build as buildUI } from \"../ui/taskfile.js\";\n\nexport const build = defineTask({\n  name: \"build:app\",\n  command: \"vite build\",\n  dependsOn: [buildUI],  // Cross-package dependency\n});\n```\n\n### Custom Task Logic\n\nFor complex tasks, you can provide custom logic:\n\n```javascript\nexport const customTask = defineTask({\n  name: \"custom\",\n  async run(ctx) {\n    // Custom async logic\n    console.log(\"Running custom task...\");\n\n    // Check if aborted\n    if (ctx.abort.aborted) {\n      return;\n    }\n\n    // Your custom logic here\n  },\n  inputs: [\"src/**/*\"],\n});\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhackwaly%2Ftask","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhackwaly%2Ftask","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhackwaly%2Ftask/lists"}