Build on-demand Docker containers for projects + agentic coding using mise.
- Docker (installed and running)
- Go 1.21+ (for building from source)
- Bash or Zsh shell
ghCLI (required for GitHub Copilot provider only)
brew install mheap/tap/agent-en-placegit clone https://github.com/mheap/agent-en-place
cd agent-en-place
go build
# Move binary to your PATH
mv agent-en-place /usr/local/bin/Download the latest release for your platform from GitHub Releases.
Define a function in your .bashrc / .zshrc / other shell config file
function vibe() { bash -lc "$(agent-en-place $1)" }Then in any directory, run vibe <provider>
The tool will:
- Detect tool versions from your project's configuration files
- Build a Docker image with those tools (or reuse cached image)
- Generate and execute a
docker runcommand - Launch the selected AI coding tool in the container
agent-en-place can be customized via YAML configuration files. See docs/config.md for the full configuration reference.
Configuration files are loaded and merged in order (later files override earlier):
- Embedded defaults - Built into the binary
- User config -
~/.config/agent-en-place.yaml - Project config -
./.agent-en-place.yaml - Explicit config -
--config <path>
Add a custom agent (~/.config/agent-en-place.yaml):
agents:
aider:
packageName: pipx:aider-chat
command: aider --yes
configDir: .aider
envVars:
- OPENAI_API_KEY
depends:
- pythonagent-en-place automatically detects tool versions from project configuration files:
.tool-versions (asdf/mise format)
node 20.11.0
python 3.12.0
ruby 3.3.0
mise.toml (mise native format)
[tools]
node = "20.11.0"
python = "3.12.0"When you provide a mise.toml, agent-en-place will:
- Copy your
mise.tomlunchanged into the container - Generate a separate
mise.agent.tomlwith agent requirements (excluding tools you've already defined) - Run both
mise install(for your tools) andmise install --env agent(for agent tools)
This means your tool versions always take precedence over agent defaults. If you specify node = "20.11.0" in your mise.toml, that version will be used instead of the agent's default latest.
Idiomatic version files are also recognized:
| File | Language | Example |
|---|---|---|
.nvmrc |
Node.js | 20.11.0 |
.node-version |
Node.js | 20.11.0 |
.python-version |
Python | 3.12.0 |
.ruby-version |
Ruby | 3.3.0 |
Gemfile |
Ruby | ruby "3.3.0" |
.go-version |
Go | 1.21.0 |
.java-version |
Java | 17 |
.sdkmanrc |
Java | java=17.0.2 |
.crystal-version |
Crystal | 1.10.0 |
.exenv-version |
Elixir | 1.15.0 |
.yvmrc |
Yarn | 1.22.19 |
.bun-version |
Bun | 1.0.0 |
Note: Node.js is automatically included if not specified, as it's required by all supported AI coding tools.
Currently supported providers:
- Package:
@anthropic-ai/claude-code - Command:
claude --dangerously-skip-permissions - Requirements: None
- Configuration: Stored in
~/.claudeand~/.claude.json - Environment: Uses
ANTHROPIC_API_KEYif set, or OAuth credentials from config
- Package:
@openai/codex - Command:
codex --dangerously-bypass-approvals-and-sandbox - Requirements: None
- Configuration: Stored in
~/.codex
- Package:
opencode-ai - Command:
opencode - Requirements: None
- Configuration: Stored in
~/.config/opencode/and~/.local/share/opencode/
- Package:
@github/copilot - Command:
copilot --allow-all-tools --allow-all-paths --allow-all-urls - Requirements:
ghCLI authenticated withgh auth login - Configuration: Stored in
~/.copilot - Environment: Automatically uses
GH_TOKENfromghCLI
- Package:
@google/gemini-cli - Command:
gemini --yolo - Configuration: Stored in
~/.gemini
- Configuration Detection: Scans current directory for
.tool-versions,mise.toml, and idiomatic version files - Version Parsing: Extracts tool names and versions from configuration files
- Mise Config Generation:
- If you have a
mise.toml: copies it unchanged and generatesmise.agent.tomlwith only the tools you haven't specified - If no
mise.toml: generatesmise.agent.tomlwith all required agent tools
- If you have a
- Dockerfile Generation: Creates a Debian 12-slim based Dockerfile with:
- mise runtime manager
- All detected development tools at specified versions
- Non-root user (UID 1000) for security
- Image Building: Builds Docker image (or reuses cached image if unchanged)
- Image naming:
mheap/agent-en-place:<tool1>-<version1>-<tool2>-<version2>-...
- Image naming:
- Container Execution: Outputs
docker runcommand with:- Current directory mounted to
/workdir - Provider config directory mounted (e.g.,
~/.copilot) - Appropriate environment variables set
MISE_ENV=agentto activate the agent environment
- Current directory mounted to
--debug
Show Docker build output instead of hiding it. Useful for troubleshooting build failures.
agent-en-place --debug opencode--rebuild
Force rebuilding the Docker image even if it already exists. Useful when you want to pull latest tool versions.
agent-en-place --rebuild copilot--dockerfile
Print the generated Dockerfile and exit without building. Useful for debugging or customization.
agent-en-place --dockerfile codex--mise-file
Print the generated mise configuration files and exit without building. Shows both your mise.toml (if present) and the generated mise.agent.toml.
agent-en-place --mise-file claudeExample output:
# mise.toml (user)
[tools]
node = "20.11.0"
# mise.agent.toml (generated)
[tools]
"npm:@anthropic-ai/claude-code" = "latest"
python = "latest"
Note that node is not in the generated mise.agent.toml because you specified it in your mise.toml.
--config
Use a specific configuration file. See docs/config.md for configuration options.
agent-en-place --config ./my-config.yaml claudeagent-en-place --debug --rebuild opencodeYou can override tool definitions using environment variables, which is useful for when you want to enforce specific tool versions regardless of project configuration files. I use this when I'm working on something quickly and want to use a cached image.
AGENT_EN_PLACE_TOOLS
A comma-separated list of tool@version pairs. When set, these tools take the highest priority -- overriding versions from mise.toml, .tool-versions, and idiomatic version files. Tools from config files that are not specified in the environment variable are still installed.
AGENT_EN_PLACE_TOOLS=node@latest,python@3.12 agent-en-place claudenpm-style packages (including scoped packages) are supported:
AGENT_EN_PLACE_TOOLS=node@20,npm:trello-cli@1.5.0 agent-en-place claude
AGENT_EN_PLACE_TOOLS=npm:@my-org/some-package@1.2.3 agent-en-place claudeIf you omit the @version, it defaults to latest:
AGENT_EN_PLACE_TOOLS=node,python agent-en-place claudeAGENT_EN_PLACE_SPECIFIED_TOOLS_ONLY
When set to 1 alongside AGENT_EN_PLACE_TOOLS, all file-based tool discovery is skipped. Only the tools listed in AGENT_EN_PLACE_TOOLS (plus the agent's own tool) are installed. .tool-versions, mise.toml, and idiomatic version files are ignored entirely.
AGENT_EN_PLACE_TOOLS=node@20,python@3.12 \
AGENT_EN_PLACE_SPECIFIED_TOOLS_ONLY=1 \
agent-en-place claudeThis is useful when you want a minimal, deterministic container with only the tools you explicitly specify.
Note: Setting AGENT_EN_PLACE_SPECIFIED_TOOLS_ONLY=1 without AGENT_EN_PLACE_TOOLS has no effect (a warning is printed to stderr).
Mise environment variables can be configured in two ways, and both sources are merged (host env vars take precedence over config values for the same key).
Via config file (mise.env):
mise:
env:
ruby_compile: falseKeys are automatically uppercased and prefixed with MISE_ (e.g., ruby_compile becomes MISE_RUBY_COMPILE). Boolean values true/false are converted to strings.
Via host environment:
Any environment variables starting with MISE_ that are set on your host are automatically forwarded into the Docker image.
export MISE_RUBY_COMPILE=false
agent-en-place claudeBoth sources produce ENV directives in the Dockerfile, available during mise install (build time) and at container runtime.
Note: MISE_ENV and MISE_SHELL are excluded from forwarding. MISE_ENV is set at container runtime via docker run -e MISE_ENV=agent, and MISE_SHELL is host-specific and not relevant inside the container.
MIT License