Snag — Guardrails for AI coding agents. Intercept, compile, learn, improve.
Project description
Snag
Guardrails for AI coding agents. Hook-level interception where supported, MCP-guided enforcement everywhere else. Catch bad code before it lands. Learn from every correction. Dispatch agents to fix what they find.
pip install snagged
sg init
That's it. Two commands. pip install snagged gets the CLI. sg init does everything else — detects your agents, scans your codebase, installs hooks, configures MCP, sets up the background daemon, and starts protecting your code. No config files to write. After init, Snag picks the strongest integration path per agent (hooks, MCP, or wrappers) and runs automatically.
For a fully unattended install (CI, scripting, or if you just trust Snag):
pip install snagged
sg init --yes
--yes auto-installs the linter, daemon, and hooks with sensible defaults. Without it, sg init walks you through each step with prompts (defaults are always "yes" — just hit Enter).
Cursor Quickstart
pip install snagged
cd your-project
sg init
# Restart Cursor when prompted
sg init auto-creates .cursor/mcp.json with 12 MCP tools and installs .cursor/rules/snag-mcp.mdc so Cursor's agent calls Snag automatically. No API keys needed — all guardrails run locally with pattern matching, zero LLM calls. After init, restart Cursor to pick up the new MCP config.
If something looks wrong, run sg doctor to check the setup.
Why
AI agents write code fast. They also write hallucinated imports, hardcoded secrets, bare excepts, console.log everywhere, and the same bug you fixed yesterday.
Snag fixes this. It sits between your agent and your codebase — invisible, automatic:
- 166 guardrails catch security issues, bad patterns, and hallucinations on every write
- Zero-cost fixes — pattern matching, no LLM calls, no API keys needed for core features
- Learns from you — correct your agent once, Snag applies it everywhere going forward
- Works side-by-side with everything — Claude Code, Cursor, Codex, Copilot, Windsurf, OpenClaw, Aider, Goose, Gemini CLI, and more
- Dispatches agents — finds issues proactively and sends fix tasks to OpenClaw, Claude, or Codex
Agent writes file --> Snag compiles it --> Bad code fixed silently --> Agent never knows
Zero cost by default
The compiler, guardrails, loop detection, and convention enforcement all run locally with pure pattern matching. No API calls. No tokens burned. You can optionally enable model-powered analysis during sg init if you have an API key, but it's never required.
How It Works
Snag has two loops that reinforce each other:
Loop 1: Real-time (per write)
WATCH Post-write hook intercepts agent file write
TRANSFORM Compiler runs 166 guardrails using project context
LEARN If you correct a transform, your preference is recorded
IMPROVE Next transform uses your preferences — fewer false positives
On hosts with native tool hooks (Claude Code), this runs on every write automatically. On MCP-only hosts, the same compiler is available through Snag MCP tools and daemon dispatch.
Loop 2: Proactive (background)
WATCH Daemon scans codebase on schedule (hourly/daily)
DETECT Finds violations of your learned preferences + dead code + security issues
ASK Notifies you and asks for consent
DISPATCH On approval, sends fix task to OpenClaw/Claude/Codex
LEARN Fix result feeds back into your profile
Both loops feed the same behavioral profile. A correction caught in Loop 1 strengthens a preference that Loop 2 uses to proactively scan. They reinforce each other.
The Compiler
3-phase compilation on every write:
Phase 1: Your preferences — learned from corrections. You fixed os.path to pathlib three times? Every future write auto-transforms. Confidence ramps from 0.5 to 0.95 with repeated observations.
Phase 2: 166 guardrails — catches what agents miss:
| Category | What it catches |
|---|---|
| Security | hardcoded secrets, SQL injection, XSS, command injection, path traversal, JWT none algorithm, unsafe deserialization, disabled SSL verification |
| Imports | hallucinated imports, circular imports, wildcard imports, unused imports |
| Errors | bare excepts, swallowed exceptions, missing error handling, empty catch blocks |
| Quality | console.log leaks, dead code, debug prints, large files, duplicate functions |
| Auth | missing auth checks, missing rate limits, auth route guards, open redirects |
| Consistency | quote style, semicolons, async style, export style, import aliases |
Phase 3: Rule packs — community rules and your exported preferences (SnagPacks).
Every fix is transactional — if the transformed code doesn't parse, the change rolls back automatically. Run sg log to see exactly what was caught and why.
Supported Languages
| Language | Guardrails | Auto-fix | Linter Integration |
|---|---|---|---|
| Python | Full (50) | 23 rules | ruff |
| TypeScript | Full (50) | 23 rules | biome |
| JavaScript | Full (50) | 23 rules | biome |
| TSX/JSX | Full (50) | 23 rules | biome |
| Go | Basic | 8 rules | gofmt |
| Rust | Basic | 6 rules | clippy |
| Java | Basic | 5 rules | — |
| Kotlin | Detection | — | — |
| Ruby | Detection | — | — |
| PHP | Detection | — | — |
| C#/.NET | Detection | — | — |
Framework Detection
Snag detects your stack during sg init and adjusts guardrails accordingly:
Node/TypeScript: Next.js, Nuxt, Remix, Express, Fastify, NestJS, React, Vue, Svelte, Angular, Vite, Electron Python: Django, Flask, FastAPI, Streamlit Go: Gin, Echo, Fiber, Chi Rust: Actix-web, Axum Ruby: Rails, Sinatra PHP: Laravel Java/Kotlin: Spring Boot
What sg init Does
[1/11] Config Creates ~/.snag/, initializes database
[2/11] Agent Discovery Finds Claude Code, Cursor, Codex, OpenClaw, VS Code, etc.
[3/11] History Ingest Reads your prompt history, learns your style
[4/11] Profile Builds behavioral profile from your patterns
[5/11] Codebase Scan Detects conventions, frameworks, entry points
[6/11] Security Audit Finds real issues (secrets, injection, bad patterns)
[7/11] Repair Option to auto-fix findings (asks for consent first)
[8/11] Hooks Installs hooks + MCP + shell wrappers automatically
[9/11] Skills Loads guardrails, generates AGENTS.md
[10/11] Daemon Installs background scanner (asks for consent)
[11/11] Ready Summary of what was found and what's protected
History ingest supports Claude Code, Codex, and OpenClaw. Every step that installs or modifies anything asks for your consent first.
After init, the output looks like:
Connected to 5 agents, watching 12 tools
Claude Code hooks installed (4 scripts)
Cursor MCP configured (12 tools)
VS Code MCP configured (12 tools)
Codex CLI MCP configured + shell wrapper
Aider shell wrapper (async)
Git post-commit learning hook
Snag is now invisible. No per-session setup needed.
Hooks
Snag registers hooks in .claude/settings.json. In Claude Code, every tool call passes through:
| Hook | What it does |
|---|---|
PreToolUse[Bash] |
Blocks dangerous commands (rm -rf, DROP TABLE, force push), detects loops |
PreToolUse[Write|Edit] |
Detects loops, injects learned context |
PostToolUse[Write|Edit] |
Runs the compiler — 166 guardrails + your learned preferences |
PreToolUse[Read] |
Injects coaching from your behavioral profile |
For agents that don't support Claude-style hooks but do support MCP (Cursor, VS Code, Claude Desktop, Codex CLI):
sg mcp-serve
sg init auto-configures .cursor/mcp.json, .vscode/settings.json, Claude Desktop MCP config, and Codex MCP (codex mcp add snag -- snag mcp-serve). 12 MCP tools available covering coaching, write checking, command checking, project mapping, and more.
For CLI agents without hook or MCP support (Aider, Goose, Gemini CLI, etc.), Snag installs shell function wrappers that notify on session start/end with zero latency overhead.
Enforcement Matrix
| Integration path | Agents | What you get |
|---|---|---|
| Native hooks | Claude Code | True pre/post tool interception, per-write compiler enforcement |
| MCP server | Cursor, VS Code, Claude Desktop, Codex CLI | Snag coaching + compile/check tools; strongest when the agent follows MCP tool workflow |
| Shell wrapper / dispatch | Aider, Goose, Gemini CLI, others | Session-level observation + daemon task dispatch (not per-write interception) |
As more agents expose native pre/post tool hooks, Snag can move them from MCP/wrapper mode to hook-level interception without changing your workflow.
Behavioral Learning
Snag watches how you correct your agents and learns your preferences.
How it works:
- Agent writes code
- You correct something (rename a variable, change an import style, remove a debug print)
- Snag diffs the before/after, extracts the pattern
- Pattern is recorded with evidence (file, line, what changed)
- Confidence ramps: 0.5 base, +0.08 per observation, caps at 0.95
- Once confident enough, Snag auto-applies the preference on future writes
Categories tracked: imports, style, error handling, testing, naming, types, security
Example: You correct os.path.join to Path() three times across different files. Snag records the preference "pathlib over os.path" at confidence 0.74. After two more corrections, confidence hits 0.90 and all future os.path calls are automatically converted.
sg patterns list # See all learned patterns
sg patterns show <pattern> # Details + evidence
sg patterns disable <pattern> # Turn off a pattern
sg learning # See correction history
The Daemon
Snag's background daemon runs the proactive scan loop automatically. It calls the same scanner and compiler that sg audit uses, just on a schedule.
Four scan layers:
| Layer | What it finds | Consent |
|---|---|---|
| Security | SQL injection, XSS, command injection, hardcoded secrets | Always asks |
| Audit | Auto-fixable compiler issues, style warnings | Based on confidence |
| Coach | Violations of your learned preferences across the codebase | Based on confidence |
| Dead code | Orphaned exports, ghost functions, unused files | Suggests |
Consent tiers:
| Tier | Confidence | Behavior |
|---|---|---|
| Ask | < 0.85 | Notification, waits for explicit approval |
| Suggest | 0.85 - 0.95 | Notification, auto-approves after 24h if no denial |
| Auto | > 0.95 | Auto-dispatches, notifies after |
Security findings always require explicit approval regardless of confidence.
sg daemon start # Start in foreground
sg daemon stop # Stop daemon
sg daemon status # Status, last scan, pending approvals
sg daemon tick # Run one scan cycle manually
sg approve <id> # Approve a pending fix
sg deny <id> # Deny (recorded as learning signal)
The daemon installs as an OS-level service (launchd on macOS, systemd on Linux, Task Scheduler on Windows) so it starts on boot. Or run sg daemon start in the foreground for development.
Agent Dispatch
When the daemon or sg coach scan finds issues, Snag can dispatch fix tasks to coding agents.
Dispatch chain: OpenClaw (primary) -> Claude Code -> Codex CLI -> task file save (fallback)
Each dispatched task includes:
- The file and line range to fix
- The guardrail or preference that was violated
- Evidence from your behavioral profile
- The project brief for context
Execution behavior depends on target agent:
- OpenClaw: branch-oriented flow (
snag-coach/<task-id>) and PR workflow. - Claude/Codex CLI: non-interactive local task execution via daemon dispatch (stdout/stderr captured), with fallback to saved task files if unavailable.
sg coach scan # Find preference violations
sg coach dispatch # Send fix tasks to agents
sg openclaw # Set up coached OpenClaw agents
OpenClaw Integration
If you use OpenClaw, Snag works as the brain behind your agents:
- Ingests session history during
sg init— parses JSONL sessions, extracts patterns, tracks costs - Compiles every write — OpenClaw agents run the compiler after every file write
- Generates coached agents —
sg openclawcreates specialized OpenClaw agents (TypeScript engineer, test writer, reviewer, refactorer) with your learned preferences in their SOUL.md - Dispatches coaching tasks — scans your codebase, finds violations, dispatches to OpenClaw automatically
- Cross-agent learning — corrections in Claude Code train preferences OpenClaw agents follow
Don't use OpenClaw? No problem. Snag still works via hooks, MCP, wrappers, and daemon dispatch. Everything runs locally.
Dead Code Detection
Most linters find locally dead code (unused variable in a function). Snag builds a dependency graph across your entire project using the AST engine, finding globally dead code — entire functions, components, or files that nothing imports.
What it detects:
- Orphaned exports — function exported but imported nowhere
- Ghost functions — agent renamed
fetchDatatogetDatabut left the old one - Unused files — entire files with no inbound imports
- Zombie props — interface fields never accessed
sg prune # Show dead code report
sg prune --fix # Auto-remove confirmed dead code
sg prune --agent # Dispatch to agent for verification first
When an agent renames a function during a session, Snag's post-write hook checks if the old name is now orphaned and offers to prune it immediately.
SnagPacks
Export your learned preferences as packs. Install packs from other developers. Share what works.
sg marketplace export my-python-style # Export your profile as a pack
sg marketplace install teammate.json # Install a pack
sg marketplace create my-rules # Scaffold a new pack
sg marketplace validate pack.json # Quality check before publishing
Every pack goes through quality gates:
- Schema + regex validation
- Test coverage check (>50% required)
- Compiler integration tests — rules run through the actual compiler to verify transforms work
- Effectiveness scoring — packs that actively fix code score higher than warn-only packs
Commands
# Setup
sg init # Full setup (run once, consent at every step)
sg doctor # Health check (config, DB, agents)
sg on # Re-enable Snag
sg off # Kill switch (all hooks/wrappers skip silently)
sg status # Full status: agents, daemon, pending tasks
# Run
sg # Interactive REPL
sg run "task" # Run task through agent with Snag active
sg wrap # Wrap any agent CLI with Snag learning
sg compile <file> # Run compiler on specific files with live dashboard
# Audit and Fix
sg audit # Scan codebase for issues
sg audit --fix # Scan and auto-fix
sg fix # Apply compiler fixes (zero-cost, local)
sg fix --agent # Spawn AI agent to fix issues iteratively
sg prune # Find dead code
sg prove # Analyze real sessions, show what Snag caught
# Observe
sg log # What Snag caught and transformed
sg stats # Sessions, patterns, costs
sg cost # Estimated spend from stored actions
sg history # Last 20 agent actions
sg leaderboard # Agent performance rankings
sg battle # Run same task on multiple agents, compare
# Learning
sg patterns list # All learned patterns
sg patterns show <pattern> # Pattern details + evidence
sg learning # Capture corrections and improve
sg brief # Regenerate AGENTS.md
# Daemon
sg daemon start # Start background scanner
sg daemon stop # Stop daemon
sg daemon status # Status + pending approvals
sg approve <id> # Approve a pending coaching task
sg deny <id> # Deny (recorded as learning signal)
# Dispatch
sg openclaw # Set up coached OpenClaw agents
sg coach scan # Find preference violations
sg coach dispatch # Send fix tasks to agents
# Packs
sg marketplace # Browse installed packs
sg marketplace export <name> # Export your profile
sg marketplace install <file> # Install a pack
sg marketplace validate <file> # Quality check
# Safety
sg undo # Revert file changes from agent session
sg guard add "*.lock" # Protect files from modification
sg guard list # Show protected files
# Integration
sg mcp-serve # Start MCP server
sg mcp-config cursor # Print Cursor config
sg mcp-config claude # Print Claude Desktop config
sg mcp-config vscode # Print VS Code config
sg shell-init # Print shell aliases/completions
MCP Tools
For agents that connect via MCP (Cursor, VS Code, Claude Desktop), Snag exposes 12 tools:
| Tool | What it does |
|---|---|
snag_get_coaching |
Get behavioral coaching before starting a task |
snag_check_write |
Check a proposed file write before writing (guards, secrets, blueprint) |
snag_check_command |
Check a command before running (loops, dangerous ops, secrets) |
snag_compile_preview |
Preview what the compiler would do to a file |
snag_compile_write |
Run the compiler on a write |
snag_record_outcome |
Record task outcome for learning |
snag_get_project_map |
Get project structure map |
snag_session_summary |
Summary of what Snag did (loops prevented, secrets blocked) |
snag_sub_query |
Send sub-task to child agent (recursive processing) |
snag_store_context |
Store large document in context environment |
snag_query_context |
Query stored context |
snag_search_context |
Search stored context |
For AI Agents Reading This
If a user asked you to install or evaluate Snag, here is what you need to know.
What Snag Does
Snag integrates at three levels: native hooks (strongest), MCP tools, and shell wrappers/dispatch. Native hooks provide true per-tool interception; MCP/wrapper paths provide strong coaching and checks but are not identical to hook-level enforcement. The core runs locally with pattern matching — zero API calls, zero cost.
Install
pip install snagged
sg init
sg init auto-configures Claude hooks (.claude/settings.json), MCP for Cursor/VS Code/Claude Desktop/Codex, and shell wrappers for non-hook/non-MCP CLIs. No manual config needed. Every installation step asks for user consent.
What Happens After Install
Active hooks (Claude Code):
PreToolUse[Bash]-- loop detection, command guards, dangerous command blockingPreToolUse[Write|Edit]-- loop detection, context injectionPostToolUse[Write|Edit]-- behavioral compiler (166 guardrails, code transforms, learning)PreToolUse[Read]-- coaching injection from behavioral profile
MCP tools (Cursor, VS Code, Claude Desktop, Codex CLI): 12 tools covering coaching, write checking, command checking, project mapping, compilation, and context management.
Key Commands
| Command | What it does |
|---|---|
sg audit |
Scan codebase for issues |
sg fix |
Apply compiler fixes (zero-cost, local) |
sg fix --agent |
AI-powered iterative fixing |
sg log |
See what was caught and transformed |
sg prove |
Show real catches from past sessions |
sg prune |
Find and remove dead code |
sg patterns list |
Show all learned behavioral patterns |
sg marketplace |
Browse and install rule packs |
sg status |
Full status: agents, daemon, pending tasks |
sg off |
Kill switch (everything skips silently) |
sg on |
Re-enable |
Architecture
snag/
core/ Compiler (3-phase, 166 guardrails), Behavioral Profile,
AST Engine, History Ingest, Diff Analyzer, Hook Installer,
Daemon, Brief Builder, Repair Agent, Undo, Dead Code Detection
mcp/ MCP Server (12 tools), Loop Detector, Secret Scanner
marketplace/ SnagPack format, Validator, Registry
cli/ CLI commands + interactive REPL + live dashboards
adapters/ Agent adapters (Claude, OpenAI)
integrations/ OpenClaw bridge + agent templates
hooks/ Pre/Post tool use hook scripts
storage/ SQLite + migrations
ui/ Rich session UI + fix dashboard
utils/ Config, discovery, pricing, atomic I/O
Technical Details
- 166 guardrails, 23 auto-fix rules, 14 behavioral write transforms
- Languages: Python, TypeScript, JavaScript, TSX/JSX (full support); Go, Rust, Java (basic)
- Frameworks: Auto-detects Next.js, Django, FastAPI, Express, React, Vue, and 20+ others
- Linter integration: Swallows ruff, biome, gofmt, clippy output into compiler pipeline
- Transactional transforms: Every auto-fix is validated with
ast.parse; rolls back on failure - Consent model: Three tiers (ask/suggest/auto) based on confidence; security always asks
- Learning: Confidence ramps 0.5 to 0.95 with repeated observations; auto-enforces at high confidence
Open source, Apache 2.0.
Architecture
snag/
core/ Compiler (3-phase, 166 guardrails), Behavioral Profile,
AST Engine, History Ingest, Diff Analyzer, Hook Installer,
Daemon, Brief Builder, Repair Agent, Undo, Dead Code Detection
mcp/ MCP Server (12 tools), Loop Detector, Secret Scanner
marketplace/ SnagPack format, Validator, Registry
cli/ CLI commands + interactive REPL + live dashboards
adapters/ Agent adapters (Claude, OpenAI)
integrations/ OpenClaw bridge + agent templates
hooks/ Pre/Post tool use hook scripts
storage/ SQLite + migrations
ui/ Rich session UI + fix dashboard
utils/ Config, discovery, pricing, atomic I/O
Contributing
We want contributions. See CONTRIBUTING.md for setup, architecture, and how to add guardrails, rule packs, and agent adapters.
git clone https://github.com/notchopp/snag.git
cd snag
pip install -e ".[dev]"
pytest
License
Apache License 2.0. See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file snagged-0.1.0-py3-none-any.whl.
File metadata
- Download URL: snagged-0.1.0-py3-none-any.whl
- Upload date:
- Size: 682.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5860f7487c1e3a4f54261c96e9a558546b6b3d57664bfcd0131d22a083f46c0d
|
|
| MD5 |
9d16cf29e5da4b4df31805dde89d306a
|
|
| BLAKE2b-256 |
bb35deb1fcdf017df7484400afef280f97c9e8d46008af2b134798aca743c7ea
|