> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lagerdata.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Devenv

> Manage a local Docker-based development environment for your project

`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. Every engineer, and your CI, then builds and tests in the
same container.

The environment is consumed by [`lager exec`](/source/reference/cli/exec)
(run a command in the container) and `lager devenv terminal` (open an
interactive shell in the container).

## Syntax

```bash theme={null}
lager devenv COMMAND [ARGS]...
```

## 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 your `PATH`. Install it from
[docker.com](https://docs.docker.com/get-docker/). On Linux, add your user to
the `docker` group so you don't need `sudo`:

```bash theme={null}
sudo usermod -aG docker $USER   # then log out/in, or run: newgrp docker
```

***

## create

Create the `DEVENV` section in your project's `.lager` config. Run this once
per project before using `lager exec` or `lager devenv terminal`.

```bash theme={null}
lager devenv create
```

| 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 |

The image name is validated against standard Docker naming (`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 configured `mount_dir`, and the container is
removed on exit (unless `--detach` is used).

```bash theme={null}
lager devenv terminal
```

| 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 |

CLI flags take precedence over the matching keys stored in the `DEVENV`
config. The CLI applies the config-defined `ports`, `volumes`, and
`environment` first, then appends anything you pass on the command line.

`terminal` also wires up SSH for you automatically. It forwards your
`SSH_AUTH_SOCK` agent socket, and it mounts `~/.ssh/id_ed25519` and
`~/.ssh/known_hosts` (read-only) when they exist. It also mounts your global
`.lager` config into the container, so nested `lager` calls are authenticated.

Use `--info` to see what runs, without launching anything:

```bash theme={null}
lager devenv terminal --info
```

### Attach to a running container

```bash theme={null}
# Open a second shell in a container started with --detach --name build
lager devenv terminal --attach build --shell /bin/bash
```

***

## show

Print the resolved `DEVENV` configuration — scalar keys, list keys (ports,
volumes, environment), and saved commands.

```bash theme={null}
lager devenv show
```

***

## set / unset

Set or remove individual configuration keys without re-running `create`.

```bash theme={null}
lager devenv set image lagerdata/devenv-cortexm:latest
lager devenv set mount_dir /workspace
lager devenv set port 8080:8080      # appends to the ports list
lager devenv unset platform
```

Scalar keys (replaced on `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 with
[`lager exec <name>`](/source/reference/cli/exec). Commands are stored as
`cmd.<name>` keys in the `DEVENV` section.

```bash theme={null}
lager devenv add build "make -j4"
lager devenv add test "pytest tests/ --tb=short"
lager devenv commands          # list saved commands
lager devenv delete build      # remove one
```

Command names can contain only letters, numbers, dashes, and underscores. If
you omit the command string, `add` prompts for it.

| Subcommand | Option | Description |
| - | - | - |
| `add` | `--warn` / `--no-warn` | Warn when overwriting an existing command (default: `--warn`) |
| `delete` | `--devenv NAME` | Delete the command from a named devenv rather than the current one |

***

## Persistent bind-mounts: mount

Persist host bind-mounts / named volumes in the config so they're applied on
every `lager devenv terminal` and `lager exec` run.

```bash theme={null}
lager devenv mount add /host/cache:/root/.cache       # host bind-mount
lager devenv mount add toolchain:/opt/toolchain       # named volume
lager devenv mount add /etc/ssl/certs:/etc/ssl/certs:ro
lager devenv mount list
lager devenv mount remove /host/cache:/root/.cache
```

Specs use Docker `-v` form: `HOST:CONTAINER[:ro]` for a bind-mount or
`NAME:CONTAINER` for a named volume. For portability across machines, specs can
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.

```bash theme={null}
lager devenv env set CFLAGS=-O2
lager devenv env set DEBUG=0
lager devenv env list
lager devenv env unset DEBUG
```

`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`](/source/reference/cli/exec) | Run a one-off or saved command in that container |

All three read the same `DEVENV` section. A command saved with
`lager devenv add` runs under `lager exec`. A mount added with
`lager devenv mount add` applies to `terminal`, and to `exec` when `exec`
starts a container. In a CI job that the CLI detects, `exec` runs the command
in place and ignores mounts. See
[Running in CI](/source/reference/cli/exec#running-in-ci).

## Notes

* Configuration is stored in the `DEVENV` section of the nearest `.lager`
  config file, discovered by walking up from the current directory.
* `terminal` launches the container with `--rm` by default, so it's removed on
  exit unless you pass `--detach`.
* Exit codes from the container are propagated to the CLI.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.