Claude Code

Run checks on Ciresk CI from Claude Code: a CLAUDE.md snippet, a hook that gates git push, and the MCP endpoint.

Three pieces, each optional on its own. The contract behind them is in How it works.

Instructions

Append this to the repository's CLAUDE.md. The nearest CLAUDE.md wins in a monorepo, the same rule the manifest follows.

CLAUDE.md
## Verification (Ciresk CI)
- Check your change: `ciresk ci check` (remote, the exit code is the result). Exit 0 means pass; 1 means a task or test failed; 2-8 name the reason (usage, auth, policy, budget, cancelled, timed out, infra).
- Tests for one crate or package: `ciresk ci test -p <crate>`; the whole suite only when asked: `ciresk ci test`.
- On failure read the summary first, then `ciresk ci tests <job>` and the `next` command it prints; never ask for a whole log.
- Never run `cargo test`, `cargo clippy`, `pnpm test` or workspace-wide builds here: the hook denies them and names the replacement; locally only `cargo check -p <crate>` or `pnpm typecheck`.
- `git push` and `gh pr create` are gated by a hook that runs `ciresk ci check`; a denied call shows the summary, fix it and retry.
- Show the job id and the summary as evidence before saying a change is done; never claim success without a `succeeded` verdict.
- Through MCP (`ciresk` server): start the job from the shell with `ciresk ci run <kind> --json` (it uploads the working tree and prints `data.id`), or call `run` with kind, repo slug and `tree_root` set to that output's `data.tree.root` (`wait_s: 45` returns the summary when the job finishes in time), then `job_wait` (up to 55 s per call, obey `poll_after_ms`); `job_tests` and `job_logs` are the drill-downs; `job_cancel` asks for confirmation; `jobs_list` and `job_artifacts` are read-only.

The hook

Instructions are requests; the hook is what Claude Code runs on every shell call. It looks at each command of a chain or pipeline on its own: cargo test, cargo nextest, cargo clippy, workspace-wide cargo build or cargo check, and pnpm test or pnpm build (and the npm, yarn and bun equivalents) are denied with the ciresk ci command that replaces them. Before a git push or gh pr create (as the first command or after ;, &&, ||, |) it runs ciresk ci run check --wait --json, and when the exit code is not 0 denies the call with the summary as the reason: verdict, job id, failing tests with file:line, the last 20 lines of the failed task and the next command. Everything else, and exit 0, lets the normal permission flow continue.

.claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash|PowerShell",
        "hooks": [
          { "type": "command", "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/ciresk-check.sh\"", "timeout": 1800 }
        ]
      }
    ]
  }
}

The hook is two files from tools/ci/integrations/claude-code/ in the Ciresk source repository: hooks/ciresk-check.sh and settings.json (on Windows without Git Bash, hooks/ciresk-check.ps1 and settings.windows.json). That repository is not public yet and the installer does not ship these files, so outside Ciresk they are not available today. What every installed CLI has is the smaller guard below, ciresk ci hook pretooluse, which denies workspace-wide cargo runs but does not gate git push; for the push gate use the git pre-push hook, whose script is printed on that page. Inside Ciresk, copy the two files into the repository:

Terminal
mkdir -p .claude/hooks
cp ciresk-check.sh .claude/hooks/ && chmod +x .claude/hooks/ciresk-check.sh
cp settings.json .claude/settings.json      # or merge the "hooks" key into an existing file
KnobEffect
CIRESK_CI_SKIP=1Skips the hook while it is set.
CIRESK_CI_BINThe CLI binary the hook runs; by default the program behind ciresk ci.
A missing jq or binaryDenies with a message that says so, never silently passes.

The hook does not print or store the token: the CLI reads it from the OS keychain or CIRESK_CI_TOKEN. The timeout of 1800 s is there because a check can take minutes. A smaller guard is built into the CLI as ciresk ci hook pretooluse: it reads the hook document on stdin and denies workspace-wide cargo build|check|clippy|test|nextest --workspace runs with the reason that they go through Ciresk CI. It needs no file in the repository besides the settings:

.claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash", "hooks": [{ "type": "command", "command": "ciresk ci hook pretooluse" }] }
    ]
  }
}

MCP

Point Claude Code at the cell's MCP endpoint. No token goes into the file: Claude Code discovers OAuth from the endpoint's protected-resource metadata; run /mcp once to log in. Tools appear as mcp__ciresk__run, mcp__ciresk__job_summary and so on, which is also the name a hook matcher uses.

.mcp.json
{
  "mcpServers": {
    "ciresk": {
      "type": "http",
      "url": "https://ci.eu.ciresk.com/v1/ci/mcp"
    }
  }
}

The tools and what each returns are in How it works.

Start the watcher for the session

An agent session edits many files and runs ciresk ci check often. Run ciresk ci watch in a background shell at session start (a SessionStart hook or the first command): it keeps the tree index current, pre-uploads changed files and writes a heartbeat the CLI trusts for 3 s, so every check is one request to queued. A hook that cannot keep a process runs ciresk ci watch --once --json right before the check.

Attribution and trust

A job started inside Claude Code carries actor: agent:claude-code and the session id, and runs at your own tier: a coding agent under your key is your tool. An organization that wants agent jobs isolated turns on the agent_branches_untrusted policy, which runs them as untrusted; CIRESK_ACTOR or --actor sets another actor. See Workers and trust. Tokens, prompts and transcripts are not sent.