PandaCode is an independent CLI for running coding tasks through multiple agent runtimes with one command shape. The first version supports:
pandacode codex ...: Codex throughcodexctl sessionapp-server/control-plane commands.pandacode claude ...: Claude Code through a realtmuxsession.pandacode bamboo ...: Bamboo through its provider-native read/search/edit/write/bash coding loop for domestic OpenAI-compatible providers such as DeepSeek, Xiaomi/MiMo, Kimi, Zhipu, MiniMax, Qwen, and Stepfun.
PandaCode is not Open Dynamic Workflow. It is the lower-level executor that a workflow system can call.
By default, task execution uses the strongest production profile:
- Claude:
opuswithmaxeffort. - Codex:
gpt-5.5withxhigheffort, based on localcodexctl modelssupport. - Bamboo:
deepseekprovider with Bamboo's provider default model andhighreasoning effort. Use--provider,--model, and--effortto choose another domestic model. - Permission mode:
maxby default. Use--permission limitedfor a lower-risk workspace-write mode. - User settings and MCP: isolated off. Claude runs with inline PandaCode-owned hook settings and an empty strict MCP config.
Use the top-level commands first. They are intentionally small and choose a runtime automatically:
pandacode run --cd <workspace> --session <task-id> --task-file task.md --json
pandacode status --cd <workspace> --session <task-id> --json
pandacode resume --cd <workspace> --session <task-id> --task "continue and verify" --json
pandacode logs --cd <workspace> --session <task-id> --tail 200 --jsonRuntime selection is progressive:
- Omit
--runtimeforauto. - Pass
--runtime bamboo|claude|codexwhen a caller already knows the backend. - Pass
--provider deepseekto select Bamboo from the top-levelruncommand. - Use
pandacode <runtime> ...only when you need runtime-specific advanced controls such as Bamboo cache/cost/compact flags.
After any runtime saves a session, pandacode status, logs, resume,
answer, artifacts, interrupt, and stop can use the global latest session
without repeating the runtime name. Automation should still pass an explicit
--session <task-id> when running concurrent tasks.
--task-file paths are resolved from the current process directory first and
then from --cd, so callers can keep task files next to the target workspace or
address them relative to the workspace root.
Commands that receive --json also return a machine-readable failure envelope:
{ "ok": false, "state": "failed", "error": ... }. Callers do not need a
separate stderr parser for runtime errors such as a missing API key.
exec and resume return compact JSON summaries. They report the runtime
status, session ids, model/effort where available, local artifact paths, and
short redacted output tails without dumping full app-server or terminal event
streams. Bamboo also reports usage, cache, verification, and changed files. Use
logs --json when a caller needs a structured tail of the underlying runtime
output.
If a runtime asks for external input, exec/resume return
state: "waiting_for_user" with pending_user_input instead of treating the
turn as a failure. Use pandacode <runtime> answer --choice N --wait or
--text ... to continue the session. Claude answers the visible TUI prompt;
Codex delegates to codexctl session answer; Bamboo maps answer to a resume
turn that passes the selected/text answer back into the same Bamboo run history.
The stable high-level states are:
completed: the turn ended successfully.waiting_for_user: the runtime is blocked on explicit external input.idle: the runtime is alive and ready for another turn.running: the runtime is still working.timeout: PandaCode did not observe completion or a blocking prompt in time.stopped: the delegated runtime/session is gone.blockedorfailed: the task cannot continue without a new instruction or the runtime reported a hard failure.
pandacode run --task "fix the failing tests" --cd .
pandacode resume --task "continue from the last result" --cd .
pandacode status --cd .
pandacode logs --cd . --json
pandacode <runtime> exec --task "fix the failing tests" --cd .
pandacode <runtime> resume --session latest --task "continue from the last result"
pandacode <runtime> answer --session latest --choice 2 --wait --cd .
pandacode <runtime> status --session latest --cd .
pandacode <runtime> logs --session latest --cd .
pandacode <runtime> artifacts --session latest --cd .
pandacode <runtime> interrupt --session latest --cd .
pandacode <runtime> stop --session latest --cd .
pandacode <runtime> model --session latest --model <model> --effort high --cd .
pandacode <runtime> models
pandacode <runtime> list --cd .
pandacode <runtime> doctor<runtime> is currently codex, claude, or bamboo.
Task input can be provided three ways:
pandacode claude exec --task "create a small HTML demo"
pandacode codex exec --task-file task.md
pandacode bamboo exec --provider deepseek --model deepseek-v4-pro --effort high --task-file task.md
pandacode claude exec - < task.mdFuture workflow agents should treat pandacode as the only public interface.
Once the binary is installed and the requested backend is available on the
machine, an agent can run coding tasks without preparing Claude settings, MCP
files, hooks, or project configuration.
Recommended agent loop:
pandacode doctor --cd <workspace> --json
pandacode models --cd <workspace> --json
pandacode run --cd <workspace> --session <name> --runtime auto --model <model> --effort <effort> --permission max --task-file task.md --json
pandacode status --cd <workspace> --session <name> --json
pandacode logs --cd <workspace> --session <name> --json
pandacode answer --cd <workspace> --session <name> --choice 1 --wait --json
pandacode resume --cd <workspace> --session <name> --task-file next.md --json
pandacode stop --cd <workspace> --session <name> --jsonpandacode doctor is a per-runtime health report. Top-level ok means at least
one runtime is usable; inspect each runtime's ok, missing, and
capabilities fields before choosing a backend.
With --runtime auto, a known --model can select the matching backend:
domestic model ids such as kimi-k2.6 select Bamboo and infer their provider,
Claude aliases such as opus select Claude, and gpt-* ids select Codex.
Use --provider only when the Bamboo provider cannot be inferred from the
model id or you want to override the default.
The same command shape applies to Codex and Bamboo. answer --choice maps to
codexctl session answer --pick; logs --visible remains Claude-only because
Codex and Bamboo have structured run snapshots rather than a terminal
viewport.
For Bamboo domestic-model runs, prefer the top-level command for normal use:
pandacode run --cd <workspace> \
--session <task-id> \
--provider deepseek \
--model deepseek-v4-pro \
--effort high \
--permission max \
--task-file task.md \
--jsonUse pandacode bamboo exec --help only for advanced cache, cost, compact,
verification, and provider-specific request parameters.
PandaCode owns the runtime glue internally:
- Claude hook settings are generated as inline JSON for each process.
- The hook command calls the installed
pandacodebinary through its current executable path. - User and project Claude settings are not modified.
- User MCP configuration is ignored for executor sessions.
- Runtime state is written under
.pandacode/so callers can observe and resume sessions. - Orchestrators can set
PANDACODE_STATE_DIRto isolate executor metadata from the target workspace state; relative values resolve under--cd.
Codex uses codexctl session start/send/execute/read/watch/interrupt/stop/list.
exec starts the app-server session and then calls session execute, because
session start is a Plan-mode turn and PandaCode is meant to be an executor.
The PandaCode session record stores the Codex run_id, thread_id, and local
log paths under .pandacode/sessions/codex. Each Codex session gets its own
control channel: logs are written under .pandacode/codex/runs/<session>/logs
and the codexctl daemon socket is a short per-session temp socket. This keeps
parallel workflow nodes from sharing one codexctl daemon/run namespace.
Long task prompts are transported by file reference: PandaCode stores the full
task under .pandacode/<runtime>/prompts/ and sends a short instruction telling
the runtime to read that file. This avoids tmux paste limits and codexctl
app-server pipe/socket failures while preserving the original task text for
observability. Codex start also retries transient transport failures with a fresh
control socket.
Claude uses tmux to start interactive Claude Code and sends turns into that
session. Completion is detected with an explicit marker in the visible tmux
buffer. It does not use claude -p, --output-format stream-json, or
--json-schema.
PandaCode starts Claude with isolated local settings, inline PandaCode-owned hook settings, and an empty strict MCP config so unrelated user hooks or MCP auth prompts do not pollute executor sessions. Hook configuration is not written into the target workspace; only runtime event/log artifacts are persisted.
When a Claude tmux session must be restarted, PandaCode resumes the saved Claude
conversation with official claude --resume <session-id> using the session id
captured from Claude hook events.
Bamboo is embedded as a native PandaCode runtime. It calls the selected
OpenAI-compatible provider directly, runs Bamboo's autonomous
read/search/edit/write/bash tool loop in-process, and stores artifacts under
.pandacode/bamboo/runs. The PandaCode session record stores the Bamboo
run_id so pandacode bamboo resume can rebuild the compact-aware resume
context from the previous report and event tail. Bamboo event logs are exposed
through pandacode bamboo logs; full reports keep provider/model settings,
usage, cache hit/miss, estimated cost, verification, and context compaction
metrics.
Bamboo provider selection:
pandacode bamboo exec \
--provider deepseek \
--model deepseek-v4-pro \
--effort high \
--task "fix the failing tests"
pandacode bamboo model \
--session latest \
--provider xiaomi \
--model mimo-v2.5-pro \
--effort highGeneration parameters are exposed on bamboo exec, bamboo resume, and
bamboo model:
pandacode bamboo exec \
--provider kimi \
--model kimi-k2.6 \
--effort none \
--thinking disabled \
--max-tokens 2048 \
--temperature 0.6 \
--top-p 0.95 \
--task "make the requested change"Supported Bamboo native generation flags include --thinking enabled|disabled,
--max-tokens, --temperature, --top-p, --presence-penalty,
--frequency-penalty, repeated --stop, and repeated --param KEY=JSON.
bamboo model persists these settings for the next resume turn.
Autonomous-run controls from the original Bamboo executor are also exposed on
bamboo exec and bamboo resume:
pandacode bamboo exec \
--provider deepseek \
--model deepseek-v4-pro \
--max-steps 100 \
--model-timeout-ms 180000 \
--run-timeout-ms 7200000 \
--max-total-tokens 800000 \
--max-cost 10 \
--max-cost-currency cny \
--price-file .pandacode/bamboo/pricing.cn.json \
--verify "cargo test" \
--cache-warm \
--task-file task.mdBudget, verification, cache warmup, compact, and price-file controls are
reported through PandaCode capabilities. Bamboo currently implements them
natively; Claude and Codex report them as unsupported in doctor/models
instead of accepting and silently ignoring them.
Provider credentials are read from PandaCode/Bamboo environment variables. The
preferred generic variables are PANDACODE_BAMBOO_PROVIDER,
PANDACODE_BAMBOO_API_KEY, PANDACODE_BAMBOO_MODEL,
PANDACODE_BAMBOO_BASE_URL, and PANDACODE_BAMBOO_PRICE_FILE. Legacy
BAMBOO_* aliases still work. Provider-specific keys such as
DEEPSEEK_API_KEY, XIAOMI_API_KEY, KIMI_API_KEY, ZHIPU_API_KEY,
MINIMAX_API_KEY, QWEN_API_KEY, and STEPFUN_API_KEY are also supported.
Base URLs can be overridden with provider-specific variables such as
DEEPSEEK_BASE_URL.
Useful Bamboo docs:
docs/agent-caller-quickstart.mddocs/bamboo-agent-caller-guide.mddocs/bamboo-coding-tools.mddocs/bamboo-cache-strategy.mddocs/bamboo-migration-audit.mddocs/bamboo-verification-matrix.md
Live env and price examples:
mkdir -p .pandacode/bamboo
cp docs/bamboo-live.env.example .pandacode/bamboo/live.env
cp docs/bamboo-pricing.cn.json.example .pandacode/bamboo/pricing.cn.jsonLive provider smoke:
scripts/smoke-bamboo-live-providers.shPandaCode exposes two permission modes and defaults to max.
max: highest trusted automation mode. Claude maps this to interactive--dangerously-skip-permissions; Codex maps it to--dangerously-full-access; Bamboo uses the full autonomous tool loop with built-in protected-path and dangerous-command safety.limited: lower-risk workspace-write mode. Codex maps this to--sandbox workspace-write --approval-policy never; Claude maps this to--permission-mode acceptEdits; Bamboo allows normal workspace edits and local verification but blocks background commands, installs, downloads, and recursive/destructive cleanup.
Runtime state is written inside the target workspace:
.pandacode/
sessions/
claude/
codex/
bamboo/
claude/
events/
logs/
prompts/
codex/
runs/
prompts/
bamboo/
events/
prompts/
runs/
This keeps workflow callers able to inspect session metadata, visible logs, and runtime artifacts without parsing terminal history.
For workflow runners, CI, and other orchestrators that need per-run isolation,
set PANDACODE_STATE_DIR before launching PandaCode:
PANDACODE_STATE_DIR=.odw/runs/<run-id>/pandacode-state/bamboo/<session> \
pandacode bamboo exec --cd <workspace> --session <session> --task-file task.md --jsonPandaCode itself does not depend on Open Dynamic Workflow. ODW may call PandaCode through this CLI/environment contract, but executor prompts, terminal logs, provider reports, and resume records remain owned by PandaCode.
The current test suite includes unit tests plus fake-runtime integration tests for all runtime paths:
cargo fmt --check
cargo test
cargo clippy -- -D warnings
cargo buildThe fake integrations exercise exec, resume, status, logs, artifacts,
answer, model, interrupt, stop, list, models, and doctor without
spending real model calls.