paranoid_
Integrate

Integrations

Ways to run paranoid in a workflow: the GitHub Action, a pre-commit hook, and Claude Code (a Stop hook and an MCP server). All of them run the same binary you use locally.

GitHub Action

The composite action at alainrk/paranoid/action@main runs verify on the pull request range, uploads the report as an artifact, appends it to the job summary, optionally posts a sticky PR comment, and sets the check status from the verdict. Full inputs, outputs, and the SARIF upload example are on the Exit codes & CI page.

- uses: alainrk/paranoid/action@main
  with:
    sandbox: none # or auto, when the runner has docker
    claims: summary.md # optional

pre-commit

This repository ships .pre-commit-hooks.yaml with one hook, paranoid-verify. Add it to a target project's .pre-commit-config.yaml:

repos:
  - repo: https://github.com/alainrk/paranoid
    rev: main # pin a tag or commit
    hooks:
      - id: paranoid-verify

Then, in the target project:

pre-commit install --hook-type pre-commit --hook-type pre-push
pre-commit run paranoid-verify --all-files # try it once by hand

What the hook runs

paranoid verify --sandbox none --offline --base HEAD

The commit range at each stage

stages: [pre-commit, pre-push] runs the same command at both points. --base HEAD covers different changes at each point.

To raise the bar, add args: [--fail-under, "80"] (or any other verify flag) to the hook entry in the target project's own .pre-commit-config.yaml. pre-commit appends args after entry.

The golang hook language

pre-commit's golang language builds the hook's own repository with go install ./... inside an isolated Go environment it manages itself. Since this repo has a go.mod at the root and its command lives at cmd/paranoid, that install produces a binary named paranoid (Go names the binary after the directory holding package main), which lands on PATH inside pre-commit's environment and matches the hook's entry line. No manual install step or wrapper script is needed. A Go toolchain is required, and pre-commit's golang language can provide one.

There is no GitLab CI component or merge-request comment integration.

Claude Code

A settings.json hook config and an MCP server. The hook is configuration only and needs no extra Go code. Full docs, the settings snippet, and the security notes: integrations/claude-code/README.md.

Stop hook and PreToolUse variant

{
  "hooks": {
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "paranoid verify --sandbox none --offline --format text --fail-under 80 --strict 1>&2"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(git commit *)",
            "command": "paranoid verify --sandbox none --offline --format text --fail-under 80 --strict 1>&2"
          }
        ]
      }
    ]
  }
}

Copy the hooks block into .claude/settings.json (committed, shared) or .claude/settings.local.json (personal). Claude Code's Stop hook contract blocks the session only on exit code 2, with the command's stderr fed back as the reason; the trailing 1>&2 redirects verify's report (stdout by default) to stderr so Claude receives it, and --strict maps a warn verdict onto exit 2 too, since a plain exit 1 does not block. The PreToolUse variant uses Claude Code's if field to match the Bash tool's command text (Bash(git commit *)). This scopes a hook to one command; matcher alone only matches the tool name.

MCP server

paranoid mcp runs a Model Context Protocol server over stdio: newline-delimited JSON-RPC 2.0, implemented on the standard library with no SDK dependency. It implements initialize, tools/list, and tools/call for one tool, verify (arguments: path, base, head, claims, session, offline, sandbox), which runs the same pipeline as paranoid verify and returns the JSON report as the tool result. To add it to Claude Code as an MCP server:

{
  "mcpServers": {
    "paranoid": {
      "command": "paranoid",
      "args": ["mcp"]
    }
  }
}

Trust boundary

Both integrations depend on the binary they run and the files that configure them. If the agent under audit can edit the installed paranoid binary, .paranoid-baseline.json, or the hook configuration, it can make paranoid say pass. Install paranoid outside the repository the agent can write to, and point the hook at that installed binary on PATH, never a repo-local build. SF006 watches .paranoid-baseline.json and hook configuration files for this reason. It does not prevent the edit. It reports the edit as a finding in the next run.