Skip to content

Claude Code Governor (mod)

The TapPass Governor is a Claude Code mod that puts TapPass in the loop of Claude Code’s own agent runtime. Before every tool call and every model request, it calls POST /v1/govern, acts on the verdict, and draws a live governance panel inside Claude Code.

It is the fuller sibling of the PreToolUse hook. Use whichever fits:

PreToolUse hook Governor mod (this page)
Governs tool calls Yes Yes (built-ins, MCP, and subagent calls)
Governs model requests (LM calls) No Yes (every turn.step)
Live panel in Claude Code No Yes
Install Python SDK command A mod directory, no Python
Needs Claude Code hooks Claude Code v2.1.287 or later

Pick the hook when you only need tool-call governance and already use the Python SDK. Pick the mod when you want every model request governed too, or the live panel.

  • Claude Code v2.1.287 or later. Check with claude --version.
  • A reachable TapPass instance (local dev, staging, or production).
  • A tp_dev_ data-plane agent key. The key is the whole credential: TapPass resolves the agent and session identity from it server-side, so you do not pass an agent id.

The mod lives in the TapPass repository at integrations/claude-code-governor/. Clone or copy that directory to a path of your own, for example ~/mods/tappass-governor.

Terminal window
git clone https://github.com/tappass/tappass.git
cp -r tappass/integrations/claude-code-governor ~/mods/tappass-governor

Load the mod for a session with --plugin-dir:

Terminal window
claude --plugin-dir ~/mods/tappass-governor

The first time the mod is enabled, Claude Code prompts for its configuration. Approve it, and the TapPass Governor pane opens.

All settings are userConfig fields, set when you enable the mod. You can change them later with /config.

Field Default Meaning
tappass_token (none) Your tp_dev_ key, used as the Authorization: Bearer token for POST /v1/govern. It is marked sensitive, so Claude Code stores it in the OS secure credential store, not in settings.json. If you leave it empty, the TAPPASS_AGENT_KEY environment variable is used as a fallback. With no key at all, the mod still loads and records every action as unverified.
tappass_base_url https://app.tappass.ai The TapPass API base. Use http://localhost:PORT for local dev, or your staging URL, to switch environments. The token is sent only to this URL.
enforcement_mode enforce enforce blocks denied actions. shadow records and renders verdicts but never blocks, so you can watch what a policy would do before you turn it on.
fail_mode open open lets an action run when TapPass is unreachable (recorded as unverified). closed blocks it.
agent_id (none) Advisory only. Ignored for tp_dev_ keys, which TapPass resolves identity from. Set it only when you use an admin key.

Set tappass_base_url to point the mod at the TapPass you want to govern against:

  • Local dev: http://localhost:9620 (or the port your dev server uses).
  • Staging: your staging host.
  • Production: https://app.tappass.ai.

The panel labels the environment it is talking to (local, staging, or prod), so you always know which TapPass is deciding.

  • Every tool call flows through the mod’s tool.call handler. This covers Claude Code’s built-in tools (Bash, Edit, Write, Read, and so on), MCP tools (mcp__server__tool), and tool calls made by subagents. The mod sends a TOOL_CALL behavior with the tool name, the arguments, and, for an MCP tool, the server parsed from the tool name.
  • Every model request flows through the mod’s turn.step handler. The mod sends an LLM_CALL behavior with the model and the recent messages. A blocked model request is answered without ever reaching the model, and the turn is aborted.
Verdict outcome enforce mode shadow mode
allow (with a mandate) proceed proceed
allow without a mandate treated as block proceed
block, escalate deny the tool, abort the model request record only, proceed
needs_approval ask you to approve or deny the tool, abort the model request record only, proceed

A redaction or rewrite returned by TapPass as modified_payload is applied to the tool’s arguments before the tool runs.

The pane shows, live:

  • The environment, the mode (ENFORCE or SHADOW), and whether a key is configured.
  • Running counts of allow, block, approval, and unverified decisions.
  • The most recent verdicts, each with the tool or model name, the outcome, and the round-trip latency.

A blocked action also raises a toast with the reason.

  1. Start with enforcement_mode: enforce against a TapPass that has a policy you can trigger (for example, a rule that blocks Bash commands containing rm -rf, authored from a template or in plain English).
  2. Ask Claude Code to run a harmless tool. Confirm a verdict row appears in the panel.
  3. Ask it to run the action your policy blocks. Confirm the tool is denied, the reason appears, and a toast is shown.
  4. Switch enforcement_mode to shadow. Confirm the same action is now recorded as it would be decided, but is no longer blocked.
  5. Stop TapPass. With fail_mode: open, confirm actions run and are recorded as unverified. With fail_mode: closed, confirm they are blocked.
  • The panel does not open, or /plugin does not list the mod. The module did not load. Run claude plugin validate ~/mods/tappass-governor and fix what it reports.
  • Everything is unverified. No key is configured. Set tappass_token, or export TAPPASS_AGENT_KEY.
  • Every action is blocked and the reason mentions a 401. The key was rejected. Check that it is a valid tp_dev_ key for the tappass_base_url you set.
  • Actions are blocked only while TapPass is down. fail_mode is closed. Set it to open to let work continue when TapPass is unreachable.

The mod ships with a test suite that runs with no network and no sign-in:

Terminal window
cd ~/mods/tappass-governor
claude plugin test