Tasks in devenv allow you to define units of work that form a dependency graph (a DAG). devenv schedules them in parallel wherever possible, respects dependency ordering, and can cache results to skip work that hasn’t changed. Tasks integrate naturally with processes and the shell lifecycle via built-inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/cachix/devenv/llms.txt
Use this file to discover all available pages before exploring further.
enterShell and enterTest hooks.
Defining Tasks
Tasks are defined undertasks in devenv.nix. The key is a namespaced name using colons:
devenv.nix
Dependencies Between Tasks
Declare edges between tasks usingbefore or after:
after = [ "other" ]— run this task afterother(makesotheran upstream dependency).before = [ "other" ]— run this task beforeother(makes this task an upstream dependency ofother).
before and after describe the same edge from opposite ends, so you can declare a dependency from whichever side is more convenient. These are equivalent:
devenv.nix
Dependency States
A dependency waits for its target to reach a particular state before it is considered satisfied. Append an@ suffix to choose the state explicitly:
| Suffix | Satisfied when | Failure propagates? |
|---|---|---|
@started | the target has begun executing | yes |
@ready | a process passes its readiness probe; for tasks this means success | yes |
@succeeded | the target exits with code 0 (or is skipped) | yes |
@completed | the target finishes, regardless of exit code | no (soft dependency) |
@ready for processes and @succeeded for one-shot tasks.
A common use is running a setup task once a service is ready:
devenv.nix
Execution Modes
When you run a task, devenv schedules a subgraph around it rather than only that one task.--mode controls how much of the graph is included:
| Mode | Runs |
|---|---|
single | only the named task |
before (default) | the task and everything upstream of it |
after | the task and everything downstream of it |
all | the entire connected graph, both upstream and downstream |
devenv up starts processes in before mode, while devenv test runs in all mode. This difference matters for setup tasks attached to processes — see Processes as tasks below.enterShell and enterTest Integration
devenv:enterShell and devenv:enterTest are built-in lifecycle events that run tasks at specific points:
devenv:enterShellruns before the shell is entered (devenv shell) and before processes start (devenv up).devenv:enterTestruns before tests execute (devenv test). It depends ondevenv:enterShell, so all shell setup tasks run first automatically.
before to declare that your task should run before the event completes:
devenv.nix
devenv:git-hooks:install as a dependency of devenv:enterShell.
Using Another Language for Task Execution
Tasks can use a specific package as their interpreter, for example a Python package:devenv.nix
Caching with status
If you define a status command, it will be executed first. If it returns 0, the exec command is skipped. When a task is skipped, outputs from the most recent successful run are restored and passed to dependent tasks.
devenv.nix
Running Only When Files Have Changed
UseexecIfModified to specify a list of files or glob patterns to monitor. The task only runs if any of these files have been modified since the last successful run:
devenv.nix
Inputs and Outputs
Tasks support passing inputs and producing outputs, both as JSON objects. The following environment variables are available inside a task’sexec script:
$DEVENV_TASK_INPUT— JSON object fromtasks."myapp:mytask".input$DEVENV_TASKS_OUTPUTS— JSON object with dependent task names as keys and their outputs as values$DEVENV_TASK_OUTPUT_FILE— writable file where the task writes its JSON output$DEVENV_TASK_EXPORTS_FILE— writable file for exporting environment variables to dependent tasks (writename\0base64(value)\0pairs)
devenv.nix
Shell Messages
Tasks can display messages to the user when entering the shell by writing adevenv.messages array to $DEVENV_TASK_OUTPUT_FILE:
devenv.nix
Passing Inputs from the CLI
You can override or add inputs when running tasks from the command line using--input and --input-json:
--input count=3 sets a number, --input flag=true sets a boolean, and --input name=hello sets a string.
You can also pass a full JSON object:
--input-json is applied first, then individual --input values are merged on top.
Processes as Tasks
All processes defined inprocesses are automatically available as tasks with the devenv:processes: prefix. This allows you to:
- Run individual processes as tasks
- Define dependencies between tasks and processes
- Use
before/afteredges connecting tasks and processes interchangeably
devenv.nix
devenv tasks run devenv:processes:web-server, it will:
- First run any tasks that have
before = [ "devenv:processes:web-server" ] - Then execute the process itself
@completed state:
devenv.nix
Git Integration
Tasks can reference the git repository root path using${config.git.root}, which is useful in monorepo environments:
devenv.nix
devenv.nix file is located within the repository.