Claude Code
The api-governance plugin at tag v1.2.1 is version 1.2.1, and that plugin carries the mod.
The api-governance plugin at tag v1.2.3 is version 1.2.3.
Claude Code asks for the plugin's api_key option when you install or enable the plugin in /plugin, and you set it with /plugin configure api-governance@coderifts, or from a shell with claude plugin configure api-governance@coderifts --values-stdin and the api_key value on stdin.
The key is stored in your platform's secure credential store, not in settings.json.
The plugin no longer reads the CODERIFTS_API_KEY or CODERIFTS_API_BASE environment variables (before 1.2.2 it did), and the coderifts CLI still reads CODERIFTS_API_KEY.
Since 1.2.2 the plugin asks for the key through its userConfig api_key option, and that option is marked sensitive.
On 2026-10-03 the marketplace file on main lists agent-hooks at version 0.2.2.
The same file at tag v1.2.1 lists agent-hooks at version 0.2.0.
On every Write, Edit and MultiEdit call that touches a contract file, the mod holds the call until preflight answers, and any other decision, an error, an answer it cannot read, or no answer within 8 s is refused.
A CONTINUE or CONTINUE_WITH_MONITORING answer runs the call, and so does no break detected when there is no API key.
Without a key the no-break path is analyze, which is not an authorization.
A Write, Edit or MultiEdit call that does not touch a contract file is not refused.
The catch refuses the call when the check fails before the tool runs.
When the tool has already run, the catch still returns a deny and says the change is unchecked.
The band is for the turn.
It leads with that turn's refusal, and when the turn has both a refusal and an allowance it appends a count of how many were refused and how many were allowed this turn.
A new turn clears the band.
With one refusal and one allowance in the turn, the count text is · 1 refused, 1 allowed this turn.
The refusal mark is ✗ CodeRifts.
Installed as a mod, it is one of the mods the user installed: a mod that runs before it can answer or rewrite the call, or what this mod reads, so it never sees the change; disableAllHooks in any settings file (the .claude/settings.json of the project included), --safe-mode or --bare turns it off.
Only an organization mod (installed in place from a marketplace directory the administrator owns, and enabled in managed settings) runs before the mods users install and keeps its refusal for the calls it sees; installed from its GitHub marketplace this plugin never counts as one, and --safe-mode or three crashes of the hooks worker unload even that.
This mod (api-governance 1.2.3) does not inspect shell commands: a shell write to a contract file passes it; the required check is the guarantee.
The install lines at tag v1.2.1 are /plugin marketplace add coderifts/api-governance and /plugin install api-governance@coderifts.
/plugin marketplace add coderifts/api-governance
/plugin install api-governance@coderifts
The project-scope option is labeled Install for all collaborators on this repository (project scope).
That option enables the plugin for everyone who works in this repository.
Committing that entry turns the plugin on for your collaborators but does not download it to their machines, so each collaborator also runs claude plugin install api-governance@coderifts --scope project once.
Read on 2026-10-03, claude --version printed 2.1.288 (Claude Code) and claude plugin list printed api-governance@coderifts version 1.2.1, enabled, scope user, and agent-hooks@coderifts version 0.2.2, enabled, scope user.
The mods overview documents a dim line such as 1 mod active · first-mod. This round did not open /plugin, so that line is not measured for api-governance.
The module comment at tag v1.2.1 says that on 1.2.0 the mod refused the breaking edit and allowed a second edit in the same turn, and that the 1.2.0 band showed only the last one.
This round did not repeat that edit.
ADVISORY · TOOL CALL · TIMEOUT AND UNMATCHED TOOLS PASS THROUGH
This host passes a stalled hook through. Its documentation says so plainly: do not count on a stalled hook to act as a gate. Our adapter therefore returns a hard refusal on every internal failure, rather than trusting the host to stop.
Two routes. The catalogue is the short one.
claude plugin marketplace add coderifts/api-governance
claude plugin install agent-hooks@coderifts
✔ Successfully installed plugin: agent-hooks@coderifts (scope: user)
The block below is the 2026-09-26 plugin list, which printed 0.2.0.
agent-hooks@coderifts
Version: 0.2.0
Scope: user
Status: enabled
Or wire it yourself, if you would rather pin the path. A version pin is not a security audit nor an integrity check.
npm i @coderifts/agent-hooks
Then one entry in your project's .claude/settings.json — the package ships it at claude-code/settings.snippet.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit|MultiEdit|Bash",
"hooks": [
{
"type": "command",
"timeout": 8,
"command": "node",
"args": [
"${CLAUDE_PROJECT_DIR}/node_modules/@coderifts/agent-hooks/claude-code/hook.mjs"
]
}
]
}
]
}
}
timeout is in seconds — the host's unit, and deliberately low: our own budget is 5000 ms, so a slow answer becomes a readable approval request rather than a host-level pass-through.
Optional environment: CODERIFTS_API_KEY, CODERIFTS_ENDPOINT, CODERIFTS_TIMEOUT_MS. Without a key the gate runs in analyse mode and every gated call ends at a human — there is no setting that makes an unanswered call pass.
That optional environment is the npm hook path, not the api-governance plugin, which does not read CODERIFTS_API_KEY.
@coderifts/agent-hooks 0.3.1. A write to a named contract file is denied. A write that can reach a contract file without naming it asks, and it asks only when a contract file is under that directory. Published 2026-10-04. When CodeRifts could not decide, the refusal says GOVERNANCE_UNAVAILABLE: CodeRifts could not decide (why); this is not a finding about your change. This is that package. It is not the api-governance 1.2.3 mod, and it is not the coderifts CLI.
A PreToolUse hook installed outside managed settings does not prove the call was refused: since Claude Code 2.1.287 a user-installed mod runs before it, can answer the call so the hook never runs, and can approve a call the hook blocked; only a hook in managed settings is final.
Source, read 2026-10-03: code.claude.com/docs/en/plugins/mods/events and code.claude.com/docs/en/plugins/mods/overview.
Measured 2026-09-26 (external run). Plugin marketplace add, plugin list, and agent-hooks. This page did not re-run the host.
One file for a fleet is a different step. One file puts the hook on every machine; the required check makes it a gate.
Indexed from r/ClaudeAI, 2026-06-22 (the thread URL returned no body on this run): “CLAUDE.md says what you would like to happen. A hook decides what is allowed to happen.” The wording looked for on that forum, “Use hooks — if a restriction matters, don’t rely on Claude remembering prose in CLAUDE.md once the context gets crowded”, was not found. The carrier informs, the hook stops, and the required check forces. audit what happened under the allow list. The same split is on what each path does.
Measured 2026-09-26 (external run) — plugin marketplace add, plugin list, and agent-hooks. This page did not re-run the host.