Part of the CLK documentation. Test suites and how to run them.
CLK ships three test suites and a one-command orchestrator that runs them all in an ephemeral Docker container.
| Suite | What it covers | Runner |
|---|---|---|
tests/ |
Unit + integration regression tests (CI-gated) | pytest |
user_tests/ |
End-to-end CLI / REST API / kickoff.sh user tests |
pytest |
pi-extension/tests/ |
TypeScript Node tests for the Pi extension | npm |
# Interactive: prompts for LLM provider, API key, base URL, model.
# Builds an ephemeral Docker image, runs every suite inside, then tears
# the container down (success or failure).
./scripts/run_all_tests.sh
# CI / scripted use — skip the prompts and use the shell provider:
./scripts/run_all_tests.sh --non-interactive
# Single suite (no Docker, runs directly on the host):
./scripts/run_all_tests.sh --local --suite=user
./scripts/run_all_tests.sh --local --suite=ci
./scripts/run_all_tests.sh --local --suite=piThe interactive menu asks four questions:
- LLM provider (shell / claude / codex / gemini / pi / ollama / openwebui)
- Auth mode (cli vs apikey) for the CLI-driven providers
- API key, base URL, model name — only for the chosen provider
- Confirm + go
All deterministic tests (CLI plumbing, REST API contract, etc.) run
against the shell provider regardless — they need no credentials and
always succeed. The opt-in real-provider smoke test
(test_kickoff_with_user_selected_provider in user_tests/) runs
kickoff.sh end-to-end with whatever provider you selected, and the
pi-extension runtime smoke verifies the pi CLI is reachable when you
chose pi and gave it a model + key.
run_all_tests.sh (Docker mode):
- Builds
clk:tests-<pid>from the projectDockerfile. - Mounts the repo read-only at
/repo, copies it into a writable/workinside the container. - Runs
pytest tests/thenpytest user_tests/thennpm testinsidepi-extension/. - Always tears down the container on exit (success, failure, or
^C) and removes the ephemeral image, unless
--keepis passed.
Useful flags:
| Flag | Effect |
|---|---|
--local |
Run on the host directly; no Docker daemon required. |
--non-interactive |
Skip all prompts; force CLK_PROVIDER=shell. |
--suite=all |
Default — run all three test directories. |
--suite=ci |
Only tests/ (regression). |
--suite=user |
Only user_tests/. |
--suite=pi |
Only pi-extension/tests/. |
--keep |
Don't remove the container or image on exit. |
--no-build |
Reuse a pre-built clk:tests-latest image. |
-k <expr> |
Forward a -k filter to pytest. |
-- <args> |
Pass remaining args verbatim to pytest. |
Each suite is just pytest / npm and can be invoked on its own:
# Regression suite (existing CI tests)
pip install -e ".[api,dev]" pytest pytest-asyncio httpx
pytest tests/ -v
# User-perspective end-to-end suite (CLI subprocess + live REST API +
# real kickoff.sh runs). Uses the shell provider — no API keys needed.
pytest user_tests/ -v
# Pi extension TypeScript suite
cd pi-extension
npm install
npm test # unit + integration tests (96 tests, ~2s)
npm run test:strict # also runs `tsc --noEmit`The user_tests/ suite verifies, from a real user's vantage point:
- Every
clksub-command (init,idea,cast,roles,plan,run,loop,status,providers,configure) exits cleanly and writes the documented.clk/artefacts. - All seven shipped providers register and the
shellprovider is always available. - The REST API serves health, capabilities, workflows, workspace CRUD, research task creation, SSE streaming, artifact listing, path traversal blocking, and cancellation.
kickoff.shproduces a self-contained workspace dir with its own git repo, and respects--provider/CLK_PROVIDERoverrides.- Filesystem invariants (commit history,
.clk/runs/shell-stubs/, per-command.clk/logs/<cmd>-<ts>.log, etc.).
The pi-extension/tests/ suite verifies:
classifyError,withRetry,looksRedacted,isMaxTurnsResult, and allrecoveryHintbranches.clkChiefPrimerrenders the captured idea + every CLK tool name (clk_cast,clk_subagent,clk_subagent_quality,clk_consensus,clk_autoresearch,clk_ralph,clk_checkpoint,clk_done).scoreResponseflags every documented failure mode (empty / refusal / malformed ACTION / malformed POST / missing outputs / low confidence / needs-review / missing-confidence) andrepairHintquotes each reason to the worker.runConsensusfans out N samples, scores them, picks the winner, caps tomaxParallel, and captures spawn errors without throwing.dispatchWithQualityretries with a repair preamble on recoverable failures and stops on refusal ormaxRetries.setIdea,setRoster,appendProgress,markDone,isDoneround-trip state through.clk/state/*.jsonandprogress.md.- The
gitwrapper does init, checkpoint, branch, merge, revert,hasRemote,commitsAhead, andpushBestEffortcorrectly against a realgitbinary (including the bare-upstream sync, the unreachable- remote failure path, and the no-remote no-op). - The extension's
defaultexport registers every documented tool (clk_cast,clk_progress,clk_checkpoint,clk_revert,clk_branch,clk_merge,clk_done,clk_consensus,clk_subagent_quality,clk_autoresearch,clk_ralph,clk_subagent) and the/clkslash command, and handles an empty-idea invocation cleanly. firstLineShortreturns single-line, capped output so a multi-line idea never bleeds line 2 into the Pi status bar.