Devenv 2.2: attach to running processes and persistent out-of-tree environments

domenkozar2 pts0 comments

devenv 2.2: attach to running processes and persistent out-of-tree environments - devenv

Skip to content

Initializing search

cachix/devenv

Essentials

Scripts

Declarative files

Git hooks

Tests

Pinning

Processes & Services

Services

Containers

Advanced

Writing devenv.yaml

Overview

Extending

Guides

Integrations

Editor support

Reference

Recipes

Blog

Roadmap

Community

Discord

devenv 2.2: attach to running processes and persistent out-of-tree environments

devenv 2.2 ships:

Attach to running processes: share one native process manager across terminals, with live status, ports, logs, and a choice to detach or stop.

Persistent out-of-tree environments: bind a directory to a local or remote --from source, including profiles and the source's complete devenv.yaml.

More reliable shell activation: automatically load hooks in fish and nushell, select the correct login shell in stripped environments, and behave predictably in multiplexers and nested shells.

SecretSpec 0.17 and Cachix integration: upgrade from SecretSpec 0.8, pull and push to private caches without exporting CACHIX_AUTH_TOKEN, and run the bundled SecretSpec CLI with the same profile and provider as devenv.

A calmer and sturdier TUI: use near-zero CPU while idle, distinguish every process state at a glance, and handle unusual terminal input safely.

Evaluation cache fixes: invalidate correctly when local inputs, copied sources, and files modified during evaluation change.

Better automation interfaces: inspect tasks as JSON, access inputs in the REPL, distinguish trace callers, and avoid streaming interactive output into coding agents.

Smaller installs and better diagnostics: remove unnecessary LLVM and debug-toolchain dependencies while surfacing clearer errors in terminals and CI.

One process manager, many terminals

Running devenv up while the native process manager is already active now attaches to it instead of failing (devenv#2936). The second invocation connects over the control socket, starts any requested processes that aren't running yet, and streams status, ports, and logs.

$ devenv up -d # start processes in the background<br>$ devenv up # attach: live status, ports, and logs<br>$ devenv processes attach # watch without requesting any starts<br>$ devenv processes start postgres # start one process, cold-starting a manager if needed

The manager resolves before and after ordering through its own task scheduler. An attached terminal first receives the current state and recent log output, then follows live changes. Other terminals can attach and detach independently without taking ownership away from the daemon.

Ctrl-C on an attached devenv up asks whether you want to detach and leave the processes running, or stop the whole manager. devenv processes attach always detaches on Ctrl-C.

devenv processes start no longer requires a manager to be running. It can cold-start one in the background with that process and its dependency closure, equivalent to devenv up -d (devenv#2930). Named starts always start the requested process, even when its default start.enable is false.

Attaching is deliberately interactive. CI jobs, piped commands, and detected coding agents report that processes are already running instead of entering a live view that could wait indefinitely.

Under the hood, the process manager became the single owner of process state, the daemon pushes attach sessions as an event stream instead of being polled, and every process launch goes through the same task graph. This fixed a family of lifecycle bugs along the way: double launches, processes vanishing from list, stuck relaunches, concurrent daemon startup, and a foreground devenv up corrupting a running daemon's PID file.

Closes devenv#971, open since February 2024.

Configure an environment once, use it anywhere

--from lets you use a devenv without checking devenv.nix into the project. In 2.1 you had to repeat the flag for every command. In 2.2, devenv allow can bind the current directory to that source:

$ cd my-project<br>$ devenv --from github:myorg/devenv-configs?dir=rust-web allow<br>$ devenv shell

Every subsequent devenv command in that directory loads the bound configuration. The native shell hook auto activates it on cd, just like a project with a local devenv.nix.

Profiles persist with the binding:

$ devenv --from github:myorg/devenv-configs \<br>--profile backend \<br>--profile observability \<br>allow

An explicit --profile still takes priority when you need a one-off override.

Local sources now bring their entire configuration with them. --from path:../shared-devenv loads the source's devenv.yaml, inputs, imports, and sibling modules from its Git repository. Modules are read from the live directory, so edits take effect without fetching or rebinding the source.

Normal in-tree projects are easier to navigate too: devenv now walks up parent directories to find devenv.nix. Commands work from any subdirectory while the shell and devenv shell -- keep the...

devenv processes from running process attach

Related Articles