Configuration¶
VibePod merges configuration from four sources in order, with each layer overriding the previous:
- Built-in defaults
- Global config —
~/.config/vibepod/config.yaml - Project config —
.vibepod/config.yamlin the current directory - Environment variables — override specific keys at runtime
Run vp config path to print the exact paths in use, and vp config show to print the fully merged result.
Full reference¶
# Config format version (always 1)
version: 1
# Agent to run when no argument is given to `vp run`
# Alias `vibe` resolves to `devstral`.
default_agent: claude
# Pull the latest image before every run (default: true)
# Can be overridden per agent with agents.<agent>.auto_pull
auto_pull: true
# Remove untagged vibepod images after a pull (default: true)
# When a pull retags `latest`, the previous image stays behind untagged
# (`vibepod/claude <none>`) and such images accumulate over time. With
# auto_clean every pull sweeps the whole `vibepod/` namespace, so leftovers
# from earlier pulls are cleared too. Tagged images, images of other
# namespaces, and images still used by a container are never removed — an
# image held by a container is picked up by a later sweep instead.
auto_clean: true
# Remove the container automatically when it stops (default: true)
auto_remove: true
# Primary Docker network created and used by VibePod
network: vibepod-network
# Log level: debug | info | warning | error
log_level: info
# Disable colour output
no_color: false
agents:
claude:
enabled: true
image: vibepod/claude:latest
auto_pull: null # Per-agent override: true/false, or null to use global auto_pull
env: {} # Extra environment variables passed to the container
volumes: [] # Reserved for future use
ports: [] # Ports to publish on the host, `docker run -p` syntax
init: [] # Optional shell commands run before agent startup
overlay: true # Set false to ignore the project's .vibepod/overlay/ (see Project overlays)
gemini:
enabled: true
image: vibepod/gemini:latest
env: {}
volumes: []
ports: []
init: []
opencode:
enabled: true
image: vibepod/opencode:latest
env: {}
volumes: []
ports: []
init: []
devstral:
enabled: true
image: vibepod/devstral:latest
env: {}
volumes: []
ports: []
init: []
auggie:
enabled: true
image: vibepod/auggie:latest
env: {}
volumes: []
ports: []
init: []
copilot:
enabled: true
image: vibepod/copilot:latest
env: {}
volumes: []
ports: []
init: []
codex:
enabled: true
image: vibepod/codex:latest
env: {}
volumes: []
ports: []
init: []
pi:
enabled: true
image: vibepod/pi:latest
env: {}
volumes: []
ports: []
init: []
agy:
enabled: true
image: vibepod/agy:latest
env: {}
volumes: []
ports: []
init: []
tau:
enabled: true
image: vibepod/tau:latest
env: {}
volumes: []
ports: []
init: []
jcode:
enabled: true
image: vibepod/jcode:latest
env: {}
volumes: []
init: []
# Connect agents to a local or remote LLM server (Ollama, vLLM, etc.)
llm:
enabled: false
base_url: "" # Server endpoint URL
api_key: "" # Auth token (set to "ollama" for Ollama)
model: "" # Model name passed to the agent
logging:
enabled: true
image: vibepod/datasette:latest
db_path: ~/.config/vibepod/logs.db
ui_port: 8001 # Port for the Datasette UI
proxy:
enabled: true
image: vibepod/proxy:latest
db_path: ~/.config/vibepod/proxy/proxy.db
ca_dir: ~/.config/vibepod/proxy/mitmproxy
ca_path: ~/.config/vibepod/proxy/mitmproxy/mitmproxy-ca-cert.pem
Environment variables¶
These variables override the corresponding config keys without editing any file:
| Variable | Config key | Example |
|---|---|---|
VP_DEFAULT_AGENT |
default_agent |
VP_DEFAULT_AGENT=vibe |
VP_AUTO_PULL |
auto_pull |
VP_AUTO_PULL=true |
VP_AUTO_CLEAN |
auto_clean |
VP_AUTO_CLEAN=false |
VP_LOG_LEVEL |
log_level |
VP_LOG_LEVEL=debug |
VP_NO_COLOR |
no_color |
VP_NO_COLOR=true |
VP_DATASETTE_PORT |
logging.ui_port |
VP_DATASETTE_PORT=9001 |
VP_PROXY_ENABLED |
proxy.enabled |
VP_PROXY_ENABLED=false |
VP_LLM_ENABLED |
llm.enabled |
VP_LLM_ENABLED=true |
VP_LLM_BASE_URL |
llm.base_url |
VP_LLM_BASE_URL=http://localhost:11434 |
VP_LLM_API_KEY |
llm.api_key |
VP_LLM_API_KEY=ollama |
VP_LLM_MODEL |
llm.model |
VP_LLM_MODEL=qwen3:14b |
VP_CONFIG_DIR |
(config root) | VP_CONFIG_DIR=/custom/path |
Image overrides¶
Each agent image can be overridden individually:
| Variable | Agent |
|---|---|
VP_IMAGE_CLAUDE |
claude |
VP_IMAGE_GEMINI |
gemini |
VP_IMAGE_OPENCODE |
opencode |
VP_IMAGE_DEVSTRAL |
devstral |
VP_IMAGE_AUGGIE |
auggie |
VP_IMAGE_COPILOT |
copilot |
VP_IMAGE_CODEX |
codex |
VP_IMAGE_PI |
pi |
VP_IMAGE_AGY |
agy |
VP_IMAGE_TAU |
tau |
VP_IMAGE_JCODE |
jcode |
VP_DATASETTE_IMAGE |
datasette (logs UI) |
VP_PROXY_IMAGE |
proxy |
VP_SKILLS_ENGINE_IMAGE |
skills-engine (used by vp skills) |
Set VP_IMAGE_NAMESPACE to change the prefix for all default images at once:
For end-to-end examples (extending a base image and assigning a brand-new image to an agent), see Agents > Image customization workflows.
Project-level config¶
Use vp config init in your repository to create .vibepod/config.yaml automatically when it does not already exist:
If .vibepod/config.yaml already exists, this command exits without modifying it; run vp config init --force to replace the file.
This writes a minimal starter file:
To copy a full agent block into the project config, pass the agent name:
This adds agents.claude to .vibepod/config.yaml (creating the file if needed). If agents.claude is already present, the command exits without modifying the file.
Then add only the keys you want to override. Project config is merged on top of global config and defaults.
# .vibepod/config.yaml
default_agent: opencode
agents:
opencode:
env:
OPENAI_BASE_URL: https://my-internal-proxy/v1
init:
- apt-get update
- apt-get install -y ripgrep
agents.<agent>.init runs inside the container before the agent process starts. Commands run with /bin/sh -lc and set -e (startup stops on the first failed command).
Commit this file to share project defaults with your team.
Publishing ports¶
By default no user-defined ports are published, so anything the agent starts inside the container — a dev server, web UI, or debugger — is unreachable from the host. agents.<agent>.ports publishes container ports on the host using the same syntax as docker run -p:
# .vibepod/config.yaml
agents:
claude:
ports:
- "8000:8000" # host:container
- "127.0.0.1:9229:9229" # bind to a specific host interface
- "6000:6000/udp" # UDP
- "3000" # container port on a random host port
Always quote port entries
YAML 1.1 parses unquoted host:container pairs as base-60 numbers:
- 22:22 loads as the integer 1342 and would publish the wrong port.
Out-of-range results (e.g. 3000:30 → 180030) are rejected at startup,
but in-range ones are not detectable — quote every entry.
Like other agent keys, a project-level ports list replaces the global one for that agent. The list applies to both vp run and vp task containers; note that two containers cannot publish the same host port at the same time, so a fixed host port limits you to one such container per agent.
The built-in proxy¶
VibePod starts a vibepod-proxy container alongside every agent. It acts as an HTTP(S) MITM proxy and logs all outbound requests to a SQLite database viewable in the Datasette UI (vp logs start).
The proxy is reachable inside the Docker network as http://vibepod-proxy:8080. It is not published on a host port.
To disable the proxy globally:
Or at runtime:
Podman users
The proxy relies on container-name DNS resolution over the vibepod-network
network. If you use Podman with the CNI backend, install the dnsname
plugin (e.g. podman-plugins on Fedora, golang-github-containernetworking-plugin-dnsname
on Debian/Ubuntu) and recreate the network. See Quickstart — Using Podman for full instructions.