lager devenv manages a reproducible, Docker-based development environment for
a project. It records the image, mount directory, shell, saved commands, bind
mounts, and environment variables in the DEVENV section of your project’s
.lager config file, so every engineer (and your CI) builds and tests in the
same container.
The environment is consumed by lager exec
(run a command in the container) and lager devenv terminal (open an
interactive shell in the container).
Syntax
Subcommands
| Command | Description |
|---|---|
create | Create the DEVENV config (image, mount dir, shell) |
terminal | Open an interactive shell in the container |
show | Print the resolved DEVENV configuration |
set | Set a scalar config key (or append to ports) |
unset | Remove a config key entirely |
add | Save a named command |
delete | Remove a saved command |
commands | List saved commands |
mount add/remove/list | Manage persistent bind-mounts / volumes |
env set/unset/list | Manage persistent environment variables |
Prerequisites
Docker must be installed and on yourPATH. Install it from
docker.com. On Linux, add your user to
the docker group so you don’t need sudo:
create
Create theDEVENV section in your project’s .lager config. Run this once
per project before using lager exec or lager devenv terminal.
| Option | Default | Description |
|---|---|---|
--image TEXT | lagerdata/devenv-cortexm | Docker image to use |
--mount-dir TEXT | /app | Where your source code is mounted inside the container |
--shell TEXT | /bin/bash | Shell executable inside the image |
name,
name:tag, registry/name, registry/name:tag). For lagerdata/* images the
shell defaults to /bin/bash; for other images you’ll be prompted. If a
DEVENV section already exists you’ll be asked before overwriting it.
terminal
Open an interactive shell inside the development container. Your project directory is bind-mounted at the configuredmount_dir, and the container is
removed on exit (unless --detach is used).
| Option | Short | Description |
|---|---|---|
--mount TEXT | -m | Mount a named Docker volume at mount_dir instead of the source dir |
--user TEXT | -u | User to run as (overrides the user config key) |
--group TEXT | -g | Group to run as (overrides the group config key) |
--name TEXT | -n | Set the container name |
--detach / --no-detach | -d | Run the container detached |
--port TEXT | -p | Publish a port (HOST:CONTAINER). Repeatable |
--entrypoint TEXT | Override the container entrypoint | |
--network TEXT | Docker network mode | |
--platform TEXT | Target platform (e.g. linux/amd64) | |
--attach TEXT | -a | Attach a shell to an already-running container by name |
--shell TEXT | -s | Shell to use when attaching (default: config shell or /bin/bash) |
--volume TEXT | -v | Bind-mount a host path (HOST:CONTAINER[:ro]). Repeatable |
--env FOO=BAR | -e | Set an environment variable. Repeatable |
--passenv NAME | Pass a variable through from your current shell. Repeatable | |
--info | Print the resolved docker command and config, then exit without launching |
DEVENV
config; config-defined ports, volumes, and environment are applied
first, then anything passed on the command line is appended.
terminal also wires up SSH for you automatically: it forwards your
SSH_AUTH_SOCK agent socket and mounts ~/.ssh/id_ed25519 and
~/.ssh/known_hosts (read-only) when they exist, and it mounts your global
.lager config into the container so nested lager calls are authenticated.
Use --info to debug what would run without launching anything:
Attach to a running container
show
Print the resolvedDEVENV configuration — scalar keys, list keys (ports,
volumes, environment), and saved commands.
set / unset
Set or remove individual configuration keys without re-runningcreate.
set): image, mount_dir, shell, user,
group, entrypoint, hostname, macaddr, network, platform,
repo_root_relative_path.
The ports key is a list and is appended to (the singular alias port
is accepted). Edit volumes and environment with lager devenv mount and
lager devenv env respectively — set will refuse them and point you at the
right command.
Saved commands: add / delete / commands
Save shell commands under a name so they can be run withlager exec <name>. Commands are stored as
cmd.<name> keys in the DEVENV section.
add prompts for it. By default add warns when
overwriting an existing command; pass --no-warn to suppress that.
Persistent bind-mounts: mount
Persist host bind-mounts / named volumes in the config so they’re applied on everylager devenv terminal and lager exec run.
-v form: HOST:CONTAINER[:ro] for a bind-mount or
NAME:CONTAINER for a named volume. For portability across machines, specs may
use ~, environment variables, and ${PROJECT_ROOT} (which expands to your
project’s .lager directory).
Persistent environment variables: env
Persist environment variables in the config so they’re set on every run.env set replaces any existing value for the same variable.
How it relates to lager exec
| Command | Purpose |
|---|---|
lager devenv ... | Configure the local container (image, mounts, env, saved commands) |
lager devenv terminal | Open an interactive shell in that container |
lager exec | Run a one-off or saved command in that container |
DEVENV section, so a command saved with
lager devenv add is runnable with lager exec, and a mount added with
lager devenv mount add applies to both terminal and exec.
Notes
- Configuration is stored in the
DEVENVsection of the nearest.lagerconfig file, discovered by walking up from the current directory. terminallaunches the container with--rmby default, so it’s removed on exit unless you pass--detach.- Exit codes from the container are propagated to the CLI.

