Docs · Quickstart · Examples
caw (Coding Agent Wrapper) wraps multiple coding-agent CLIs — Claude Code, Codex, and opencode — behind a single Agent / Session API. Swap providers without changing your code, attach MCP tool servers, capture structured trajectories, and manage credentials for Docker containers. caw aims at the common cases with a small, ergonomic API — if you need fine-grained control over agent behavior, reach for the underlying agent SDKs; caw isn't trying to replace them.
caw is on PyPI as coding-agent-wrapper. The recommended path is uv:
uv add coding-agent-wrapper # use as a library in a uv-managed project
uv tool install coding-agent-wrapper # install just the CLI (caw, caw-traj) globallyPlain pip works too:
pip install coding-agent-wrapperRequires Python 3.10+. You also need at least one provider CLI installed and authenticated (claude, codex, or opencode) — run caw doctor to see what caw can find.
For local development:
uv sync --extra devfrom caw import Agent
agent = Agent() # defaults to claude_code
traj = agent.completion("Explain what this repository does")
print(traj.result)
print(f"{traj.usage.total_tokens} tokens, ${traj.usage.cost_usd:.4f}")agent = Agent(model="claude-opus-4-7", reasoning="high")
agent.set_system_prompt("You are a security reviewer.")
with agent.start_session() as session:
print(session.send("Review src/auth.py for vulnerabilities").result)
print(session.send("Now check src/api.py").result)
# session.end() runs on exit and returns the full TrajectoryThe most common way is the CAW_PROVIDER env var — set it once and every Agent() picks it up:
export CAW_PROVIDER=codexfrom caw import Agent
agent = Agent() # uses whatever CAW_PROVIDER saysOr hand caw a fallback order and let it pick whichever is installed & healthy at runtime:
agent = Agent(provider=["claude", "codex", "opencode"])
traj = agent.completion("Reply with a one-line hello.")
print(f"[{traj.agent}] {traj.result}") # whichever provider handled itDecorate a Python function with @tool and pass it in — caw stands up a tool server for you:
from caw import Agent, tool
@tool(description="Add two numbers")
def add(a: int, b: int) -> int:
return a + b
agent = Agent(stateless_tools=[add])
print(agent.completion("What is 17 plus 25? Use the tool.").result)For stateful tools (shared state across calls in a session), subclass ToolKit — see the guide.
Every call returns a structured Trajectory. Save it and browse it later:
with Agent(data_dir="caw_data").start_session(traj_path="run.json") as session:
session.send("List the Python files here and count them.")Two viewers ship with caw:
caw-traj run.json # compact, step-indexed terminal view
caw viewer # web UI, open run.json by path in the browser- Providers — one API across Claude Code, Codex, and opencode.
- Auto-provider fallback — pick the first installed/healthy provider, fall back transparently.
- Models & tiers — portable
ModelTierselection instead of hard-coded model strings. - Sessions & resume — multi-turn conversations that resume across processes via a
resume_handle. - MCP tools, ToolKit, and subagents — give the agent tools, declaratively or as child agents.
- Provider health — raw availability/credential signals, with an optional live probe (
caw doctor). - Trajectory viewer — browse saved trajectories in the browser or terminal.
- Docker credentials — bind-mount agent OAuth credentials into containers without touching host files (
caw auth).
Every interaction yields a structured Trajectory with turns, content blocks, token usage, and cost — persisted to JSONL when you pass data_dir=.
Full docs, guides, and API reference: https://zzjas.github.io/caw/. Machine-readable llms.txt / llms-full.txt are published alongside, since caw's users are often agents.
Runnable examples live in examples/.