Skip to content

Commit 6a79ac0

Browse files
authored
Merge pull request #215 from thevibeworks/docs/custom-images
docs: add custom image guide
2 parents 6954c47 + 72604f8 commit 6a79ac0

5 files changed

Lines changed: 206 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ Read these if you want to understand the machinery instead of cargo-culting comm
6868
- [How It Works](docs/how-it-works.md)
6969
- [Philosophy](docs/philosophy.md)
7070
- [Advanced Usage](docs/advanced-usage.md)
71+
- [Custom Images](docs/custom-images.md)
7172
- [Docs Home](docs/index.md)
7273

7374
Project policy and OSS housekeeping:

docs/advanced-usage.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ deva.sh codex -p rust
104104

105105
If the image tag is missing locally, deva pulls it. If that fails and a matching Dockerfile exists, it points you at the build command.
106106

107+
If you want your own image entirely, read [Custom Images](custom-images.md).
108+
That covers local builds, private tags, per-project overrides, and personal-only setups.
109+
107110
## Multi-Agent Workflow
108111

109112
One default container shape can serve all supported agents in the same project:

docs/custom-images.md

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# Custom Images
2+
3+
This is the guide for people who want their own deva image instead of
4+
the stock one.
5+
6+
Common reasons:
7+
8+
- you want extra tools baked in
9+
- you want a personal image in your own registry
10+
- you want local experiments without waiting for upstream releases
11+
12+
That is fine. deva does not care where the image came from. It cares
13+
that the image exists and that the tag you asked for is real.
14+
15+
## The Two Knobs
16+
17+
Deva picks the runtime image from two host-side variables:
18+
19+
- `DEVA_DOCKER_IMAGE`
20+
- `DEVA_DOCKER_TAG`
21+
22+
If you do nothing, it uses:
23+
24+
```text
25+
DEVA_DOCKER_IMAGE=ghcr.io/thevibeworks/deva
26+
DEVA_DOCKER_TAG=latest
27+
```
28+
29+
For the rust profile, the default tag becomes `rust`.
30+
31+
Important detail:
32+
33+
- if you set only `DEVA_DOCKER_IMAGE`, `PROFILE=rust` can still change the
34+
tag to `rust`
35+
- if you want zero surprises, set both `DEVA_DOCKER_IMAGE` and
36+
`DEVA_DOCKER_TAG`
37+
38+
## Build A Local Image
39+
40+
Base image:
41+
42+
```bash
43+
docker build -t deva-local:latest .
44+
```
45+
46+
Rust profile image:
47+
48+
```bash
49+
docker build -f Dockerfile.rust -t deva-local:rust .
50+
```
51+
52+
Then run deva against it:
53+
54+
```bash
55+
DEVA_DOCKER_IMAGE=deva-local \
56+
DEVA_DOCKER_TAG=latest \
57+
deva.sh codex
58+
```
59+
60+
Or for the rust image:
61+
62+
```bash
63+
DEVA_DOCKER_IMAGE=deva-local \
64+
DEVA_DOCKER_TAG=rust \
65+
deva.sh claude
66+
```
67+
68+
Deva checks local images first. If the image is already there, it does
69+
not need to pull anything.
70+
71+
## Build A Personal Registry Image
72+
73+
If you want your own registry namespace, tag it that way from the start:
74+
75+
```bash
76+
docker build -t ghcr.io/yourname/deva:daily .
77+
docker push ghcr.io/yourname/deva:daily
78+
```
79+
80+
Then point deva at it:
81+
82+
```bash
83+
export DEVA_DOCKER_IMAGE=ghcr.io/yourname/deva
84+
export DEVA_DOCKER_TAG=daily
85+
deva.sh codex
86+
```
87+
88+
That is the whole trick. This is not Kubernetes. It is just an image
89+
name plus a tag.
90+
91+
## Keep It Personal
92+
93+
If this is only for you, put the override in `.deva.local`:
94+
95+
```text
96+
DEVA_DOCKER_IMAGE=ghcr.io/yourname/deva
97+
DEVA_DOCKER_TAG=daily
98+
```
99+
100+
That file is the right place for personal registry tags, private images,
101+
and "I am trying weird stuff" experiments.
102+
103+
If the whole team should use the same custom image, put it in `.deva`
104+
instead:
105+
106+
```text
107+
DEVA_DOCKER_IMAGE=ghcr.io/acme/deva
108+
DEVA_DOCKER_TAG=team-rust-20260312
109+
```
110+
111+
Yes, deva's config loader will export those variables for the wrapper.
112+
That is intentional.
113+
114+
## Extend The Official Image Instead Of Starting From Nothing
115+
116+
If you just need a few extra tools, do not rebuild the universe.
117+
118+
Use the published image as your base:
119+
120+
```dockerfile
121+
FROM ghcr.io/thevibeworks/deva:latest
122+
123+
RUN apt-get update && apt-get install -y --no-install-recommends \
124+
graphviz \
125+
postgresql-client \
126+
&& rm -rf /var/lib/apt/lists/*
127+
```
128+
129+
Build and run it:
130+
131+
```bash
132+
docker build -t deva-local:extras .
133+
DEVA_DOCKER_IMAGE=deva-local DEVA_DOCKER_TAG=extras deva.sh gemini
134+
```
135+
136+
That is usually the sane move.
137+
138+
## What Still Comes From The Wrapper
139+
140+
Changing the image does not change the wrapper model.
141+
142+
Deva still controls:
143+
144+
- workspace mounts
145+
- auth mounts
146+
- config-home wiring
147+
- container naming
148+
- persistent vs ephemeral behavior
149+
- debug and dry-run output
150+
151+
So a custom image is not a custom launcher. It is just a different root
152+
filesystem under the same wrapper behavior.
153+
154+
## Personal Use Without Installing Anything Globally
155+
156+
You do not need to replace your whole system install.
157+
158+
Per-shell:
159+
160+
```bash
161+
DEVA_DOCKER_IMAGE=deva-local \
162+
DEVA_DOCKER_TAG=latest \
163+
deva.sh codex
164+
```
165+
166+
Per-project:
167+
168+
```text
169+
# .deva.local
170+
DEVA_DOCKER_IMAGE=deva-local
171+
DEVA_DOCKER_TAG=latest
172+
```
173+
174+
That way your personal image only affects the project where you meant to
175+
use it. Amazing concept.
176+
177+
## Gotchas
178+
179+
- If you set only the image and forget the tag, profile defaults may
180+
still pick `latest` or `rust`.
181+
- If the image is private, pulls need auth. Public docs pointing at a
182+
private image are broken by definition.
183+
- If you build a custom image that removes expected tools or paths,
184+
deva will not magically repair your bad Dockerfile.
185+
- If your image tag does not exist locally and cannot be pulled, deva
186+
fails fast. Good. Silent nonsense would be worse.
187+
188+
## Sanity Check
189+
190+
Use this before blaming the wrapper:
191+
192+
```bash
193+
DEVA_DOCKER_IMAGE=deva-local \
194+
DEVA_DOCKER_TAG=latest \
195+
deva.sh codex --debug --dry-run
196+
```
197+
198+
If the printed image is wrong, your override is wrong.
199+
If the printed image is right, the problem is somewhere else.

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ If you want the internals instead of vague hand-waving:
1919
- [How It Works](how-it-works.md)
2020
- [Philosophy](philosophy.md)
2121
- [Advanced Usage](advanced-usage.md)
22+
- [Custom Images](custom-images.md)
2223

2324
## What This Is
2425

mkdocs.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
site_name: deva.sh docs
2-
site_description: Docker-based multi-agent launcher for Claude, Codex, and Gemini
2+
site_description: Docker-based multi-agent launcher for Codex, Claude, and Gemini
33
site_url: https://docs.deva.sh
44
repo_url: https://github.com/thevibeworks/deva
55
repo_name: thevibeworks/deva
@@ -33,6 +33,7 @@ nav:
3333
- Authentication: authentication.md
3434
- Philosophy: philosophy.md
3535
- Advanced Usage: advanced-usage.md
36+
- Custom Images: custom-images.md
3637
- Troubleshooting: troubleshooting.md
3738
- Research:
3839
- UID/GID Handling: UID-GID-HANDLING-RESEARCH.md

0 commit comments

Comments
 (0)