harnessctl
v0.2.17
Published
Universal CLI wrapper for coding agents
Maintainers
Readme
harnessctl
One command for Claude Code, Codex, DeepAgents, Gemini, Cursor, OpenCode, and custom coding agents.
harnessctl is a small CLI that lets you run, compare, hand off, and fail over between coding-agent CLIs without changing how you work.
Use it when one agent is better at planning, another is better at editing, and a third is available when the first one hits a rate limit.
Install
npm install -g harnessctl
harnessctl setupOr use Homebrew:
brew install mnvsk97/tap/harnessctlOther options:
# Linux / macOS binary installer
curl -fsSL https://raw.githubusercontent.com/mnvsk97/harnessctl/main/install/install.sh | bash
# From source
git clone https://github.com/mnvsk97/harnessctl.git
cd harnessctl
bun install
bun run src/cli.ts --helpQuick Start
# Run the default agent
harnessctl run "fix the auth bug"
# Pick an agent
harnessctl run --agent codex "refactor the database layer"
harnessctl run --agent deepagents "run the tests and fix failures"
# Open an interactive agent shell
harnessctl shell --agent claude
# Check configured agents
harnessctl doctorCore Workflows
Hand Off Between Agents
Every run gets a run ID. Use it to continue with another agent.
harnessctl run --agent codex "refactor auth"
# run: 1713364500000-codex
harnessctl handoff 1713364500000-codex --agent claude "review and add tests"The next agent gets a compact handoff: original task, summary, changed files, and a pointer to the full context file under .harnessctl/handoffs/.
Compare Agents
Run the same prompt across agents and optionally ask a judge agent to pick the best result.
harnessctl compare "fix this bug" --agents codex,claude
harnessctl compare "fix this bug" --agents codex,claude --judge claudeRun Pipelines
Chain agents through different stages of a task.
harnessctl pipeline "build auth module" --plan codex --build claude --test codexFail Over Automatically
Configure a fallback agent for rate limits, token limits, or auth failures.
# ~/.harnessctl/agents/claude.yaml
fallback: codex
auto_failover: true
failover_transfer: transcriptWhen Claude fails for a limit/auth reason, harnessctl hands the task to Codex with context.
Useful Commands
harnessctl list # installed/configured agents
harnessctl doctor # health checks
harnessctl models --agent codex # known models for an agent
harnessctl logs # recent run history
harnessctl logs --run-id RUN_ID # one run only
harnessctl replay RUN_ID # rerun a previous prompt
harnessctl stats --cost # spend summary
harnessctl run "continue" --resume # resume latest harness session
harnessctl run --name auth-fix "fix" # name a session
harnessctl run --template review "src" # use a prompt template
harnessctl run --budget 2.00 "task" # daily spend guardrail
harnessctl context set "Node 22, postgres, follow existing patterns"
harnessctl context syncSupported Agents
| Agent | Native resume | Transcript handoff | Failover | | --- | --- | --- | --- | | Claude Code | yes | full | full | | Codex | no | full | full | | DeepAgents | yes | summary + session DB pointer | summary | | Gemini | yes | full | summary | | Cursor | yes | full | summary | | OpenCode | no | no | summary | | Custom YAML | configurable | no | summary |
Custom agents live in ~/.harnessctl/agents/<name>.yaml.
Setup Checklists
Each underlying coding harness must be installed and authenticated before harnessctl can run it. Use harnessctl doctor after setup to confirm the selected harness is ready.
Required before use:
claude --version
claude auth login
harnessctl doctorHarnessctl invokes Claude Code in print mode and reads native session JSONL files from ~/.claude/projects for richer handoffs.
Required before use:
codex --version
codex login
harnessctl doctorCodex can authenticate with ChatGPT login or an API key. Harnessctl invokes Codex with codex exec for headless runs.
DeepAgents support uses the CLI's non-interactive stdin mode, so it behaves like the other headless harnessctl adapters:
harnessctl run --agent deepagents "fix the failing tests"
harnessctl run --agent deepagents "continue that change" --resume
harnessctl run --agent deepagents -- --agent backend-devThe adapter invokes deepagents --stdin --auto-approve --shell-allow-list recommended --quiet --no-stream. To pass DeepAgents-specific flags, put them after -- or in ~/.harnessctl/agents/deepagents.yaml under extra_args. Project context syncs to DeepAgents' native .deepagents/AGENTS.md file.
Before running DeepAgents through harnessctl, configure provider credentials with DeepAgents' /auth flow, or set OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY, GOOGLE_CLOUD_PROJECT, a custom api_key_env from ~/.deepagents/config.toml, or the matching DEEPAGENTS_CLI_* variant in your shell, project .env, ~/.deepagents/.env, ~/.harnessctl/.env, project .harnessctl/.env, or ~/.harnessctl/agents/deepagents.yaml under env.
OpenAI-compatible gateways can be configured directly in DeepAgents, then used by harnessctl without passing model flags every time:
# ~/.deepagents/config.toml
[models]
default = "openai:provider-account/model-name"
[models.providers.openai]
base_url = "https://gateway.example.com"
api_key_env = "GATEWAY_API_KEY"
models = ["provider-account/model-name"]
[models.providers.openai.params]
use_responses_api = false# ~/.deepagents/.env
GATEWAY_API_KEY=...Check setup:
deepagents --version
deepagents -n "Say hello" -q --no-stream
harnessctl doctorRequired before use:
gemini --version
harnessctl doctorAuthenticate by running gemini interactively, or set one of the supported environment paths before running harnessctl:
export GEMINI_API_KEY=...
# or use Vertex AI configuration
export GOOGLE_GENAI_USE_VERTEXAI=trueHarnessctl invokes Gemini with stream JSON output and --yolo for headless execution.
Required before use:
agent --version
agent login
harnessctl doctorYou can also set CURSOR_API_KEY instead of using agent login. Harnessctl invokes Cursor's agent CLI in print/headless mode.
Required before use:
opencode --version
opencode auth login
harnessctl doctorHarnessctl invokes OpenCode with opencode --pipe, so the OpenCode CLI must already be configured with whatever provider credentials your OpenCode setup needs.
Custom harnesses live at:
~/.harnessctl/agents/<name>.yamlMinimal shape:
cmd: your-agent-command
args: ["--headless"]
stdin: true
timeout: 300
env:
YOUR_AGENT_API_KEY: ${YOUR_AGENT_API_KEY}Then verify:
harnessctl list
harnessctl doctor
harnessctl run --agent <name> "Say hello"Configuration
First run creates:
~/.harnessctl/
config.yaml
agents/
runs/
sessions/
templates/
pipelines/Common settings:
harnessctl config set default codex
harnessctl config set-fallback claude codex --auto
harnessctl config getDevelopment
bun install
bun run src/cli.ts --help
bun test
bun run typecheck
bun run bundle
bash test/sim-headless-failover.sh
bash test/sim-fallback.sh
bash test/sim-deepagents.sh
bash test/real-deepagents-smoke.shtest/real-deepagents-smoke.sh uses configured DeepAgents provider credentials when available. If no credential is configured, it runs the installed DeepAgents CLI with a temporary local class_path chat model so the harnessctl subprocess path is still exercised end to end without external secrets.
Docs
More detailed guides live in docs/guide, and example notebooks live in docs/examples/notebooks.
