A task runner that delegates the work to other tools
Rust
59
306 commits
updated Sep 10, 2026
Dela is a task runner that provides discovery for task definitions in various formats, and lets you execute tasks without specifying the runner while delegating their execution to your existing tools like make, npm, uv, and others.
Install dela from npmjs.com via npm or another compatible JavaScript package manager and initialize it to set up shell integration:
$ npm install -g @aleyan/dela
$ dela init
Alternatively, you can build and install the Rust binary directly from crates.io:
cargo +1.96.1 install dela
dela init
The dela init command will:
~/.config/dela directory for configurationList all available tasks in the current directory:
$ dela list
You can invoke a task just by its name from the shell via <task>. For example here build task is defined in Makefile and is invoked directly.
$ build
If you are running dela in a directory for the first time, it will ask you to put the task or the task definition file or the directory itself on the allowed list. This is because you might want to run dela in non fully trusted directories and cause inadvertent execution.
$ build
Running build from ~/Projects/dela/Makefile for the first time. Allow?
0) Allow one time
1) Allow build from ~/Projects/dela/Makefile
2) Allow any command from ~/Projects/dela/Makefile
3) Allow any command from ~/Projects/dela
4) Deny
You can also use dr (acronym for dela run) to explicitly invoke a task via dela:
$ dr build
Or use dela run for subshell execution:
$ dela run build
The allowlist is a TOML file located at ~/.config/dela/allowlist.toml. It stores allow and deny rules at folder, file, and task level. It gets updated when you either run a task in a new folder for the first time, or when you run dela allow <task> and dela deny <task> commands explicitly.
Dela includes an MCP (Model Context Protocol) server that allows AI assistants and editors to discover and execute tasks programmatically.
The mcp executed tasks need to be already on the allowlist. The mcp server respects the allowlist, but does not give agents tools to modify it.
You need to have dela installed first and then run the command for your coding agent.
$ dela mcp --init-cursor # Cursor: ~/.cursor/mcp.json
$ dela mcp --init-vscode # VSCode: <user profile>/Code/User/mcp.json
$ dela mcp --init-codex # OpenAI Codex: ~/.codex/config.toml
$ dela mcp --init-gemini # Gemini CLI: ~/.gemini/settings.json
$ dela mcp --init-antigravity # Antigravity: ~/.gemini/config/mcp_config.json
$ dela mcp --init-claude-code # Claude Code: ~/.claude.json
$ dela mcp --init-cline # Cline: ~/.cline/data/settings/cline_mcp_settings.json (override with CLINE_MCP_SETTINGS_PATH)
$ dela mcp --init-opencode # OpenCode: ~/.config/opencode/opencode.json
$ dela mcp --init-crush # Crush: ~/.config/crush/crush.json
$ dela mcp --init-grok # Grok Build: ~/.grok/config.toml (override with $GROK_HOME/config.toml)
Re-running an --init-* flag repairs a broken entry (a missing binary, a relative path)
and otherwise leaves your config alone, including any arguments you added by hand.
Assuming you have already run dela init.
$ dela mcp [--cwd <directory>]
The server communicates over stdio using JSON-RPC 2.0 and streams task output via logging notifications.
Tool names are stable, and list_tasks exposes a stable wire format (including unique_name with suffixes like test-m).
| Tool | Description |
|---|---|
list_tasks | List all available tasks with metadata (runner, availability, allowlist status) |
status | List all currently running background tasks |
task_start | Start a task by unique name with optional args/env/cwd |
task_status | Get status for running instances of a specific task |
task_output | Get stream-aware output chunks for a task by PID, with optional offset paging |
task_stop | Stop a running task by PID (SIGTERM + grace period + SIGKILL) |
The MCP server uses the same allowlist as the CLI (~/.config/dela/allowlist.toml). Tasks must be explicitly allowlisted to be executed via MCP. Use the regular dela CLI commands to manage allowlists.
dela init must be run before starting the MCP server so the dela config directory and allowlist exist.
dela uses your shell's command_not_found_handler to detect when you are trying to run a command that doesn't exist. It then scans the current working directory for task definition files and executes the appropriate task runner.
Then the bare command will be executed instead of the task. Tasks shadowed by shell builtins and conflicting with other tasks get a unique suffixed name (for example test from a Makefile becomes test-m), so you can run the task via its suffixed name; dr <task_name> also works.
You add tasks to your existing task definition files (like Makefile, package.json, or pyproject.toml), and dela will discover them automatically.
When executing bare tasks or via dr, tasks are executed in the current shell environment. When running tasks via dela run, tasks are executed in a subshell environment.
Currently, dela supports zsh, bash, fish, and PowerShell.
Currently, dela supports make, npm, yarn, pnpm, bun, uv, poetry, poe (poethepoet), Turborepo, Maven, Gradle, GitHub Actions, Docker Compose, CMake, Travis CI, just, mise and task.
Currently, dela supports macOS and Linux. There is no Windows support, powershell is for Linux only.
Allowlists are a safety feature to prevent accidental execution (especially in untrusted directories). They’re not a sandbox, so treat tasks from downloaded repos with the same caution you would with make or npm.
dela is not at 0.1 yet and its cli is subject to change.
Other task runners that handle multiple runners are task-keeper, ds, and rt.
For developing dela, please refer to the development guide, testing guide, and style guide.
Note: dela is not at 0.1 yet and its CLI is subject to change.
238 commits
68 commits
Rust
82.4%
Shell
7.2%
Python
6.0%
Makefile
1.4%
Dockerfile
1.1%
PowerShell
1.1%
A task runner that delegates the work to other tools
Rust
59
306 commits
updated Sep 10, 2026
Dela is a task runner that provides discovery for task definitions in various formats, and lets you execute tasks without specifying the runner while delegating their execution to your existing tools like make, npm, uv, and others.
Install dela from npmjs.com via npm or another compatible JavaScript package manager and initialize it to set up shell integration:
$ npm install -g @aleyan/dela
$ dela init
Alternatively, you can build and install the Rust binary directly from crates.io:
cargo +1.96.1 install dela
dela init
The dela init command will:
~/.config/dela directory for configurationList all available tasks in the current directory:
$ dela list
You can invoke a task just by its name from the shell via <task>. For example here build task is defined in Makefile and is invoked directly.
$ build
If you are running dela in a directory for the first time, it will ask you to put the task or the task definition file or the directory itself on the allowed list. This is because you might want to run dela in non fully trusted directories and cause inadvertent execution.
$ build
Running build from ~/Projects/dela/Makefile for the first time. Allow?
0) Allow one time
1) Allow build from ~/Projects/dela/Makefile
2) Allow any command from ~/Projects/dela/Makefile
3) Allow any command from ~/Projects/dela
4) Deny
You can also use dr (acronym for dela run) to explicitly invoke a task via dela:
$ dr build
Or use dela run for subshell execution:
$ dela run build
The allowlist is a TOML file located at ~/.config/dela/allowlist.toml. It stores allow and deny rules at folder, file, and task level. It gets updated when you either run a task in a new folder for the first time, or when you run dela allow <task> and dela deny <task> commands explicitly.
Dela includes an MCP (Model Context Protocol) server that allows AI assistants and editors to discover and execute tasks programmatically.
The mcp executed tasks need to be already on the allowlist. The mcp server respects the allowlist, but does not give agents tools to modify it.
You need to have dela installed first and then run the command for your coding agent.
$ dela mcp --init-cursor # Cursor: ~/.cursor/mcp.json
$ dela mcp --init-vscode # VSCode: <user profile>/Code/User/mcp.json
$ dela mcp --init-codex # OpenAI Codex: ~/.codex/config.toml
$ dela mcp --init-gemini # Gemini CLI: ~/.gemini/settings.json
$ dela mcp --init-antigravity # Antigravity: ~/.gemini/config/mcp_config.json
$ dela mcp --init-claude-code # Claude Code: ~/.claude.json
$ dela mcp --init-cline # Cline: ~/.cline/data/settings/cline_mcp_settings.json (override with CLINE_MCP_SETTINGS_PATH)
$ dela mcp --init-opencode # OpenCode: ~/.config/opencode/opencode.json
$ dela mcp --init-crush # Crush: ~/.config/crush/crush.json
$ dela mcp --init-grok # Grok Build: ~/.grok/config.toml (override with $GROK_HOME/config.toml)
Re-running an --init-* flag repairs a broken entry (a missing binary, a relative path)
and otherwise leaves your config alone, including any arguments you added by hand.
Assuming you have already run dela init.
$ dela mcp [--cwd <directory>]
The server communicates over stdio using JSON-RPC 2.0 and streams task output via logging notifications.
Tool names are stable, and list_tasks exposes a stable wire format (including unique_name with suffixes like test-m).
| Tool | Description |
|---|---|
list_tasks | List all available tasks with metadata (runner, availability, allowlist status) |
status | List all currently running background tasks |
task_start | Start a task by unique name with optional args/env/cwd |
task_status | Get status for running instances of a specific task |
task_output | Get stream-aware output chunks for a task by PID, with optional offset paging |
task_stop | Stop a running task by PID (SIGTERM + grace period + SIGKILL) |
The MCP server uses the same allowlist as the CLI (~/.config/dela/allowlist.toml). Tasks must be explicitly allowlisted to be executed via MCP. Use the regular dela CLI commands to manage allowlists.
dela init must be run before starting the MCP server so the dela config directory and allowlist exist.
dela uses your shell's command_not_found_handler to detect when you are trying to run a command that doesn't exist. It then scans the current working directory for task definition files and executes the appropriate task runner.
Then the bare command will be executed instead of the task. Tasks shadowed by shell builtins and conflicting with other tasks get a unique suffixed name (for example test from a Makefile becomes test-m), so you can run the task via its suffixed name; dr <task_name> also works.
You add tasks to your existing task definition files (like Makefile, package.json, or pyproject.toml), and dela will discover them automatically.
When executing bare tasks or via dr, tasks are executed in the current shell environment. When running tasks via dela run, tasks are executed in a subshell environment.
Currently, dela supports zsh, bash, fish, and PowerShell.
Currently, dela supports make, npm, yarn, pnpm, bun, uv, poetry, poe (poethepoet), Turborepo, Maven, Gradle, GitHub Actions, Docker Compose, CMake, Travis CI, just, mise and task.
Currently, dela supports macOS and Linux. There is no Windows support, powershell is for Linux only.
Allowlists are a safety feature to prevent accidental execution (especially in untrusted directories). They’re not a sandbox, so treat tasks from downloaded repos with the same caution you would with make or npm.
dela is not at 0.1 yet and its cli is subject to change.
Other task runners that handle multiple runners are task-keeper, ds, and rt.
For developing dela, please refer to the development guide, testing guide, and style guide.
Note: dela is not at 0.1 yet and its CLI is subject to change.
238 commits
68 commits
Rust
82.4%
Shell
7.2%
Python
6.0%
Makefile
1.4%
Dockerfile
1.1%
PowerShell
1.1%