Skip to main content

Claude Code Integration

SigmaShake integrates with Claude Code in two complementary ways:

  1. MCP tools — Claude Code calls ssg_* tools directly to set up governance, search the Hub, write rules, and diagnose issues
  2. PreToolUse hook — Every tool call Claude Code makes is evaluated against your rules before it executes

Both are configured automatically by a single command.


Quick setup​

ssg init --client=claude-code

This writes to .claude/settings.json (macOS/Linux: ~/.claude/settings.json, Windows: %USERPROFILE%\.claude\settings.json):

  • Hook — registers ssg hook eval as a PreToolUse handler
  • MCP server — registers ssg mcp-server as ssg-governance
  • Permissions — 14 standard tools pre-approved, 18 destructive patterns pre-denied

Restart Claude Code once, then say:

"Set up SigmaShake governance for my project"


MCP Tools (AI-assisted setup)​

With the MCP server connected, Claude Code has access to 14 governance tools it can use autonomously. This table shows 3 of them as examples:

Ask ClaudeTool
"Set up SigmaShake for my project"ssg_onboard — one-shot project setup
"Check if governance is working"ssg_doctor — full health diagnostics
"Block kubectl in production"ssg_apply_rule — AI-authored rule

See MCP Server for the complete tool reference.


PreToolUse Hook (runtime protection)​

Every time Claude Code calls a tool, the PreToolUse hook runs ssg hook eval:

Claude calls: Bash("git push --force origin main")
↓
ssg hook eval evaluates against rules
↓
Decision: block
↓
Claude receives: "Force push is blocked."
Claude does NOT execute the command.

Hook configuration​

The PreToolUse entry written to .claude/settings.json:

{
"hooks": {
"PreToolUse": [
{
"matcher": "",
"hooks": [{ "type": "command", "command": "ssg hook eval" }]
}
]
}
}

The matcher field is an empty string so the hook fires for every tool call. ssg init repairs a non-empty matcher on re-install.

See One Source, Many Agents for why one rules source can govern multiple hosts via ssg init --client=<name>.

No circuit breaker​

The shipped Go hook has no circuit breaker. It never auto-allows a call after repeated DENY decisions. If a rule blocks all tool calls, fix or remove the rule (ssg list, ssg lint). A circuit breaker existed in the legacy TypeScript hook only (2026-10-11 note).


Permissions​

ssg init --client=claude-code pre-configures permissions.allow and permissions.deny so you don't need to whitelist tools manually.

Allowed (14 standard tools):

Bash(*), Read, Write, Edit, MultiEdit, Glob, Grep, Agent,
WebFetch, WebSearch, TodoWrite, TodoRead, AskUserQuestion, ToolSearch

Denied (18 destructive patterns):

Categories covered: recursive deletion, disk-level writes (dd, mkfs variants), shell history wipe, output redirect truncation, force-push variants, hard resets, force-clean, crontab writes, and raw secret-file reads (.env, .env.*, */secrets/*).

The exact entry strings are defined in the Go initClaudeCodePermissions.Deny list in internal/cli/init.go of the ssg source (2026-10-13: the earlier reference to a legacy TypeScript file was stale). The list also holds Bash(*cron*), so any command that contains cron is denied.

Permissions are merged additively — existing entries are never removed. Running ssg init again is safe.

Scope

By default ssg init --client=claude-code writes the hook to ~/.claude/settings.json (global), so every Claude Code session is governed regardless of which directory the agent is launched from.

To scope the hook to the current project directory only:

ssg init --client=claude-code --project-only

To write hooks and permissions to ~/.claude/settings.json globally (equivalent to the default, but can be re-run standalone to repair global settings):

ssg init --global

Allowed Domains and WebFetch mirroring​

When you add a domain to the Allowed Domains list in the SSG dashboard, SSG can mirror that entry into Claude Code's own WebFetch(domain:...) permissions in ~/.claude/settings.json. This means a domain trusted in SSG is also trusted by Claude Code's permission layer without a separate manual step.

The dashboard calls POST /api/allowed-domains/webfetch with {base, wildcard, op: "add"|"remove"}. A wildcard entry maps to both WebFetch(domain:base) (exact host) and WebFetch(domain:*.base) (subdomains). The host is validated server-side; no client-supplied strings are written verbatim.

This mirroring is best-effort and additive — the SSG .rules ALLOW is the source of truth for governance decisions. Removing a domain from Allowed Domains removes the corresponding WebFetch permission entry.


Tool capability mapping​

SigmaShake maps Claude Code's tool names to SSG capability categories for rule matching:

Claude Code ToolSSG Capability
Bashexecute
Readread
Write, Edit, MultiEditwrite
Glob, Grepsearch
Agentagent
WebFetch, WebSearchnetwork
Anything elseexecute (conservative default)

Write rules targeting capabilities, not individual tools:

DENY execute → blocks Bash
DENY write → blocks Write, Edit, MultiEdit
DENY network → blocks WebFetch, WebSearch

Human approval flow (ASK rules)​

When a rule uses ASK, the ssg hook sends the request to the dashboard and waits for your decision. The wait is not open-ended. The hook waits 20 seconds by default (45 seconds at most):

  1. The hook posts the pending decision to the dashboard at http://localhost:5599
  2. You approve or deny in the dashboard within the wait window
  3. The hook returns your decision and Claude Code continues

If you do not answer in time, the hook returns ASK to Claude Code and Claude Code shows its own ASK prompt. See Evaluation.

Start the dashboard before using ASK rules:

ssg serve

Agent monitoring​

Monitor Claude Code's Agent tool (sub-agent spawning):

rule log-explore-agents {
enabled true
LOG agent
IF input.subagent_type EQUALS "Explore"
MESSAGE "Explore agent activity logged."
}

rule block-background-agents {
enabled true
DENY agent
IF input.run_in_background EQUALS "true"
MESSAGE "Background agents require explicit approval."
}

The dashboard audit table shows agent subagent_type as inline badges.


Example rules for Claude Code​

Require approval for deployments​

rule require-approval-deploy {
enabled true
priority 90
severity error
ASK execute
IF command CONTAINS "deploy"
OR command CONTAINS "kubectl apply"
OR command CONTAINS "terraform apply"
MESSAGE "Deployment detected."
PROMPT "Allow this deployment?"
}

Block npm publish without approval​

rule require-approval-npm-publish {
enabled true
priority 90
severity error
ASK execute
IF command CONTAINS "npm publish"
MESSAGE "npm publish detected."
PROMPT "Allow publishing to npm registry?"
}

Log all file writes to src/​

rule log-src-writes {
enabled true
LOG write
IF path GLOB "src/**"
MESSAGE "Source file write logged."
}

Troubleshooting​

Hook not triggering​

Check the hook is registered:

cat .claude/settings.json | grep -A5 "PreToolUse"

Re-run if missing:

ssg init --client=claude-code

All tools being blocked​

Check for broad rules:

ssg list # show all active rules
ssg lint # check for syntax issues

MCP tools not visible in Claude Code​

  1. Verify ssg mcp-server starts cleanly:
    echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | ssg mcp-server
  2. Restart Claude Code (MCP connections initialize at startup)
  3. Check ~/.claude/mcp_config.json or .claude/mcp_config.json for the ssg-governance entry

ASK decisions not appearing in dashboard​

ssg status # check daemon is running
ssg serve # start dashboard at localhost:5599