Thanks for your interest in contributing.
# Clone and install
git clone https://github.com/mnvsk97/harnessctl.git
cd harnessctl
bun install
# Run from source
bun run src/cli.ts run "hello"
# Verify
bun test
bun run typecheck
bun run bundle
# Build binary
bun build --compile src/cli.ts --outfile harnessctl- Create
src/adapters/<agent>.tsimplementing theAdapterinterface - Define
base(command + fixed args),argMap(flag translations),parseOutput, andhealthCheck - Register it in
src/adapters/registry.ts - Add a default YAML config in
src/config.tsDEFAULT_AGENTS
Look at src/adapters/codex.ts or src/adapters/opencode.ts as compact references.
-
base.cmdandbase.argsinvoke the agent in headless/non-interactive mode -
argMapdeclares which harnessctl flags the agent supports and how they translate -
parseOutputextracts summary, session ID, cost, and token usage from output -
detectExitReasonis added only if the shared detector is not enough -
healthCheckandauthCheckare cheap, non-interactive commands - Tests cover parsing and flag mapping for the adapter
src/
cli.ts # entrypoint
config.ts # config loading
invoke.ts # subprocess execution (headless run)
session.ts # session management
log.ts # run logging
adapters/ # per-agent translation layer
commands/ # CLI commands (run, shell, list, doctor, config, pipeline)
- Keep it minimal. harnessctl is plumbing, not a platform.
- Runtime dependencies should stay near zero; prefer Node built-ins.
- Adapters should be self-contained and boring.
- Test with the actual agent CLI before submitting.
Open an issue on GitHub with:
- Which agent and version
- The command you ran
- What you expected vs what happened