Add opt-in root access, persistent containers and per-project packages

This commit is contained in:
2026-10-27 21:04:41 +01:00
parent a2cda697dd
commit 874352397f
5 changed files with 283 additions and 19 deletions

View File

@@ -7,6 +7,8 @@ Run Claude Code isolated in a podman container, one command per project.
- `Containerfile`: the image (Debian slim + Claude Code).
- `claudio.sh`: builds, updates and runs the container.
- `.claudio`: template for per-project settings (plain bash).
- `test.sh`: end-to-end tests, run on the host (`./test.sh`, or `./test.sh --update`
to also test the slow `claudio update`).
## Install
@@ -27,6 +29,7 @@ claudio --resume # any extra args are passed to claude
claudio shell # bash inside the container instead of claude
claudio build # build the image
claudio update # rebuild from scratch: latest base image + latest Claude Code
claudio reset # remove this project's persistent container (PERSIST=1)
```
The current directory is mounted at the same path inside the container.
@@ -43,6 +46,9 @@ cp ~/claudio/.claudio ~/projects/myapp/
```bash
GUI=1
AUDIO=1
ROOT=1
PERSIST=1
PACKAGES=(python3 nodejs)
MOUNTS=("$HOME/.gitconfig:/home/claude/.gitconfig:ro" "/data/shared")
PODMAN_ARGS=(-e GITHUB_TOKEN -p 3000:3000)
CLAUDE_ARGS=(--model opus)
@@ -50,6 +56,9 @@ CLAUDE_ARGS=(--model opus)
- `GUI=1`: graphical apps open on your desktop (see below).
- `AUDIO=1`: apps can play sound (see below).
- `ROOT=1`: passwordless `sudo` inside the container (see below).
- `PERSIST=1`: keep the container, and system changes, between runs (see below).
- `PACKAGES`: extra Debian packages for this project (see below).
- `MOUNTS`: extra `-v` mounts. A bare path is mounted at the same path. Add `:ro` for read-only.
- `PODMAN_ARGS`: extra `podman run` options.
- `CLAUDE_ARGS`: default arguments for `claude`.
@@ -73,11 +82,46 @@ Both are off by default and work by sharing a single socket from your session.
The image only ships OpenGL drivers, a font and the PulseAudio client. Add the
apps you want to run (and their libraries) to the `apt-get install` line.
## Root access
`ROOT=1` lets Claude (and you, in `claudio shell`) run `sudo` without a
password, for example to `apt-get install` a missing tool. It is off by default:
the image grants passwordless sudo to the `sudo` group, and claudio only adds
you to that group when `ROOT=1`.
- System changes last only as long as the container, which is removed after
every run unless `PERSIST=1` (see below).
- With rootless podman, root in the container is still your unprivileged host
user, so it gets no access to the host beyond what is already mounted. With
rootful podman it is real root (limited by the container's capabilities).
## Keeping system changes
There are two ways, and they combine well:
- `PACKAGES=(python3 nodejs)` builds a per-project image with those packages
on top of the base image (`localhost/claudio:pkgs-<hash>`). It is rebuilt
automatically when the list changes or after `claudio update`, so this is
the place for anything the project always needs. Projects with the same list
share the image.
- `PERSIST=1` keeps one container per project instead of a fresh one each run,
so anything done with `sudo` (or written outside the mounts) is still there
next time. All `claudio` and `claudio shell` sessions in the project share
it, and it is stopped when the last one exits. It is **recreated, losing
those changes**, when the image changes (`claudio update`, a new
`PACKAGES` list) or when the container's options change (`MOUNTS`, `GUI`,
`AUDIO`, `ROOT`, `PODMAN_ARGS`); editing `CLAUDE_ARGS` or comments does not. Run `claudio reset`
to start it over by hand. Background processes do not survive the stop, and
`-e VAR` values in `PODMAN_ARGS` are read when the container is created.
A good habit: let Claude install things ad hoc with `PERSIST=1`, and move the
ones worth keeping into `PACKAGES`.
## State
The container's home (`/home/claude`) lives in the podman volume `claudio-home`.
This volume is shared by all projects and holds your login, settings and history.
The container itself is removed after every run.
The container itself is removed after every run, unless `PERSIST=1`.
- Reset everything: `podman volume rm claudio-home`
- Need more tools in the image? Add them to the `apt-get install` line, then run `claudio update`.