Agent Setup
Cloche supports any agent that can read a prompt from stdin and print CLOCHE_RESULT:<name> to stdout.
Built-in Agents
Cloche has a concept of known agents — agent commands it understands natively. Known agents receive default arguments automatically, and some arguments are required and will always be injected regardless of agent_args. Unknown agents (e.g. codex) receive no default arguments; the prompt is passed on stdin and the command is invoked as-is.
Known agents
| Command | Default args (overridable) | Required args (always injected) |
|---|---|---|
claude |
-p --dangerously-skip-permissions --model sonnet |
--output-format stream-json --verbose |
How agent_args interacts with defaults
When agent_args is not set, the agent receives its full default argument list.
When agent_args is set, it replaces the default args entirely — but required args are always appended if not already present. You cannot remove a required arg.
For claude, this means:
-p,--dangerously-skip-permissions, and--model sonnetare overridable: they are present by default but absent if you supplyagent_argswithout them.--output-format stream-jsonand--verboseare required: Cloche injects them even if youragent_argsomits them.--output-format stream-jsonis necessary because the prompt adapter parses Claude’s streaming JSON output to extract results and token usage.--verboseis required for that stream to include the result event.
Overriding arguments
Use agent_args to replace the default args. Required args are always present, so you do not need to include them.
step implement {
prompt = file(".cloche/prompts/implement.md")
agent_args = "-p --dangerously-skip-permissions --model claude-opus-4-5"
results = [success, fail]
}
Note that -p and --dangerously-skip-permissions must be included explicitly when using agent_args, since they are overridable defaults and will not be injected automatically.
Named agent declarations
Rather than repeating agent_args on every step, declare named agents at the workflow level and reference them from steps:
workflow "develop" {
agent haiku_claude {
command = "claude"
args = "-p --dangerously-skip-permissions --model claude-haiku-4-5"
}
agent opus_claude {
command = "claude"
args = "-p --dangerously-skip-permissions --model claude-opus-4-6"
}
step commit {
prompt = file(".cloche/prompts/commit.md")
agent = haiku_claude
results = [success, fail]
}
step implement {
prompt = file(".cloche/prompts/implement.md")
agent = opus_claude
results = [success, fail]
}
implement:success -> commit
implement:fail -> abort
commit:success -> done
commit:fail -> abort
}
Required args (--output-format stream-json and --verbose) are still injected automatically — you do not need to include them in args. Step-level agent_command and agent_args override the agent declaration.
Unknown agents
Any agent_command value not in the known agents table is treated as unknown. Unknown agents receive no default arguments, the prompt on stdin, and agent_args is passed through verbatim.
Fallback Chains
Specify multiple agent commands as a comma-separated list. Cloche tries each in order until one succeeds:
agent_command = "claude,gemini,codex"
Fallback behavior:
| Outcome | Action |
|---|---|
| Command not found / failed to start | Try next command in the list. |
Exit non-zero without CLOCHE_RESULT marker |
Try next command in the list. |
Exit non-zero with CLOCHE_RESULT marker |
Use that result — no fallback. |
| Exit 0 | Use result — no fallback. |
| All commands fail to start | Step returns an error. |
| Last command crashes without marker | Step returns fail. |
Claude Code
Prerequisites
- Claude Code installed on the host machine:
npm install -g @anthropic-ai/claude-code - An active Claude Code session on the host. Run
claudeonce interactively to authenticate before starting the daemon.
How Authentication Works
Cloche automatically copies ~/.claude/ and ~/.claude.json from the host into each container at /home/agent/.claude and /home/agent/.claude.json. The files are copied — not bind-mounted — so each container gets its own isolated credential copy. Cloche runs chown -R agent:agent on the copied auth files at container startup so the unprivileged agent user can read them.
Dockerfile
FROM cloche-base:latest
USER root
# Install Node.js (required for Claude Code)
RUN apt-get update \
&& apt-get install -y --no-install-recommends nodejs npm \
&& rm -rf /var/lib/apt/lists/*
# Install Claude Code
RUN npm install -g @anthropic-ai/claude-code
# Add your project's build dependencies here
# RUN apt-get install -y ...
USER agent
Workflow Config
Claude is the default agent — no explicit configuration is required. The full default invocation is:
claude -p --output-format stream-json --verbose --dangerously-skip-permissions --model sonnet
Override with agent_args in your workflow or step config if needed. See overriding arguments above for how defaults and required args interact.
API Key Alternative
Set ANTHROPIC_API_KEY in the daemon’s environment and it will be passed into containers automatically — no session files required.
Troubleshooting
- Claude Code not found in container — Ensure the Dockerfile installs
@anthropic-ai/claude-codevia npm. - Authentication errors — Run
claudeon the host to ensure the session is active before starting the daemon. - Permission errors on
~/.claude— Check that the Dockerfile does not override the container entrypoint, which handles credential injection and runschown -R agent:agenton the auth files.
Codex
Prerequisites
An OpenAI API key with Codex access.
How Authentication Works
Codex authenticates via API key. Pass it to containers using CLOCHE_EXTRA_ENV:
export CLOCHE_EXTRA_ENV="OPENAI_API_KEY=sk-..."
cloched &
Dockerfile
FROM cloche-base:latest
USER root
RUN apt-get update \
&& apt-get install -y --no-install-recommends nodejs npm \
&& rm -rf /var/lib/apt/lists/*
RUN npm install -g @openai/codex
USER agent
Workflow Config
Set agent_command = "codex" in your workflow or config.toml. Codex is not a known agent, so it receives the prompt on stdin with no default arguments. Add agent_args if your version requires explicit flags:
agent_command = "codex"
agent_args = "--full-auto"
Token Usage Capture
Codex does not emit token usage in its standard output. Use usage_command to capture it separately. The command must output JSON with input_tokens and output_tokens fields:
{"input_tokens": 1234, "output_tokens": 567}
Configure via config.toml (applies to all Codex steps):
[agents.codex]
usage_command = "codex usage --last --json"
Or per-step in the workflow file:
step implement {
...
usage_command = "codex usage --last --json"
}
Step-level usage_command takes precedence over the [agents.codex] config.toml value.
Troubleshooting
- Codex not found — Ensure the Dockerfile installs
@openai/codexvia npm. - Authentication errors — Verify
CLOCHE_EXTRA_ENVincludes a validOPENAI_API_KEYand that the daemon was started after the variable was set. - No output — Ensure the installed Codex CLI version supports reading prompts from stdin.