Skip to content

Commit e9338ad

Browse files
authored
Merge pull request #389 from thevibeworks/fix/statusline-data-dir-388
fix: stop hard-coding statusline data dir into containers
2 parents 4c6e321 + f7f4c74 commit e9338ad

11 files changed

Lines changed: 307 additions & 290 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Created by https://www.toptal.com/developers/gitignore/api/node
22
# Edit at https://www.toptal.com/developers/gitignore?templates=node
33

4+
.claude/
45
*.bak
56

67
### Node ###

AGENTS.md

Lines changed: 25 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -1,209 +1,25 @@
1-
This file provides guidance to coding agents working in this repository.
2-
3-
## What This Repo Is
4-
5-
`deva.sh` is a Docker-based multi-agent launcher for:
6-
7-
- OpenAI Codex
8-
- Claude Code
9-
- Google Gemini CLI
10-
11-
The container is the sandbox. Agent-level permission theater is not.
12-
13-
That is the core design. Do not "improve" it by moving trust back into
14-
interactive prompt confirmations.
15-
16-
## Workflow Rules
17-
18-
We use issue-based development.
19-
20-
1. Before any Git or GitHub CLI command, read the matching file in
21-
`workflows/`:
22-
- `GITHUB-ISSUE.md`
23-
- `GIT-COMMIT.md`
24-
- `GITHUB-PR.md`
25-
- `RELEASE.md`
26-
2. Keep one branch per issue when practical.
27-
3. PRs should reference and close the relevant issue.
28-
29-
## Release Rules
30-
31-
Release workflow lives in `workflows/RELEASE.md`.
32-
33-
Current release source of truth:
34-
35-
- version comes from `deva.sh`
36-
- changelog comes from `CHANGELOG.md`
37-
- images are published by GitHub Actions
38-
39-
Do not use `claude.sh` as the version source. That is old baggage.
40-
41-
## Project Structure
42-
43-
```text
44-
deva/
45-
├── deva.sh
46-
├── claude.sh
47-
├── claude-yolo
48-
├── agents/
49-
├── Dockerfile
50-
├── Dockerfile.rust
51-
├── docker-entrypoint.sh
52-
├── install.sh
53-
├── .deva.example
54-
├── examples/
55-
├── docs/
56-
├── .github/workflows/
57-
├── workflows/
58-
├── CHANGELOG.md
59-
├── DEV-LOGS.md
60-
└── AGENTS.md
61-
```
62-
63-
Important current roles:
64-
65-
- `deva.sh`: primary entrypoint and container lifecycle manager
66-
- `agents/*.sh`: agent-specific auth and command wiring
67-
- `install.sh`: one-line installer
68-
- `.github/workflows/ci.yml`: lint, docs, and smoke coverage
69-
- `.github/workflows/release.yml`: tagged image + release flow
70-
- `.github/workflows/nightly-images.yml`: scheduled nightly image refresh
71-
72-
Legacy compatibility wrappers still exist:
73-
74-
- `claude.sh`
75-
- `claude-yolo`
76-
77-
They are compatibility shims, not primary branding.
78-
79-
## Security Model
80-
81-
Deva runs agent CLIs inside Docker and disables their built-in permission
82-
prompts:
83-
84-
- Claude: `--dangerously-skip-permissions`
85-
- Gemini: `--yolo`
86-
- Codex: unrestricted mode equivalent
87-
88-
That is deliberate.
89-
90-
The security boundary is:
91-
92-
- the container
93-
- the exact mounts and env vars we pass into it
94-
95-
So the real risks are the host bridges we expose:
96-
97-
- mounted workspace paths
98-
- mounted auth files
99-
- `/var/run/docker.sock`
100-
- `--host-net`
101-
- tmux bridge tooling
102-
103-
Do not document or implement this as if the agent sandbox is protecting the
104-
host. It is not.
105-
106-
## Auth And Config Model
107-
108-
Deva supports multiple auth modes per agent.
109-
110-
Current design:
111-
112-
- default config root is `~/.config/deva`
113-
- per-agent homes live under that root
114-
- `--config-home` isolates auth state
115-
- `-Q` means bare mode: no config loading, no autolink, no host auth mounts
116-
- non-default auth overlays default credential paths instead of moving live
117-
host files around
118-
119-
If you touch auth code, verify real `--dry-run` output and one live path.
120-
Auth bugs are usually mount bugs wearing a fake auth moustache.
121-
122-
## Container Model
123-
124-
Persistent containers are keyed by workspace plus container shape.
125-
126-
Shape includes things like:
127-
128-
- selected agent
129-
- extra volumes
130-
- explicit config home
131-
- auth mode
132-
133-
So it is not "one container per repo" in the naive sense. Different shapes
134-
must not collide.
135-
136-
For clean repros and CI smoke tests, use:
137-
138-
```bash
139-
deva.sh claude -Q -- --version
140-
deva.sh codex -Q -- --version
141-
deva.sh gemini -Q -- --version
142-
```
143-
144-
Non-interactive launch paths must work without a TTY.
145-
146-
## Common Checks
147-
148-
Run these before claiming things work:
149-
150-
```bash
151-
./deva.sh --help
152-
./deva.sh --version
153-
./claude-yolo --help
154-
./scripts/version-check.sh
155-
```
156-
157-
If you changed container launch, mounts, auth, or the installer, also run:
158-
159-
```bash
160-
./deva.sh claude --debug --dry-run
161-
./deva.sh claude -Q -- --version
162-
./deva.sh codex -Q -- --version
163-
./deva.sh gemini -Q -- --version
164-
```
165-
166-
If you changed docs site plumbing, also run:
167-
168-
```bash
169-
mkdocs build --strict
170-
```
171-
172-
## Bridges
173-
174-
Bridges are deliberate holes from container back to host.
175-
176-
Current ones:
177-
178-
- Docker socket mount
179-
- tmux bridge
180-
181-
Treat bridge changes as security-sensitive. They change the real trust
182-
boundary, not some fake marketing boundary.
183-
184-
## Documentation Rules
185-
186-
Public copy should say `deva.sh` first.
187-
188-
Allowed:
189-
190-
- mention `claude.sh` / `claude-yolo` as compatibility wrappers
191-
- historical notes in changelog/dev logs
192-
193-
Not allowed:
194-
195-
- presenting the project as Claude-only
196-
- using `claude.sh` as the primary interface in current docs
197-
- leaving stale release or workflow prompts centered on old naming
198-
199-
## Issue Hygiene
200-
201-
Do not use the issue queue as a mirror of every upstream vendor changelog.
202-
203-
If upstream version tracking is automated, close the old noise and keep the
204-
real issue queue for:
205-
206-
- bugs in deva
207-
- missing features in deva
208-
- docs gaps in deva
209-
- concrete release/process work in deva
1+
@./.claude/CLAUDE.md
2+
@./CLAUDE.md
3+
4+
<!-- deva:container-context -->
5+
# Container Environment (deva)
6+
7+
You are inside a Docker container running Ubuntu Linux 24.04 LTS
8+
(Noble Numbat), not on the host machine. The workspace is a
9+
bind-mount from the host at the same absolute path, but the
10+
runtime is Linux.
11+
12+
- This is Linux. Host-only tools (open, pbcopy, pbpaste, sw_vers,
13+
diskutil, defaults, launchctl) are not available.
14+
- No display server. Browsers and GUI tools will not work.
15+
- Hard links (`ln` without -s) fail across mount boundaries.
16+
Use `cp` or relative symbolic links (`ln -sr`).
17+
- Prefer relative paths for project-internal references.
18+
Absolute paths work here but are container-specific.
19+
- $HOME is /home/deva (not /root). sudo works without password.
20+
- Pre-installed: Node.js, Python (use `uv`, not pip), Go, git,
21+
gh, make, curl. pip is NOT in PATH.
22+
- Docker is available (socket mounted from host).
23+
- System packages and build caches persist across sessions.
24+
- Container details are in DEVA_* environment variables.
25+
<!-- /deva:container-context -->

Dockerfile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,11 @@ RUN --mount=type=cache,target=/tmp/tmux-cache,sharing=locked \
151151
hash -r && \
152152
tmux -V
153153

154-
ENV NPM_CONFIG_FETCH_RETRIES=5 \
154+
ENV NPM_CONFIG_FETCH_RETRIES=2 \
155155
NPM_CONFIG_FETCH_RETRY_FACTOR=2 \
156-
NPM_CONFIG_FETCH_RETRY_MINTIMEOUT=10000
156+
NPM_CONFIG_FETCH_RETRY_MINTIMEOUT=1000 \
157+
NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT=10000 \
158+
NPM_CONFIG_FETCH_TIMEOUT=30000
157159

158160
# Stable agent base: user, shell, and shared runtimes.
159161
# Keep volatile agent package installs out of this stage so downstream

Makefile

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ PLAYWRIGHT_VERSION ?= 1.60.0
4040
RUST_TOOLCHAINS ?= stable
4141
RUST_DEFAULT_TOOLCHAIN ?= stable
4242
RUST_TARGETS ?= wasm32-unknown-unknown
43+
DOCKER_BUILD_EXTRA_ARGS ?=
44+
SKIP_BUILD_NETWORK_CHECK ?= 0
4345

4446
TOOLCHAIN_BUILD_ARGS := \
4547
--build-arg NODE_MAJOR=$(NODE_MAJOR) \
@@ -91,15 +93,26 @@ export VERSION_PINS_FILE
9193

9294
.DEFAULT_GOAL := help
9395

94-
.PHONY: build build-main rebuild build-core build-rust-image build-rust build-all
96+
.PHONY: build build-network-check build-main rebuild build-core build-rust-image build-rust build-all
9597
.PHONY: buildx buildx-multi buildx-multi-rust buildx-multi-local
9698
.PHONY: versions-up versions versions-pin toolchains scripts commands clean clean-all shell test test-rust test-local
9799
.PHONY: info push pull build-test dev context-size lint version-check
98100
.PHONY: release-patch release-minor release-major help
99101

100102
build: build-all
101103

102-
build-main:
104+
build-network-check:
105+
@if [ "$(SKIP_BUILD_NETWORK_CHECK)" = "1" ]; then \
106+
echo "Skipping Docker build network check"; \
107+
else \
108+
echo "Checking Docker build DNS for registry.npmjs.org..."; \
109+
printf '%s\n' \
110+
'FROM node:$(NODE_MAJOR)-bookworm-slim' \
111+
'RUN node -e "require('\''dns'\'').lookup('\''registry.npmjs.org'\'',{all:true},(e,a)=>{if(e){console.error(e);process.exit(1)};console.log(a.map(x=>x.address).slice(0,3).join('\'','\''))})"' \
112+
| docker build $(DOCKER_BUILD_EXTRA_ARGS) --progress=plain --no-cache -f - . >/dev/null; \
113+
fi
114+
115+
build-main: build-network-check
103116
@echo "🔨 Building Docker image with $(DOCKERFILE)..."
104117
@if [ -f "$(VERSION_PINS_FILE)" ]; then \
105118
echo "📌 Using shared defaults from $(VERSION_PINS_FILE)"; \
@@ -136,23 +149,23 @@ build-main:
136149
fi; \
137150
fi
138151
@echo "Hint: override via GO_VERSION=... CLAUDE_CODE_VERSION=... or run 'make versions-pin'"
139-
docker build -f $(DOCKERFILE) $(MAIN_BUILD_ARGS) -t $(MAIN_IMAGE) .
152+
docker build $(DOCKER_BUILD_EXTRA_ARGS) -f $(DOCKERFILE) $(MAIN_BUILD_ARGS) -t $(MAIN_IMAGE) .
140153
@echo "✅ Build completed: $(MAIN_IMAGE)"
141154

142155
rebuild:
143156
@echo "🔨 Rebuilding Docker image (no cache) with $(DOCKERFILE)..."
144-
docker build -f $(DOCKERFILE) --no-cache $(MAIN_BUILD_ARGS) -t $(MAIN_IMAGE) .
157+
docker build $(DOCKER_BUILD_EXTRA_ARGS) -f $(DOCKERFILE) --no-cache $(MAIN_BUILD_ARGS) -t $(MAIN_IMAGE) .
145158
@echo "✅ Rebuild completed: $(MAIN_IMAGE)"
146159

147160

148161
build-core:
149162
@echo "🔨 Building stable core image..."
150-
docker build -f $(DOCKERFILE) --target agent-base $(CORE_BUILD_ARGS) -t $(CORE_IMAGE) .
163+
docker build $(DOCKER_BUILD_EXTRA_ARGS) -f $(DOCKERFILE) --target agent-base $(CORE_BUILD_ARGS) -t $(CORE_IMAGE) .
151164
@echo "✅ Core build completed: $(CORE_IMAGE)"
152165

153-
build-rust-image:
166+
build-rust-image: build-network-check
154167
@echo "🔨 Building Rust Docker image..."
155-
docker build -f $(RUST_DOCKERFILE) \
168+
docker build $(DOCKER_BUILD_EXTRA_ARGS) -f $(RUST_DOCKERFILE) \
156169
--build-arg BASE_IMAGE=$(CORE_IMAGE) \
157170
$(RUST_BUILD_ARGS) \
158171
-t $(RUST_IMAGE) .
@@ -348,6 +361,7 @@ help:
348361
@echo ""
349362
@echo "Available targets:"
350363
@echo " build Build all images with pinned Makefile defaults"
364+
@echo " build-network-check Check Docker build DNS before npm-heavy stages"
351365
@echo " build-core Build stable core image only"
352366
@echo " build-main Build main Docker image only"
353367
@echo " build-rust Build Rust Docker image"

0 commit comments

Comments
 (0)