Mist
MFA for agentic AI. Mist scores every prompt and tool call in Claude Code on a 7-axis risk vector (overall, financial, destruction, comms, access, production, scale). High-risk actions get gated. Approval happens silently when you're at a bound location anchor — otherwise it falls through to Claude Code's native terminal prompt with the risk score attached.
Install
Want to try Mist in a sandbox first? See DOCKER.md for a Docker lab that runs Claude Code + Mist in an isolated container without touching your host config.
Recommended (interactive, inside Claude Code)
In an active Claude Code session:
/plugin marketplace add github:percent-20/mist-plugin
/plugin install mist@mist
Claude Code clones the repo into its plugin cache, registers the marketplace, and enables the plugin's hooks declared in settings.json. Restart the session if hooks don't fire immediately.
If the hooks fail at runtime with "Cannot find module" errors, install the plugin's npm dependencies once in the cached copy:
cd ~/.claude/plugins/cache/mist/mist/<version>
npm install
(Required only if your Claude Code version doesn't auto-install plugin dependencies.)
Non-interactive (CI / scripted setups)
Add the marketplace + plugin entries to ~/.claude/settings.json directly:
{
"extraKnownMarketplaces": {
"mist": {
"source": { "source": "github", "repo": "percent-20/mist-plugin" }
}
},
"enabledPlugins": { "mist@mist": true }
}
Restart Claude Code. The plugin gets fetched and enabled on next session start. This is the pattern the Docker lab uses (see DOCKER.md).
Local development
Clone the repo, install deps, then point Claude Code at it via a local marketplace source:
git clone https://github.com/percent-20/mist-plugin
cd mist-plugin
npm install
Then add to ~/.claude/settings.json:
{
"extraKnownMarketplaces": {
"mist-local": {
"source": { "source": "local", "path": "/absolute/path/to/mist-plugin" }
}
},
"enabledPlugins": { "mist@mist-local": true }
}
Edits to source files are picked up after /reload-plugins or a session restart.
Standalone classifier CLI (no Claude Code)
The npm package also ships a mist-classify command for shell use — handy for evaluating prompts without booting Claude Code:
npm install -g @percent20/mist-plugin
mist-classify "buy 50000 macbook pros"
Or smoke-test the hooks directly from a clone:
echo '{"prompt":"buy 50000 macbook pros"}' | node hooks/user-prompt-submit.js
# → {"hookSpecificOutput":{"permissionDecision":"ask","reason":"Mist gate (overall=9, financial=9, scale=9): buy 50000 macbook pros"}}
node bin/classify.js "transfer 50000 dollars to account 1234567890"
# → vector: [9,9,0,0,0,0,9] gate: FIRES (overall>=7, financial>=5, scale>=8)
Either path is zero-config — Mist becomes active the moment the plugin loads. No keys, no pairing required. The plugin uses your existing ANTHROPIC_API_KEY to run a tiny Haiku classifier locally, and surfaces high-risk requests through Claude Code's built-in approval prompt with the risk score attached.
Optional bubble binding (recommended)
Bind a Mist bubble — a vault tied to a physical location — and Mist will auto-approve silently whenever you're inside it. No prompt, no notification, sub-second.
/mist init ← first-time setup (API key + initial bubble bind)
/mist bind ← re-bind to a different bubble later
The SafeRoom app maintains the location signal that determines bubble membership. You install SafeRoom once, set the anchor, and forget about it. When Claude Code does something risky and you're at the bound location, the gate disappears.
If you're outside the bubble, the gate denies by default. Run /mist rules policy ask to fall back to the native terminal prompt instead — useful for developers who travel; not recommended for headless / cloud Claude Code instances where there's no human at the terminal to ask.
What gets gated
The classifier outputs seven integers 0–9:
overall, financial, destruction, comms, access, production, scale
A challenge fires when ANY axis crosses its threshold. Defaults:
overall >= 7
financial >= 5
destruction >= 3
comms >= 8
access >= 7
production >= 6
scale >= 8
Tune via /mist rules set <category> <threshold>.
Examples of what scores trigger:
- "explain typescript generics" →
0,0,0,0,0,0,0 — silent
- "rm -rf node_modules" →
4,0,5,0,0,0,1 — gate fires (destruction>=3)
- "buy 50000 macbook pros" →
9,9,0,0,0,0,9 — gate fires
- "git push --force origin main" →
7,0,5,0,0,8,2 — gate fires
- "delete the production database" →
9,0,9,0,0,9,4 — gate fires
- "clean up the warehouse inventory db" →
3,0,3,0,0,0,2 — gate fires (destruction>=3, the borderline case)
How approval works
When the classifier crosses a threshold: