diff --git a/.github/workflows/nightly-images.yml b/.github/workflows/nightly-images.yml index 72343c6..6b4eb06 100644 --- a/.github/workflows/nightly-images.yml +++ b/.github/workflows/nightly-images.yml @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d2f27a..81e1324 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/DEV-LOGS.md b/DEV-LOGS.md index ad03684..7697a5f 100644 --- a/DEV-LOGS.md +++ b/DEV-LOGS.md @@ -13,6 +13,16 @@ - Minimal markdown markers, no unnecessary formatting, minimal emojis. - Reference issue numbers in the format `#` 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: diff --git a/Dockerfile b/Dockerfile index 662fabd..4308c93 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 \ diff --git a/Dockerfile.rust b/Dockerfile.rust index 3d7bba6..0f80347 100644 --- a/Dockerfile.rust +++ b/Dockerfile.rust @@ -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 && \ diff --git a/README.md b/README.md index e2872d2..d59c447 100644 --- a/README.md +++ b/README.md @@ -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) +AI agents / LLMs: read [llms.txt](llms.txt) — the whole product in one fetch. + 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. diff --git a/deva.sh b/deva.sh index 568d6b7..03e8cd8 100755 --- a/deva.sh +++ b/deva.sh @@ -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] diff --git a/docs/how-it-works.md b/docs/how-it-works.md index 48cc927..085fba1 100644 --- a/docs/how-it-works.md +++ b/docs/how-it-works.md @@ -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`: diff --git a/docs/index.md b/docs/index.md index dc4bb19..0f18986 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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 @@ -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/` diff --git a/docs/llms.txt b/docs/llms.txt new file mode 120000 index 0000000..96c448e --- /dev/null +++ b/docs/llms.txt @@ -0,0 +1 @@ +../llms.txt \ No newline at end of file diff --git a/docs/philosophy.md b/docs/philosophy.md index 515d0ec..81d5e49 100644 --- a/docs/philosophy.md +++ b/docs/philosophy.md @@ -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. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 6acc7d4..e88a41a 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -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: @@ -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. diff --git a/install.sh b/install.sh index fe07b88..ec910d5 100644 --- a/install.sh +++ b/install.sh @@ -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" diff --git a/llms.txt b/llms.txt new file mode 100644 index 0000000..665d57a --- /dev/null +++ b/llms.txt @@ -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 diff --git a/mkdocs.yml b/mkdocs.yml index 2b38701..7657d97 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -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