Skip to content

Feature matrix

Every CLI command and flag, every hook event per agent, every MCP tool, and the end-to-end agent self-test, run against throwaway projects. Generated by python bench/feature_matrix.py.

114 / 114 passed · keelyard 0.1.0 · commit 9360853 · Python 3.13.5 · Linux · 2026-10-14 · 15s

Expected exit codes: 0 ok, 1 error, 2 usage error, 3 check not passed. Rows that test an error path pass when keelyard fails cleanly with the right code.

setup

case command exit ms
✓ init --dry-run changes nothing keelyard init --dry-run --json 0 164
✓ init --no-agents keelyard init --no-agents --json 0 156
✓ init --agent claude (hooks, MCP, skill, commands, CLAUDE.md) keelyard init --agent claude --json 0 150
✓ init twice is idempotent keelyard init --agent claude --json 0 166
✓ install codex keelyard install codex --json 0 169
✓ install opencode keelyard install opencode --json 0 118
✓ install unknown agent is a usage error keelyard install cursor --json 2 92
✓ doctor keelyard doctor --json 0 130
✓ status keelyard status --json 0 121

rewind

case command exit ms
✓ snap picks up the installed files keelyard rewind snap --json 0 156
✓ snap with no change keelyard rewind snap --json 0 127
✓ snap after an edit keelyard rewind snap --json 0 151
✓ list keelyard rewind list --json 0 120
✓ list -n 1 keelyard rewind list -n 1 --json 0 135
✓ show keelyard rewind show 4 --json 0 128
✓ fork keelyard rewind fork 1 ../fork --json 0 122
✓ to keelyard rewind to 1 --json 0 155
✓ to an unknown step keelyard rewind to 999 --json 1 132
✓ show a non-number keelyard rewind show x --json 2 92

proof

case command exit ms
✓ add keelyard proof add adds numbers has a Cart --json 0 136
✓ status (open) exits 3 keelyard proof status --json 3 128
✓ check needs evidence keelyard proof check 1 --json 1 135
✓ check unknown id keelyard proof check 9 x --json 1 122
✓ check keelyard proof check 1 test_add passes --json 0 122
✓ test after (pass) keelyard proof test after --cmd python -m pytest -q -p no:cacheprovider --json 0 459
✓ test with a missing tool exits 3 keelyard proof test after --cmd no-such-tool-xyz --json 3 118
✓ shot without url keelyard proof shot --json 1 113
✓ report keelyard proof report --json 0 141

context

case command exit ms
✓ run (pass-through exit) keelyard run --json -- python -c print('hi') 0 151
✓ run a failing command keelyard run --json -- python -c import sys; sys.exit(4) 4 135
✓ run a missing command keelyard run --json -- no-such-tool-xyz 127 139
✓ run with nothing keelyard run --json 2 119
✓ filter --for keelyard filter --for pytest -q --json 0 119
✓ recall unknown id keelyard recall abc --json 1 114
✓ recall bad id keelyard recall ../etc --json 1 167
✓ code outline keelyard code outline app.py --json 0 123
✓ code outline missing file keelyard code outline nope.py --json 1 129
✓ code map keelyard code map --json 0 121
✓ code find keelyard code find Cart --json 0 118

memory

case command exit ms
✓ index keelyard memory index --json 0 166
✓ stats keelyard memory stats --json 0 139
✓ search keelyard memory search websocket --json 0 172
✓ search with odd input keelyard memory search NEAR( "* --json 0 123

usage

case command exit ms
✓ usage --by day keelyard usage --json 0 121
✓ usage --by model keelyard usage --by model --json 0 124
✓ usage --by agent keelyard usage --by agent --json 0 127

swarm

case command exit ms
✓ swarm run missing file keelyard swarm run nope.json --json 1 203
✓ swarm run bad JSON keelyard swarm run app.py --json 1 186
✓ swarm plan keelyard swarm plan fix add for strings --json 0 221
✓ swarm plan --subagents keelyard swarm plan where is add defined --subagents 0 213

arena

case command exit ms
✓ arena run missing spec keelyard arena run nope.toml --json 1 119
✓ arena render without results keelyard arena render nowhere --json 1 124

bench

case command exit ms
✓ bench leaves the timeline alone keelyard bench --json 0 302

cli

case command exit ms
✓ --version keelyard --version 0 89
✓ no command prints help keelyard 0 91
✓ unknown command keelyard frobnicate --json 2 90
✓ reinstall codex (rewind removed it) keelyard install codex --json 0 123
✓ reinstall opencode keelyard install opencode --json 0 123
✓ uninstall codex keeps AGENTS.md for opencode keelyard uninstall codex --json 0 114
✓ uninstall opencode removes the AGENTS.md block keelyard uninstall opencode --json 0 139

hooks

case command exit ms
✓ claude SessionStart keelyard hook claude SessionStart 0 161
✓ claude UserPromptSubmit keelyard hook claude UserPromptSubmit 0 116
✓ claude PostToolUse Read keelyard hook claude PostToolUse 0 122
✓ claude PreToolUse Read (repeat read denied) keelyard hook claude PreToolUse 0 106
✓ claude PostToolUse Write (snapshot) keelyard hook claude PostToolUse 0 130
✓ claude PostToolUse Bash (output filtered) keelyard hook claude PostToolUse 0 146
✓ claude PreCompact keelyard hook claude PreCompact 0 126
✓ claude Stop (blocks without proof) keelyard hook claude Stop 0 123
✓ codex PostToolUse apply_patch keelyard hook codex PostToolUse 0 128
✓ codex Stop keelyard hook codex Stop 0 128
✓ opencode PostToolUse edit keelyard hook opencode PostToolUse 0 144
✓ unknown event is ignored keelyard hook claude Future 0 140
✓ garbage stdin is ignored keelyard hook claude Stop 0 125
✓ cwd outside any project is ignored keelyard hook claude Stop 0 150

MCP tools

Called over stdio by the official MCP client. Error rows check that bad input is refused.

tool arguments result
✓ status {} ok
✓ workflow {'name': 'plan'} ok
✓ proof_requirements {'items': ['adds numbers']} ok
✓ proof_requirements {'items': []} Error executing tool proof_requirements: 1 validation error for proof_requirementsArguments
✓ proof_check {'requirement_id': 1, 'evidence': 'test_add passes'} ok
✓ proof_check {'requirement_id': 7, 'evidence': 'x'} Error executing tool proof_check: no requirement 7
✓ proof_run_tests {'phase': 'after', 'command': 'python -m pytest -q -p no:... ok
✓ proof_run_tests {'phase': 'later'} Error executing tool proof_run_tests: 1 validation error for proof_run_testsArguments
✓ proof_screenshot {} Error executing tool proof_screenshot: no url given and [proof].app_url not set
✓ proof_status {} ok
✓ rewind_list {'last': 5} ok
✓ rewind_diff {'step': 1} ok
✓ rewind_diff {'step': 0} Error executing tool rewind_diff: 1 validation error for rewind_diffArguments
✓ rewind_to {'step': 1} ok
✓ read_file {'path': 'app.py'} ok
✓ read_file {'path': 'app.py'} ok
✓ read_file {'path': '../../etc/passwd'} Error executing tool read_file: ../../etc/passwd is outside the project root
✓ read_file {'path': '.keelyard/config.toml'} Error executing tool read_file: refusing to read keelyard internal state
✓ run_compact {'command': 'python -c "print(\'ok\')"'} ok
✓ recall {'output_id': 'nope'} Error executing tool recall: unknown output id 'nope'. Hint: use the id from the last line of run_co
✓ outline {'path': 'app.py'} ok
✓ project_map {} ok
✓ find_symbol {'name': 'add'} ok
✓ usage_report {'by': 'model'} ok
✓ route_task {'task': 'design the concurrency architecture', 'n_files'... ok
✓ swarm {'tasks': [{'kind': 'ask', 'prompt': 'where is add?', 'fi... ok
✓ swarm_plan {'goal': 'fix add so it handles strings'} ok
✓ swarm_verify {'answer': 'app.py:2return a + b', 'files': ['app.py']} ok
✓ swarm_verify {'answer': 'app.py:99 nothing', 'files': ['app.py']} ok
✓ memory_search {'query': 'websocket', 'this_project_only': False} ok

Agent self-test

keelyard selftest: a scripted agent completes a task through MCP and Claude Code hook payloads.

step detail ms
✓ mcp: server starts and lists tools 13 tools, all described 0
✓ hooks: session start + prompt baseline snapshot, 84-token brief injected 318
✓ proof: requirements recorded 5
✓ context: find_symbol + deduplicated read cart.py:1: def total(prices, discount=0): 13
✓ memory: finds the fix from a past session 1 hit(s) 9
✓ swarm: helper answer is citation-checked 1/1 verified 40
✓ proof gate: blocks 'done' without evidence - Requirement #1 not verified: total() applies the discount 279
✓ rewind: wrong edit undone restored #1, undo with #2 39
✓ proof: tests pass, gate lets the agent finish exit 0, report report.html 309
✓ context: run_compact output 89 chars 20