
Self-hosted runtime control plane for AI agents. Observe or HITL approve or Block rogue tool calls before it executes: secret leaks, prompt injection, supply chain etc in a local dashboard. Agent agnostic (Claude,codex etc.)
Plus Grok Build, Crush, OpenHands, Qwen Code, Continue CLI, Goose, Hermes, OpenClaw, Devin CLI, Factory Droid, Aider, and more — see AGENT_INTEGRATIONS.md for the full coverage matrix
For the Skill, curl, and git-clone alternatives, plus PEP 668 systems and secret-cloaking setup, see the full installation guide.
tools/call is policy-evaluated before it forwards and each response is injection-scanned before the model sees it, so a poisoned tool result never becomes context. prismor mcp-gateway install moves an existing .mcp.json behind it_meta, and prismor tags lists, tests, and lints the rule expressionsuse_subject("user:alice") and a multi-tenant agent gets per-user attribution, per-user IAM profiles, and per-user suspensionprismor allow makes narrow exceptions, and prismor unlock opens a password-gated, time-boxed window in which an agent may edit policy (never the self-protection rules that guard Prismor itself)prismor tokens breaking down where a session's context and token spend actually wentprismor doctor health-checks every subsystem (hooks, policy signature, enrollment, telemetry sink, chain state), and prismor pause / pause-hard suspends enforcement only for a human during an incident while observe-mode logging keeps runningprismor trail verify proves the history hasn't been edited, deleted, or rewrittenprismor attest verifyprismor discover and flags any AI agent running without Prismor hooks (shadow AI)prismor ingest --discover replays on-disk session transcripts through the live policy engine, so the dashboard is populated on day one and you can see exactly what flipping a rule to enforce would have blocked, plus --coverage for sessions that ran unmonitoredFull command map across every capability: CLI Reference.
These capabilities map to the OWASP Top 10 for LLM Applications - covering prompt injection (LLM01), sensitive information disclosure (LLM02), supply chain (LLM03), improper output handling (LLM05), and excessive agency (LLM06).
Enforcement is decided per rule by your policy, not by a single global switch. Each rule carries a mode, and settings.default_mode (default observe) covers any rule that doesn't set one:
| Mode | Behavior |
|---|---|
observe (default) | Logs the tool call and the finding. Never blocks. Safe for onboarding and auditing. |
enforce | Blocks the action in real time before the agent executes it. |
Out of the box everything observes — nothing is blocked until you flip rules (or default_mode) to enforce in your policy:
# .prismor/policy.yaml
settings:
default_mode: observe # global default for rules without their own mode
rules:
- id: destructive-rm-rf
mode: enforce # this rule blocks; the rest still just observe
Policy is authoritative: a rule set to enforce blocks regardless of how the hook was installed (--mode), so an admin who flips a rule to enforce via the control plane blocks even on observe-installed devices. See Layered Policy & Exemptions for org / project / repo precedence and the non-overridable floor.
prismor setup makes the choice explicit rather than implied: an observe install ships with the defaults on, while an enforce install starts with nothing selected and asks you to pick what blocks (the safety floor is pre-marked recommended — press a to take it). Your selection is written to .prismor/policy.yaml as settings.selection: explicit plus one line per rule, so what blocks is readable in the file. When a rule then blocks something legitimate, the deny message prints the exact prismor allow <rule> --pattern '<literal>' that fixes it — for the human to run; agents are stopped from editing Prismor's own config by always-on self-protection rules, unless the human opens a short password-gated window with prismor unlock. See Choosing what blocks and Making exceptions.
The install flag still sets the starting posture, and an observe install combined with PRISMOR_LOCAL_DRY_RUN=1 acts as a local dry-run kill-switch that suppresses all blocking:
prismor install-hooks --agent all --mode observe # start in observe everywhere
prismor install-hooks --agent all --mode enforce # honor policy enforce rules
Upgrading from a pre-
moderelease? Backward compatibility is preserved: a policy that predates per-rule modes (it setssettings.block_categoriesbut nodefault_modeand no rule-levelmode) keeps its original behavior — those categories still block when installed with--mode enforce. The moment your policy adopts the per-rule model (anymode/default_mode), it becomes fully policy-authoritative as described above.
Three modules from Capabilities, with setup, output, and results.
Disabled by default. See docs/semantic-guard.md for full setup.
See docs/supply-chain.md for the full scoring table, ecosystem support, and IOC format.
This does not affect policy rules set to mode: enforce in .prismor/policy.yaml — those remain policy-authoritative regardless of how the hook was installed (see Observe / Enforce above).
Scoped Agent synthesizes a per-session allowed_tools/deny_tools list at .prismor/scoped/{session_id}.json. This check is independent of hook --mode — a tool in deny_tools is hardcoded to action: block / mode: enforce in prismor/runtime/scoped_agent.py, so it blocks even when hooks are installed with --mode observe. Uninstalling hooks or switching to observe mode will not lift a scoped denial.
prismor scope list # find the session ID
prismor scope show ID # inspect its allowed_tools / deny_tools (`latest` works too)
prismor scope clear ID # remove the scoped rules for that session
prismor scope edit ID # or hand-edit deny_tools in $EDITOR
There's no bulk-clear — each session is cleared by ID individually. If a session was scoped before you ran scope clear, the cleanest fix is usually to start a fresh session rather than chase the existing one's cached state.
See benchmark.md for the full methodology, per-category breakdown, and latency analysis.
PRs are welcome. Read CONTRIBUTING.md before you start — it explains the one thing that matters most here: reuse the mechanisms that already exist, and solve the problem in the fewest lines you can. Smaller diffs get merged faster.
The short version:
prismor/runtime/default_policy.yaml, following the schema in prismor/runtime/policy_schema.json — detection patterns never go in Pythontests/ — run bash scripts/run_security_tests.sh before opening a PRBy participating you agree to the Code of Conduct.
| Agent | Project scope | User scope |
|---|
| Claude Code | <workspace>/.claude/settings.json | ~/.claude/settings.json |
| Cursor | <workspace>/.cursor/hooks.json | ~/.cursor/hooks.json |
| Windsurf | <workspace>/.windsurf/hooks.json | ~/.codeium/windsurf/hooks.json |
| OpenClaw | <workspace>/.openclaw/plugins.json | ~/.openclaw/config.json |
| Hermes | <workspace>/.hermes/plugins.json | ~/.hermes/config.json |
| Codex | <workspace>/.codex/hooks.json | ~/.codex/hooks.json |
| Copilot | <workspace>/.github/copilot/hooks.json | ~/.copilot/hooks.json |
| Grok Build | <workspace>/.grok/hooks/prismor.json | ~/.grok/hooks/prismor.json |
| Kiro CLI | <workspace>/.kiro/agents/kiro_default.json | ~/.kiro/agents/kiro_default.json |
| Crush | <workspace>/crush.json | ~/.config/crush/crush.json |
| OpenHands | <workspace>/.openhands/hooks.json | ~/.openhands/hooks.json |
| Qwen Code | <workspace>/.qwen/settings.json | ~/.qwen/settings.json |
| Continue CLI | <workspace>/.continue/settings.json | ~/.continue/settings.json |
| Goose | <workspace>/.agents/plugins/prismor/hooks/hooks.json | ~/.agents/plugins/prismor/hooks/hooks.json |