A tool that provides isolated, containerized development environments with seamless Git integration. Run commands in a fresh Docker container with automatic repository setup and cleanup.
- 🐳 Automatic Container Management: Spins up isolated Docker containers on-demand
- 🔄 Git Integration: Clones your repository into the container with bidirectional sync via HTTP server
- 🖥️ Full TTY Support: Interactive terminal with proper size handling and signal forwarding
- 🧹 Automatic Cleanup: Removes containers and stops servers after execution
- 🔐 SSH Agent & Docker Socket Forwarding: Access host SSH keys and Docker daemon from container
- Docker: Must be installed and running
- Git: Required for repository operations
- Go: Version 1.21+ for building from source
git clone https://github.com/ryanmoran/contagent.git
cd contagent
go install .go run . [command] [args...]Start a shell in a containerized environment:
contagent /bin/bashRun a specific command:
contagent go test ./...Execute an AI agent session:
contagent claudecontagent --env CUSTOM_VAR=value --env ANOTHER=test claudecontagent --volume /host/path:/container/path /bin/bashcontagent orchestrates isolated development environments:
-
Session Initialization: Generates a unique session ID (e.g.,
contagent-1234) and branch name (e.g.,contagent/1234) -
Git HTTP Server: Starts a local Git server on the host (random port) to allow the container to pull from and push to your repository
-
Docker Image: Builds a container image from the specified Dockerfile
-
Repository Setup: Creates a tar archive of your Git repository and copies it into the container at
/appwith:- A new branch for the session
- Remote configured to point back to the host Git server
- All tracked files from HEAD (uncommitted changes are ignored)
-
Container Execution: Runs your command with:
- Full TTY support (interactive terminal)
- Automatic terminal resizing
- Signal forwarding (Ctrl+C, etc.)
- Access to host Docker socket and SSH agent
-
Cleanup: After execution or interruption:
- Container is removed (10 second graceful shutdown timeout)
- Git server is stopped
- All resources are cleaned up
Host Machine Container (contagent-1234)
├── Git Repository ├── /app (cloned repo)
├── Git HTTP Server (random port) ←──┤ └── origin → host.docker.internal:port
├── Docker Socket ────────────────────┤ /var/run/docker.sock
└── SSH Agent ────────────────────────┤ /run/host-services/ssh-auth.sock
contagent supports flexible configuration through multiple sources, allowing you to customize behavior at different levels.
Configuration is merged in the following order (later sources override earlier ones):
- Hardcoded defaults
- Global config (
~/.config/contagent/config.yaml) - Project config (
.contagent.yamlin project root) - CLI flags (final override)
Configuration files use YAML format and support all available settings.
Create a .contagent.yaml file in your project root to set project-specific defaults:
# Basic container settings
image: contagent:latest
working_dir: /app
dockerfile: ./Dockerfile
network: default
stop_timeout: 10
tty_retries: 10
retry_delay: 10ms
# Git configuration
git:
user:
name: Contagent
email: contagent@example.com
# Environment variables
# Supports variable expansion using $VAR or ${VAR} syntax
env:
MY_PROJECT_VAR: some_value
MY_PATH: $HOME/bin
USER_DIR: ${HOME}/${USER}
# Volume mounts (HOST_PATH:CONTAINER_PATH)
# Supports variable expansion
volumes:
- $HOME/.cache:/root/.cache
- ./data:/dataSee .contagent.example.yaml for a complete example with all available options.
Create ~/.config/contagent/config.yaml to set user-level defaults that apply across all projects:
git:
user:
name: Your Name
email: your.email@example.com
env:
EDITOR: vimCLI flags override all configuration files:
--image NAME: Container image name--dockerfile PATH: Path to Dockerfile for building image--working-dir PATH: Working directory inside container--network NAME: Docker network to use--stop-timeout SECONDS: Container stop timeout
--tty-retries COUNT: Number of TTY resize retry attempts--retry-delay DURATION: Delay between retries (e.g., "10ms", "100ms")
--git-user-name NAME: Git user name for commits--git-user-email EMAIL: Git user email for commits
--env KEY=VALUE: Add environment variable (can be used multiple times)--volume HOST:CONTAINER: Mount volume (can be used multiple times)
Example:
contagent --env MY_VAR=value --volume /local:/remote --image custom:latest /bin/bashBoth env and volumes sections in configuration files support environment variable expansion:
env:
# Simple expansion
HOME_PATH: $HOME
# Braced expansion
USER_DIR: ${HOME}/${USER}
# Use in volumes
volumes:
- $HOME/.ssh:/root/.ssh
- ${PWD}/data:/dataThe following environment variables are automatically passed through to the container:
TERM: Terminal type (defaults toxterm-256color)COLORTERM: Color support (defaults totruecolor)ANTHROPIC_API_KEY: API key for AI agentsSSH_AUTH_SOCK: SSH agent socket (set to/run/host-services/ssh-auth.sock)
These volumes are always mounted automatically:
/var/run/docker.sock:/var/run/docker.sock: Docker socket for Docker-in-Docker/run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock: SSH agent access
Add custom mounts via configuration files or CLI flags:
Via config file:
volumes:
- ./data:/data
- $HOME/.cache:/root/.cacheVia CLI:
contagent --volume ./data:/data --volume $HOME/.cache:/root/.cache /bin/bashIf no configuration is provided, these defaults are used:
| Setting | Default Value |
|---|---|
image |
contagent:latest |
working_dir |
/app |
network |
default |
stop_timeout |
10 seconds |
tty_retries |
10 |
retry_delay |
10ms |
git.user.name |
Contagent |
git.user.email |
contagent@example.com |
Given:
- Global config sets
git.user.name: "Alice" - Project config sets
git.user.name: "Bob"andimage: "myimage:latest" - CLI flag
--git-user-name Charlie
Result: git.user.name will be "Charlie" and image will be "myimage:latest"
go build -o contagent .Unit tests:
go test ./...Integration tests (requires Docker):
go test -tags integration ./...The container is configured with host.docker.internal:host-gateway extra host mapping, allowing it to reach the host Git server at http://host.docker.internal:<port>.
- Listens on
127.0.0.1:0(random available port) - Uses
git-http-backendCGI for Git protocol support - Requires
GIT_HTTP_EXPORT_ALL=trueto serve repositories - Requires
GIT_HTTP_ALLOW_PUSH=trueto accept pushes from container
- Gracefully handles
SIGINT(Ctrl+C) andSIGTERM - Triggers container shutdown with 10 second timeout
- Ensures cleanup even on interruption
- Terminal restored to normal mode on exit
Run AI agents in an isolated environment with full repository access:
contagent claudeThe container has access to:
- Your repository code and history
- Docker (via socket mount) for running tests/builds
- SSH agent for authenticated Git operations
Test your code in a clean environment:
contagent go test ./...Try risky operations without affecting your local environment:
contagent /bin/bash
# Inside container: experiment freely
# Changes are isolated to the containerTest CI workflows locally in the same container environment:
contagent /bin/bash -c "go build && go test && go vet"MIT License - see LICENSE file for details
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Run the test suite:
go test ./... - Submit a pull request