Every decision also lands in Activity with a per-developer
consumer_id,
so you get an audit trail of what the org’s coding agents actually did — in
Report policy mode you can run all of this observe-only before enforcing.
This complements Claude Enterprise:
the hook screens the model request org-wide with zero endpoint install
(allow/deny only); the plugin is per-machine and controls actions, with Ask.
Most orgs run both — they stamp different source.application values
(claude-code vs claude-code-plugin), so gate them separately.
Under the hood the plugin registers Claude Code lifecycle hooks that call
POST /v1/evaluate with a collector tgk_… key.
Coverage
Ask — honoured natively, through Claude Code’s own permission dialog, on
prompts and on tool calls.
Use it when you want to stop a specific shell command or MCP call on
developer machines. Not when you expect to see or block the model’s
responses. For coverage a developer cannot bypass, add
Claude Enterprise.
Limits. The model’s response is never evaluated — there is no hook on
assistant output, and system prompts, token usage and extended thinking are not
captured.
ask on UserPromptSubmit does not stop the prompt: Claude Code has
no confirmation dialog there. No redaction. Tool declarations are not evaluated.
Full comparison: Coverage.
Three pieces
Hooks fire only when all three are present:claude plugin list showing the plugin installed is not enough. Status
must be enabled. Scope: managed only means the marketplace installed it.
Console setup
- Runtime → Collectors → Catalog → IDE & coding agents → Claude Code (or the Claude Code collector type your workspace lists).
- Auth — mint a
tgk_…key (shown once). - Policies — assign a default policy. Gate Ask / Block on
source.applicationeqclaude-code-pluginif this collector also receives other traffic.
Enable the plugin
Server-managed settings (claude.ai Admin → Claude Code → Managed settings) or/Library/Application Support/ClaudeCode/managed-settings.json:
pluginConfigs. No MCP URL — org-wide MCP (claude.ai, Desktop, Cowork,
Claude Code) is a separate organization connector, and
the collector tgk_… key is never an MCP credential.
enabledPlugins: true in the admin JSON does not always flip the CLI to
enabled. Claude Code skips server-managed settings when
ANTHROPIC_BASE_URL or CLAUDE_CODE_USE_* is set (including a TrustGate LLM
proxy). In that case deploy the file path above (Kandji:
TRUSTGUARD_DEPLOY_CLAUDE_MANAGED_SETTINGS=1).
Check on the laptop:
hooks.json loads.
Collector config + binary (MDM)
If the managed file has
api_key, that key, data_url, and fail_mode are
locked. Missing ~/.trustguard/bin is fine when the MDM binary exists.
Private GitHub repo: bootstrap curl of Releases 404s without a token
(fail-open). Kandji install can set TRUSTGUARD_GITHUB_TOKEN and pin the
release version.
fail_mode: open + an empty hook body {} means allow. That is also the
response when evaluate returns allow.
What is evaluated
Ask on PreToolUse shows Claude Code’s permission dialog. The subtitle is
the generic TrustGuard sentence above. The title (tool name) is Claude
Code’s; the plugin cannot change it.
Verify
source.application = claude-code-plugin means the binary and key work. If
Claude Code still never evaluates, the plugin is disabled or hooks did not
reload.
Remote SSH / WSL: hooks run on the remote host. A Kandji binary on the Mac
does not cover that session.
claude.ai / Desktop: no lifecycle hooks. Use Claude Enterprise and/or org
Connectors, not this plugin.