How It Works¶
This is the real startup model. No mythology.
Short Version¶
deva.sh does five things:
- resolves wrapper config and agent choice
- resolves the config home and auth mode
- builds the Docker mount and env list
- creates or reuses a project-scoped container
docker execs the selected agent inside that container
That is it.
Startup Flow¶
1. Deva parses wrapper args and agent args separately¶
Wrapper flags include things like:
--rm-v-e-c,--config-home-p,--profile-Q,--quick--host-net--no-docker--debug,--dry-run
Everything after -- goes to the agent unchanged.
2. Deva loads config files¶
Config files load in this order:
$XDG_CONFIG_HOME/deva/.deva$HOME/.deva./.deva./.deva.local
Supported directives are simple:
VOLUME=host:container[:mode]ENV=NAME=valueAUTH_METHOD=...PROFILE=...EPHEMERAL=...
See .deva.example.
3. Deva resolves the config home¶
Default per-agent homes live under:
~/.config/deva/
├── claude/
├── codex/
└── gemini/
--config-home supports two layouts:
- leaf home:
DIR/.claude,DIR/.claude.json,DIR/.codex,DIR/.gemini - deva root:
DIR/claude,DIR/codex,DIR/gemini
-Q disables config-home resolution, autolink, and host config mounts entirely.
4. Deva resolves auth¶
Each agent owns its auth modes. The wrapper does not fake a universal auth abstraction because those usually turn into garbage.
Examples:
- Claude default:
.claudeand.claude.json - Claude API-style auth: env vars such as
ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN, orCLAUDE_CODE_OAUTH_TOKEN - Codex default:
.codex/auth.json - Gemini default:
.gemini
When non-default auth is active, deva mounts a blank overlay over the default credential file path so the agent cannot silently fall back to some unrelated OAuth state. That is the point of the overlay fix.
If --auth-with /path/to/file.json is used, that explicit file is mounted directly over the agent's default credential path.
5. Deva builds Docker args¶
The wrapper always mounts:
- the current workspace at the same absolute path
- the current workspace as container working directory
- UID/GID, timezone, locale, and a few useful host envs
It may also mount:
- additional user volumes from
-vor.deva - config-home contents into
/home/deva ~/.config/devaand~/.cache/devawhen using the default config root- project-local
.claudeif present /var/run/docker.sockif present and not disabled
Loose credential files, backup files, .DS_Store, and VCS junk are intentionally skipped during config-home fan-out.
6. Deva creates or reuses a container¶
Persistent is default:
- one default container shape per project
- reused across runs
- same workspace can run Claude, Codex, and Gemini in the same container when mounts, config, and auth line up
- different volumes, explicit config homes, or auth modes create separate persistent containers
Ephemeral with --rm:
- new container every time
- removed after exit
- useful for clean repros or one-shot tasks
Container names include the workspace slug and may also include hashes for:
- extra volumes
- explicit config-home
- auth mode
That prevents collisions between materially different container shapes.
7. Deva execs the agent¶
For persistent mode, the runtime shape is:
docker run -d ... tail -f /dev/nulldocker exec -it ... /usr/local/bin/docker-entrypoint.sh <agent>
For ephemeral mode, it runs the agent directly in docker run.
Agent Defaults¶
- Claude: injects
--dangerously-skip-permissionsunless you already supplied it - Codex: injects
--dangerously-bypass-approvals-and-sandboxand defaults model togpt-5-codex - Gemini: injects
--yolo
This is not subtle. The container is the trust boundary, so the agent's internal approval system is intentionally bypassed.
Proxy and Network Behavior¶
HTTP_PROXYandHTTPS_PROXYare passed throughlocalhostin those proxy URLs is translated tohost.docker.internal--host-netopts into host networking--no-dockerdisables Docker socket auto-mount
If you mount the Docker socket, stop pretending the container is isolated from the host.
Debugging the Runtime Shape¶
Use:
deva.sh --show-config
deva.sh claude --debug --dry-run
deva.sh shell
--dry-run shows the container shape without starting the container. That is good for checking env and mount wiring. It is not a proof that the agent can actually authenticate or complete a request.