Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion .github/workflows/nightly-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,43 @@ jobs:
RUST_DEFAULT_TOOLCHAIN=${{ needs.load-version-pins.outputs.rust_default_toolchain }}
RUST_TARGETS=${{ needs.load-version-pins.outputs.rust_targets }}

verify:
name: Verify Published Manifests
needs: [resolve-versions, build-base, build-rust]
runs-on: ubuntu-latest
steps:
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Outcome tripwire: assert the artifacts exist, not that the build
# steps exited 0. A green run with an unpullable tag is a lie.
# Small retry absorbs registry eventual-consistency right after push —
# a tripwire that itself flakes trains people to ignore red.
- name: Assert all nightly tags resolve
run: |
set -euo pipefail
image="${REGISTRY}/${IMAGE_NAME}"
stamp="${{ needs.resolve-versions.outputs.stamp }}"
for tag in nightly "nightly-${stamp}" nightly-rust "nightly-${stamp}-rust"; do
for attempt in 1 2 3; do
if docker manifest inspect "${image}:${tag}" >/dev/null; then
echo "ok: ${tag}"
continue 2
fi
echo "attempt ${attempt} failed for ${tag}; retrying in 10s" >&2
sleep 10
done
echo "error: ${image}:${tag} does not resolve after push" >&2
exit 1
done

summary:
name: Nightly Summary
needs: [resolve-versions, build-base, build-rust]
needs: [resolve-versions, verify]
runs-on: ubuntu-latest
steps:
- name: Publish summary
Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`GROK_CLI_VERSION` in `versions.env`, label
`org.opencontainers.image.grok_cli_version`, wired through make/CI/
nightly/release version plumbing
- Proxy-aware builds and version resolution (#407): host
`HTTP(S)_PROXY` forwarded to `docker build` via BuildKit predefined
ARGs with localhost (and authenticated `user:pass@localhost`) proxies
rewritten to `host.docker.internal` plus an explicit
`--add-host host.docker.internal:host-gateway` mapping for native
Linux Engine; npm version
resolution goes straight to registry.npmjs.org instead of honoring
`.npmrc` mirror overrides, degrading to warn-and-fallback on registry
outages; proxy credentials are redacted from all build/version logs
- `llms.txt` (#409): agent-legible repo front door — what deva is, the
four agents, install, and curated docs entry points in one fetch

### Fixed
- Three-agent drift (#409): docs site front page, mkdocs description,
and `deva.sh --help` all said Codex/Claude/Gemini after Grok shipped
- Nightly image builds retry apt fetches (`Acquire::Retries 3`) instead
of dying on transient mirror syncs, and the workflow now asserts all
four published nightly manifests actually resolve — a green run with
an unpullable tag is a lie (#409)

## [0.13.0] - 2026-07-07

Expand Down
10 changes: 10 additions & 0 deletions DEV-LOGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@
- Minimal markdown markers, no unnecessary formatting, minimal emojis.
- Reference issue numbers in the format `#<issue-number>` for easy linking.

# [2026-07-10] Dev Log: repo surface burnish #409
- Why: product ships four agents but half the storefront said three; agents visiting the repo had no llms.txt; nightly 2026-07-09 failed on a transient ubuntu mirror sync and partially published (base pushed, rust did not — nightly/nightly-rust tags diverged a day)
- What:
- drift kill: docs/index.md tagline + agent list, mkdocs site_description, deva.sh --help header now say four agents
- llms.txt at repo root per the agent-surface pattern: blockquote identity, distribution forms, install, curated docs entry points; README grew a one-line agent pointer
- Dockerfile + Dockerfile.rust: apt Acquire::Retries=3 (the exact 07-09 failure mode); nightly-images.yml grew a verify job that docker-manifest-inspects all four published tags — assert the artifact, not the exit code
- repo settings (not in this PR): description/topics/homepage updated for grok + discovery keywords
- Result: no three-agent phrasing left outside history; an agent can recommend + install deva from one fetch of llms.txt; nightly flakes retry and a push that produces no pullable manifest goes red
- Deferred: 9 stale remote branches all carry unique commits — need human triage; v0.14.0 release is ripe (grok + proxy work sitting in Unreleased)

# [2026-07-09] Dev Log: add grok agent (official xAI Grok CLI) #403
- Why: xAI shipped an official coding-agent CLI (x.ai/cli, npm @xai-official/grok); deva should launch it like claude/codex/gemini. Not to be confused with community superagent-ai/grok-cli (npm grok-dev) — different product, same bin name.
- What:
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
rm -f /etc/apt/apt.conf.d/docker-clean && \
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache && \
echo 'Acquire::Retries "3";' > /etc/apt/apt.conf.d/80-retries && \
apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates curl wget git git-lfs gnupg lsb-release locales tzdata sudo \
Expand Down
4 changes: 4 additions & 0 deletions Dockerfile.rust
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ ENV RUSTUP_HOME=/opt/rustup \

USER root

# Transient mirror flakes ("Mirror sync in progress") killed the 2026-07-09
# nightly; retry instead of failing the whole multi-arch build on one 404.
RUN echo 'Acquire::Retries "3";' > /etc/apt/apt.conf.d/80-retries

RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
[![Container](https://img.shields.io/badge/ghcr.io-thevibeworks%2Fdeva-blue)](https://github.com/thevibeworks/deva/pkgs/container/deva)
[![Agents](https://img.shields.io/badge/agents-codex%20%7C%20claude%20%7C%20gemini%20%7C%20grok-222222)](#what-this-is)

<sub>AI agents / LLMs: read [llms.txt](llms.txt) — the whole product in one fetch.</sub>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested against GitHub's actual renderer (repos/.../readme?ref=chore/burnish-409 with Accept: application/vnd.github.html): the line renders as <sub>AI agents / LLMs: read <a href="llms.txt">llms.txt</a> — …</sub> — a real link. Markdown parsing is only suppressed inside block-level HTML; <sub> is span-level. No change.


Run Codex, Claude Code, Gemini, and Grok inside Docker without pretending the agent's own sandbox is the thing keeping you safe.

The container is the sandbox. Explicit mounts are the contract. Persistent project containers keep the workflow fast instead of rebuilding the same state every run.
Expand Down
2 changes: 1 addition & 1 deletion deva.sh
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ _step() {

usage() {
cat <<'USAGE'
deva.sh - Docker-based multi-agent launcher (Claude, Codex, Gemini)
deva.sh - Docker-based multi-agent launcher (Claude, Codex, Gemini, Grok)

Usage:
deva.sh [deva flags] [agent] [-- agent-flags]
Expand Down
2 changes: 1 addition & 1 deletion docs/how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ 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
- same workspace can run Claude, Codex, Gemini, and Grok 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`:
Expand Down
6 changes: 3 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# deva.sh

Run Codex, Claude Code, and Gemini inside Docker without pretending the
agent's own sandbox is the thing keeping you safe.
Run Codex, Claude Code, Gemini, and Grok inside Docker without pretending
the agent's own sandbox is the thing keeping you safe.

The container is the sandbox. Explicit mounts are the contract.
Persistent project containers keep the workflow fast instead of
Expand All @@ -24,7 +24,7 @@ If you want the internals instead of vague hand-waving:

## What This Is

- a Docker-based launcher for Codex, Claude, and Gemini
- a Docker-based launcher for Codex, Claude, Gemini, and Grok
- one warm default container shape per project by default
- explicit mount and env wiring instead of mystery behavior
- per-agent config homes under `~/.config/deva/`
Expand Down
1 change: 1 addition & 0 deletions docs/llms.txt
2 changes: 1 addition & 1 deletion docs/philosophy.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Persistent per-project containers mean:

- warm package caches
- stateful shell history and scratch space
- fast switching between Claude, Codex, and Gemini
- fast switching between Claude, Codex, Gemini, and Grok

`--rm` still exists. It just is not the default because the default should serve real work instead of screenshots.

Expand Down
18 changes: 17 additions & 1 deletion docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ If the dry-run shape is correct but the agent still cannot authenticate, the wra

Symptom:

- first run warns that `.claude`, `.codex`, or `.gemini` is empty
- first run warns that `.claude`, `.codex`, `.gemini`, or `.grok` is empty

Meaning:

Expand All @@ -93,6 +93,22 @@ Meaning:

That is not an error. That is exactly what isolated config homes are for.

## Grok Wants A Browser The Container Does Not Have

Symptom:

- first `deva.sh grok` run tries to open a browser for OAuth and cannot

Fix, either one:

- run `grok login --device-auth` inside the session — it prints a URL and
a code you complete on any device
- authenticate once on the host; deva's autolink carries
`~/.grok/auth.json` into the container

Details, including api-key mode and why in-container `grok update`
cannot touch your host install: [Authentication](authentication.md).

## Proxy Weirdness

Deva rewrites `localhost` in `HTTP_PROXY` and `HTTPS_PROXY` to `host.docker.internal` for the container path.
Expand Down
1 change: 1 addition & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ echo " 3. Run one of:"
echo " deva.sh codex"
echo " deva.sh claude -- --help"
echo " deva.sh gemini -- --help"
echo " deva.sh grok -- --help"
echo " deva.sh shell"
echo ""
echo "warning: do not point deva at your real home directory with dangerous permissions enabled"
43 changes: 43 additions & 0 deletions llms.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# deva.sh

> Docker-first launcher for AI coding agents — Claude Code, Codex, Gemini, and Grok.
> The container is the sandbox, mounts are the explicit contract, and one warm
> project container serves all four agents. A bash script, not a framework. MIT.

deva.sh is a single entry point installed on the host; agents run inside
`ghcr.io/thevibeworks/deva` images (`:latest`, `:rust` for stable, `:nightly`,
`:nightly-rust` refreshed daily). Agent-level permission prompts are disabled
by design — isolation comes from Docker, not permission theater:
`claude --dangerously-skip-permissions`,
`codex --dangerously-bypass-approvals-and-sandbox`,
`gemini --yolo`, and `grok --always-approve`. Auth
lives in per-agent config homes under `~/.config/deva/` with OAuth (default) or
API-key modes per agent; nothing crosses the host boundary except what you
mount. Known sharp edge: mounting `/var/run/docker.sock` is host-root with
extra steps, and deva will tell you so.

Full docs: https://docs.deva.sh — if you can fetch one URL, fetch that one.

## Install

```bash
curl -fsSL https://raw.githubusercontent.com/thevibeworks/deva/main/install.sh | bash

cd your-project
deva.sh # Claude Code (the default)
deva.sh codex # same container shape, other agents
deva.sh gemini
deva.sh grok
deva.sh claude --debug --dry-run # inspect the docker run before trusting it
```

## Entry points

- [Quick Start](https://docs.deva.sh/quick-start/): install to first agent run, about 60 seconds
- [Authentication](https://docs.deva.sh/authentication/): OAuth vs API-key per agent, config homes, auth isolation, what gets masked and why
- [How It Works](https://docs.deva.sh/how-it-works/): container lifecycle, mount dispatch, config resolution order
- [Advanced Usage](https://docs.deva.sh/advanced-usage/): extra mounts, env wiring, multiple identities per project
- [Troubleshooting](https://docs.deva.sh/troubleshooting/): common failures and how to diagnose them
- [Philosophy](https://docs.deva.sh/philosophy/): why the container is the sandbox and agent permission prompts are theater
- [Custom Images](https://docs.deva.sh/custom-images/): extending the base image for your stack
- [Security Policy](https://github.com/thevibeworks/deva/blob/main/SECURITY.md): what deva protects against and what it explicitly does not
2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
site_name: deva.sh docs
site_description: Docker-based multi-agent launcher for Codex, Claude, and Gemini
site_description: Docker-first launcher for Claude Code, Codex, Gemini, and Grok — the container is the sandbox
site_url: https://docs.deva.sh
repo_url: https://github.com/thevibeworks/deva
repo_name: thevibeworks/deva
Expand Down
Loading