Skip to content

About

A reproducible, multi-architecture development environment built for agent-driven software development.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

677 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

agent-devcontainer

A reproducible, multi-architecture development environment built for agent-driven software development.

agent-devcontainer combines a ready-to-use container image, a plugin catalog for Claude Code and OpenCode, project-memory workflows, automated pull-request review, validation tooling, and reusable scaffolding for adopting the environment in other repositories.

What you get

  • Multi-architecture linux/amd64 and linux/arm64 images published through GHCR.
  • Python development through uv, plus Bun and Node.js 24.
  • A supervised nested Docker engine, Buildx, Compose, CMake, Ninja, Git LFS, and GitHub CLI.
  • Claude Code and OpenCode preinstalled with the shared agentdev catalog.
  • An optional self-improve plugin that turns verified corrections into reviewable instructions, published but not enabled by default.
  • A browser-accessible Xpra desktop with VirtualGL support.
  • An optional default-deny egress firewall with repository-controlled allowlisting.
  • IWE knowledge-graph workflows from project setup through verified shipment.
  • GitHub Actions for validation, formatting, image publishing, and AI review.
  • A resumable template workflow for adopting or updating the environment elsewhere.

The repository publishes four images:

  • ghcr.io/plume-works/agentdev-devcontainer:edge — the Dev Container runtime: tools, the staged catalog, supervised services, and the lifecycle commands.
  • ghcr.io/plume-works/agentdev-deploy:edge — a self-starting single-project OpenCode runtime; see Standalone OpenCode runtime.
  • ghcr.io/plume-works/agentdev-base:edge — the lifecycle-neutral base both runtimes derive from, for custom images that bring their own runtime.
  • ghcr.io/plume-works/ubuntu-ansible:edge — the Ansible-ready base image.

All are built on native runners and merged into multi-architecture manifests. The two runtimes are built from the same run's agentdev-base digest, and edge moves only after both pass native acceptance. The agent-desktop and agent-opencode names are no longer published; /agentdev:template-consume update mode migrates a repository that still pins agent-desktop.

Quick start

There are three supported adoption paths, all on the same published runtime.

Use the image

Point an existing devcontainer at the published image:

// .devcontainer/devcontainer.json
{
  "image": "ghcr.io/plume-works/agentdev-devcontainer:edge@sha256:dddd993a4ba9d09b0c05e452d9ccdd56ab261b3454a16826cf3a72fb47e1e12c",
  "containerEnv": {
    "DEV_WORKSPACE_FOLDER": "/workspaces/${localWorkspaceFolderBasename}",
  },
}

The image's metadata supplies the create, start, and attach commands, waitFor, the privileged mode and /var/lib/docker volume nested Docker needs, and its entrypoint starts the supervised services. Declare none of them again, add no Docker-in-Docker Feature, and copy no lifecycle script; the editor attaches only once the required services are ready.

Pin by tag and digest so the environment never changes silently. Renovate or an equivalent dependency updater can advance the digest when a new image is available; this repository's Renovate configuration provides a working example.

Derive a custom image

Add tooling in an image that starts FROM ghcr.io/plume-works/agentdev-devcontainer. Extend the lifecycle with executable hooks in /etc/agentdev/hooks/{created,started,attached}.d/, which run in name order at the end of their phase, and override the image's documented environment. Files below /opt/agentdev-runtime/ belong to the image: the runtime refuses to start when one is changed, added, or removed. See Dev Container runtime.

Adopt the complete template

Run /agentdev:template-consume to copy the complete setup or merge selected parts into an existing repository. The workflow installs the devcontainer descriptor, agent settings, project tooling, and adaptable GitHub workflows. It also records the adopted revision so future runs can safely propose upstream updates.

Template adoption is resumable, preserves settled choices, and never overwrites consumer-authored IWE knowledge. See the template consumption guide for prerequisites and the full-copy and selective-copy workflows.

Standalone OpenCode runtime

agentdev-deploy runs one project with no Dev Containers client, Coder, or project scaffolding. On start it creates its runtime account, prepares the workspace, and starts the OpenCode server, with nested Docker, an instance-local keyring, Codebase Memory MCP, and the Xpra desktop around it. Each service is supervised and recovered within a bounded budget. Claude Code is installed and configured but not started.

Launch

Deploying agentdev-deploy walks a new host through the proxy network, settings, first start, proxy routes, logins, and continuity checks. The supported deployment is compose.opencode.yml behind an existing reverse proxy. It publishes no host ports. Every launch adds the digest pin in opencode-compose-pins.yml, which Renovate advances to each digest CI promotes to edge; CI promotes only builds that passed native acceptance. Settings come from a private copy of docker/deploy/runtime.env.example:

# First start clones AGENTDEV_REPOSITORY_URL into a persistent workspace volume.
docker compose -p myproject --env-file ~/secrets/myproject.env \
  -f compose.opencode.yml -f opencode-compose-pins.yml up -d

# Or mount a host checkout (AGENTDEV_CHECKOUT) at the same in-container path.
docker compose -p myproject --env-file ~/secrets/myproject.env \
  -f compose.opencode.yml -f opencode-compose-pins.yml -f compose.opencode.bind.yml up -d

The project name (-p) scopes the instance's volumes. A clone-mode workspace is cloned once and then reused; the runtime never fetches, pulls, resets, or switches branches. A bind-mounted worktree also needs its main repository's .git mounted at the path its .git file names.

Proxy, password, and logins

  • OPENCODE_SERVER_PASSWORD is required. The proxy routes to the container on port 4096 for OpenCode, which enforces the password itself, and on 14500 for Xpra. Both are served at the root path, WebSockets included.
  • XPRA_PASSWORD is required unless AGENTDEV_SKIP_XPRA is set; without it the runtime latches failed before starting anything. Xpra checks it on every session, so a peer on the proxy network cannot bypass the proxy. The HTML5 page loads without it and asks for it on connect.
  • AGENTDEV_PROXY_NETWORK names the proxy's existing Docker network.
  • Claude Code logins live on the shared AGENTDEV_AUTH_VOLUME and reach every project container in the same identity cohort. Each project container logs in to OpenCode once: its logins share a database with its sessions in the instance home volume, and survive replacement and upgrade there. Sessions, configuration, keyrings, caches, and Docker engines stay per instance.
  • GitHub access uses an injected GH_TOKEN or GITHUB_TOKEN, which configures HTTPS Git through gh before a private clone. The token is never written to disk. GIT_AUTHOR_* and GIT_COMMITTER_* pass through only when set.

Identity and storage

Tools run as agent with passwordless sudo, using numeric IDs from AGENTDEV_UID/AGENTDEV_GID (default 1000:1000). Every container sharing one auth volume must use the same IDs; a container with other IDs latches failed rather than change the volume. A bind-mounted checkout must be writable by those IDs, and its ownership is never changed.

Path Volume Holds
/workspaces/project workspace or the bind The checkout
/home/agent home Configuration, OpenCode logins, sessions, keyring, CBM
/uv uv uv cache, Python installs, project venv
/var/lib/docker docker The nested engine, including its image store
/var/lib/agentdev/auth agentdev-opencode-auth Shared Claude Code logins

Back up home, workspace, and the auth volume to keep an instance's state; uv and docker can be rebuilt. Removing the container keeps every volume. docker compose down -v also deletes the shared auth volume, so remove a single project's state by name instead, for example docker volume rm myproject_home myproject_uv.

Startup and failures

The core path is the root bootstrap (account, volumes, and the opt-in firewall), the session bus and keyring, then the core phase (checkout, the Claude credential links, agent policy), then OpenCode. Everything else is optional work:

  • before OpenCode, which reads them when it starts: catalog registration, the Codebase Memory MCP client configuration, and the CBM daemon its MCP client connects to;
  • beside OpenCode: Xpra, which neither waits for OpenCode nor delays it;
  • after OpenCode: nested Docker and its image prune, uv sync, pre-commit hook registration, and a background index request.

Hook environments build on first use rather than at startup. The index request returns once CBM accepts the job, and the daemon indexes in the background, so a large workspace never delays startup.

The runtime reports one state:

  • pending while startup or a recovery runs;
  • ready when everything is up;
  • degraded when optional work failed or exhausted its recovery budget. OpenCode keeps serving.
  • failed when the bootstrap, a configuration check, the core phase, or a core service failed. The runtime is latched: PID 1 stays up, nothing restarts or reruns, and OpenCode is stopped. Docker's restart policy never reruns preparation.

AGENTDEV_STRICT_STARTUP=true treats any optional failure as a core one. The container exits nonzero, and Docker restarts it, only when the supervisor's own controller or supervisord fails.

Operating it

  • docker logs carries every service's output. The image healthcheck reports healthy only while a live controller reports ready and the core probes pass; pending, degraded, and failed all report unhealthy.
  • docker exec <container> agentdev-runtime health status prints the state, each failed or blocked component, the last failure record, and the retry command for each failure.
  • Every failure writes ~/.local/state/agentdev/last-failure.json on the home volume: the start's ID, the component, its command and exit status, the last 200 lines of its output, and the time. A later start never deletes it; only a later failure replaces it. A failure before the home volume is checked, such as an invalid setting or a failed bootstrap, goes to docker logs only.
  • After fixing the cause, docker exec <container> agentdev-runtime supervisor retry resumes a latched runtime from the failed component in the same container, and retry <component> reruns one failed optional component. The usual causes are an unwritable checkout, an auth volume from another identity, a missing worktree .git, or a failed project setup.
  • docker exec <container> supervisorctl -c /etc/agentdev/supervisord.conf status lists the services. docker exec -u agent -it <container> bash gives a shell with the same Docker, keyring, and display environment OpenCode's tools see.
  • To upgrade, advance the pin and run the same up -d. The new image reapplies its managed client and catalog configuration and keeps user settings and sessions.
  • AGENTDEV_SKIP_XPRA=1 drops the desktop. The egress firewall stays off unless ENABLE_FIREWALL=true, which applies the default-deny policy and then needs AGENTDEV_TRUSTED_PROXY_CIDRS.
  • Booleans, ENABLE_FIREWALL included, accept 1, true, yes, or on, and 0, false, no, off, or empty. Counts and deadlines must be positive. Any other value latches a configuration failure naming the variable.

Development environment

Area Included tools and capabilities
Python uv, system Python, and pre-commit
JavaScript Bun, Node.js 24, and Yarn
Agents Claude Code, OpenCode, MCP Inspector, and Codebase Memory MCP
Build tooling build-essential, Kitware CMake, Ninja, and pkg-config
Quality Ruff, ShellCheck, Zizmor, Ansible Lint, Prettier, Hadolint, Gitleaks, and Actionlint
GitHub Git, Git LFS, gh, and a transparent host-token wrapper
Containers Docker CE, Buildx, and Compose
Desktop Xpra with its HTML5 client, VirtualGL, Mesa, and Xvfb
Credentials Headless GNOME Keyring and shared agent authentication
Security An opt-in egress firewall with an allowlist and startup checks

Python commands run through uv run. Python environments, agent state, Codebase Memory data, and pre-commit environments persist across container rebuilds and remain isolated per worktree. Authentication is shared so opening another worktree does not require signing in again.

Upgrading from an image with Codex

Earlier images also shipped Codex. Claude Code and OpenCode are now the only supported harnesses, so an existing devcontainer's agentdev-codex volume and the codex/auth.json file on the shared auth volume are no longer used. Nothing removes them; delete them by hand once you no longer need them:

# A devcontainer's per-instance Codex volume
docker volume rm <project>_agentdev-codex
# The Codex login on the devcontainer's shared auth volume
docker run --rm -v agentdev-agents-auth:/auth busybox rm -rf /auth/codex
# The Codex login on an agentdev-deploy auth volume
docker run --rm -v "${AGENTDEV_AUTH_VOLUME:-agentdev-opencode-auth}":/auth busybox rm -rf /auth/codex

The plugin catalog

The repository is its own plugin marketplace. Claude Code sees two plugins, agentdev and self-improve; OpenCode loads agentdev through the bridge plugin it ships.

agentdev

The image carries agentdev 5.0.0, a cross-agent plugin with 37 skills and five agent definitions for Claude Code and OpenCode. It covers:

  • Git commits, branch updates, merges, and conflict resolution.
  • Pull-request creation, synchronization, review, feedback resolution, and merging.
  • GitHub Actions and CodeQL diagnostics.
  • Formatting, linting, and semantic-refactor auditing.
  • Agent and skill authoring.
  • Docker-backed execution through the project devcontainer.
  • Template adoption and updates.
  • The complete IWE project-memory workflow.

The catalog is installed during image construction. The devcontainer lifecycle installs it again after persistent agent volumes mount and refreshes a repository's workspace copy on editor attachment.

Skills use the /agentdev:<name> namespace, including /agentdev:pr-open, /agentdev:pr-review, and /agentdev:pr-merge. See the catalog README for the complete skill list, standalone installation instructions, and contributor guidance.

self-improve

self-improve 0.1.1 is a hook-driven experiential-learning engine for Claude Code. It captures turns, applies a deterministic gate to decide when a lesson is worth a review, runs an isolated reviewer that holds no tools, and proposes edits to CLAUDE.md, rules, and skills. Every mutation is authorized by the user against exact bytes, targets a normative path allowlist, and is reversible. Its four skills are /self-improve:improve, apply, reject, and rollback.

The plugin is published from the Claude marketplace and not enabled by anything this repository ships: the tracked agent settings name it nowhere, and the Ansible catalog role stages agentdev alone. Enable it deliberately, per session or per project.

Its runtime is standard-library-only — a rule enforced by a test that walks every runtime import — so the plugin adds no dependency to a consuming project. Tests that drive a real Claude session and spend model usage are skipped at collection unless SELF_IMPROVE_RUN_LIVE is set; the root Makefile carries those live targets. Behavior is specified in the learning-loop spec, and the comparative analysis behind it is in docs/research/.

IWE project memory

IWE stores product context, architecture, specifications, plans, and releases as a Markdown knowledge graph. The catalog provides a complete workflow:

Skill Purpose
iwe-setup Onboard an existing project and establish its product context.
iwe-explore Investigate ideas or GitHub issues without changing code.
iwe-plan Plan work with verified anchors and risk-scaled specification impact.
iwe-capture File complete, deduplicated bugs, proposed features, and tasks.
iwe-implement Execute plans task by task and record evidence.
iwe-branch-name Name a plan's next implementation or shipping branch.
iwe-verify Check implementation claims against code and specifications.
iwe-ship Block CRITICAL findings and record released behavior.
iwe-weekly Summarize project status and graph health.
iwe-audit Keep durable documents free of session residue.
iwe-implement-all/iwe-ship-all Process all eligible plans in sequence.

Plan checkboxes carry traceable evidence, and behavior-changing plans state their intended contract before implementation. Machine-managed dependency pins can be masked from map freshness checks without hiding structural source changes.

Consumers adopting IWE receive a schema-valid seed without inheriting this publisher repository's project knowledge.

Pull-request automation

The optional ai-responder.yml workflow performs Claude-powered reviews and handles authorized @claude tasks. Its merge gate stays pending while review runs and requires an accepted AI review.

Security gates prevent the responder from checking out or executing untrusted fork code and restrict task execution to actors with write access. Reviews use the pull request branch's own catalog, so changes to agent workflows are reviewed as changed. To request another review after new work lands, remove the pull request's author as assignee and add them back.

Adopters must configure the CLAUDE_CODE_OAUTH_TOKEN repository secret and the claude-review environment before enabling the workflow.

Pull-request descriptions separate completed Verification evidence from open Reviewer Handoff tasks. Repository-specific additions belong in .github/pr-description-guidance.md.

Validation and quality

validate_agent_files 1.0.0 validates agents, skills, prompts, plugin manifests, marketplace metadata, references, and plugin layout. Repository discovery respects .gitignore, while explicitly named files remain directly validatable. --recommend enables warning-level guidance and --errors-only suppresses it.

Pre-commit is the single lint and formatting gate: CI runs the same hooks in the pinned devcontainer image, alongside the validator suites, knowledge-base gates, and image builds.

Firewall and desktop

The firewall is installed but disabled by default. Enable it and edit the allowlist:

// .devcontainer/devcontainer.json
"containerEnv": { "ENABLE_FIREWALL": "true" }

Rules come from .devcontainer/firewall-allowlist.txt. When enabled, the firewall default-denies IPv4 egress, blocks IPv6, preserves Docker DNS, and verifies both an allowed and a blocked destination during startup.

The supplied devcontainer runs in privileged mode for nested Docker and optional GPU access. Use it only with trusted repositories and container contents.

Xpra starts on display :100 and container port 14500. Open the Xpra HTML5 entry in VS Code's Ports panel to reach the desktop; concurrent worktrees receive distinct local ports. Prefix graphical applications with vglrun for GPU acceleration. Advanced users can manage the service with agentdev-runtime xpra --background, --stop, or --port <n>.

Build and contribute

Build the images from the repository root:

docker build -t local/ubuntu-ansible docker/ansible

docker buildx build \
  -f docker/base/agentdev-base.Dockerfile \
  --build-arg FROM_IMAGE=local/ubuntu-ansible \
  -t local/agentdev-base .

docker buildx build \
  -f docker/devcontainer/agentdev-devcontainer.Dockerfile \
  --build-arg FROM_IMAGE=local/agentdev-base \
  -t local/agentdev-devcontainer .

docker/deploy/agentdev-deploy.Dockerfile builds agentdev-deploy the same way.

Install dependencies and run the primary repository checks:

uv sync --all-groups
uv run validate_agent_files --recommend . --require-marketplace claude
uv run pytest
uv run ansible-lint ansible
uv run ansible-playbook --syntax-check ansible/playbooks/setup-dev.yml

The independently released validator must also pass outside the publisher project:

cd py_packages/validate_agent_files
uv run --isolated --extra dev pytest

The canonical plugin sources are .agents/plugins/agentdev/ and .agents/plugins/self-improve/. Repository conventions live in AGENTS.md, while the template boundary classifies the reusable, customizable, and publisher-only parts of the tree.

License

MIT — see LICENSE.

About

A reproducible, multi-architecture development environment built for agent-driven software development.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages