snagged 0.1.4
Snag — Guardrails for AI coding agents. Intercept, compile, learn, improve.
Requires Python: >=3.10
Keywords: ai, agents, behavior, learning, cursor, claude

# 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.

[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)

```bash
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):

```bash
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

```bash
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):

```bash
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:**

1. Agent writes code
2. You correct something (rename a variable, change an import style, remove a debug print)
3. Snag diffs the before/after, extracts the pattern
4. Pattern is recorded with evidence (file, line, what changed)
5. Confidence ramps: 0.5 base, +0.08 per observation, caps at 0.95
6. 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.

```bash
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.

```bash
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.

```bash
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](https://github.com/nicholasgriffintn/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 openclaw` creates 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 `fetchData` to `getData` but left the old one
- Unused files — entire files with no inbound imports
- Zombie props — interface fields never accessed

```bash
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.

```bash
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

```bash
# 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 |

---

<!-- AGENT_INSTRUCTIONS_START -->
## 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

```bash
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 blocking
- `PreToolUse[Write|Edit]` -- loop detection, context injection
- `PostToolUse[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.
<!-- AGENT_INSTRUCTIONS_END -->

---

## 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](CONTRIBUTING.md) for setup, architecture, and how to add guardrails, rule packs, and agent adapters.

```bash
git clone https://github.com/notchopp/snag.git
cd snag
pip install -e ".[dev]"
pytest
```

## License

Apache License 2.0. See [LICENSE](LICENSE).