{"id":45197230,"url":"https://github.com/edouard-claude/snip","last_synced_at":"2026-04-15T06:06:19.055Z","repository":{"id":339519229,"uuid":"1162272375","full_name":"edouard-claude/snip","owner":"edouard-claude","description":"CLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Go binary","archived":false,"fork":false,"pushed_at":"2026-02-20T11:20:32.000Z","size":91,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-20T14:59:23.562Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/edouard-claude.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-20T04:01:26.000Z","updated_at":"2026-02-20T11:20:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/edouard-claude/snip","commit_stats":null,"previous_names":["edouard-claude/snip"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/edouard-claude/snip","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edouard-claude%2Fsnip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edouard-claude%2Fsnip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edouard-claude%2Fsnip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edouard-claude%2Fsnip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edouard-claude","download_url":"https://codeload.github.com/edouard-claude/snip/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edouard-claude%2Fsnip/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30331770,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T05:25:20.737Z","status":"ssl_error","status_checked_at":"2026-03-10T05:25:17.430Z","response_time":106,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-20T13:00:41.769Z","updated_at":"2026-04-15T06:06:19.047Z","avatar_url":"https://github.com/edouard-claude.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/github/v/release/edouard-claude/snip?style=flat-square\" alt=\"Release\"\u003e\n  \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/edouard-claude/snip/ci.yaml?branch=master\u0026style=flat-square\u0026label=CI\" alt=\"CI\"\u003e\n  \u003cimg src=\"https://img.shields.io/github/license/edouard-claude/snip?style=flat-square\" alt=\"License\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Go-1.25+-00ADD8?style=flat-square\u0026logo=go\" alt=\"Go\"\u003e\n\u003c/p\u003e\n\n# snip - Reduce LLM Token Usage by 60-90%\n\n**CLI proxy that filters shell output before it reaches your AI coding assistant's context window.** Works with Claude Code, Cursor, Copilot, Gemini CLI, Windsurf, Cline, Codex, Kilo Code, Antigravity, Aider, and any tool that runs shell commands.\n\nAI coding agents burn tokens on verbose shell output that adds zero signal. A passing `go test` produces hundreds of lines the LLM will never use. `git log` dumps full commit metadata when a one-liner per commit suffices.\n\nsnip sits between your AI tool and the shell, filtering output through **declarative YAML pipelines**. Write a YAML file, drop it in a folder, done. The extensible LLM token optimizer: filters are YAML data files, not compiled code.\n\n```\n  snip — Token Savings Report\n  ══════════════════════════════\n\n  Commands filtered     128\n  Tokens saved          2.3M\n  Avg savings           99.8%\n  Efficiency            Elite\n  Total time            725.9s\n\n  ███████████████████░ 100%\n\n  14-day trend  ▁█▇\n\n  Top commands by tokens saved\n\n  Command                    Runs  Saved   Savings  Impact\n  ─────────────────────────  ────  ──────  ───────  ────────────\n  go test ./...              8     806.2K  99.8%    ████████████\n  go test ./pkg/...          3     482.9K  99.8%    ███████░░░░░\n  go test ./... -count=1     3     482.0K  99.8%    ███████░░░░░\n```\n\n\u003e Measured on a real Claude Code session — 128 commands, 2.3M tokens saved.\n\n## Quick Start\n\n```bash\n# Quick install (macOS/Linux)\ncurl -fsSL https://raw.githubusercontent.com/edouard-claude/snip/master/install.sh | sh\n\n# Or via Homebrew\nbrew install edouard-claude/tap/snip\n\n# Or with Go\ngo install github.com/edouard-claude/snip/cmd/snip@latest\n\n# Then hook into Claude Code\nsnip init\n# That's it. Every shell command Claude runs now goes through snip.\n```\n\n## How It Works\n\n**Before** — Claude Code sees this (689 tokens):\n```\n$ go test ./...\nok  \tgithub.com/edouard-claude/snip/internal/cli\t3.728s\tcoverage: 14.4% of statements\nok  \tgithub.com/edouard-claude/snip/internal/config\t2.359s\tcoverage: 65.0% of statements\nok  \tgithub.com/edouard-claude/snip/internal/display\t1.221s\tcoverage: 72.6% of statements\nok  \tgithub.com/edouard-claude/snip/internal/engine\t1.816s\tcoverage: 47.9% of statements\nok  \tgithub.com/edouard-claude/snip/internal/filter\t4.306s\tcoverage: 72.3% of statements\nok  \tgithub.com/edouard-claude/snip/internal/initcmd\t2.981s\tcoverage: 59.1% of statements\nok  \tgithub.com/edouard-claude/snip/internal/tee\t0.614s\tcoverage: 70.6% of statements\nok  \tgithub.com/edouard-claude/snip/internal/tracking\t5.355s\tcoverage: 75.0% of statements\nok  \tgithub.com/edouard-claude/snip/internal/utils\t5.515s\tcoverage: 100.0% of statements\n```\n\n**After** — snip returns this (16 tokens):\n```\n10 passed, 0 failed\n```\n\nThat's **97.7% fewer tokens**. The LLM gets the same signal — all tests pass — without the noise.\n\n```\n┌─────────────┐     ┌─────────────────┐     ┌──────────────┐     ┌────────────┐\n│ Claude Code │────\u003e│ snip intercept  │────\u003e│ run command  │────\u003e│   filter   │\n│  runs git   │     │  match filter   │     │  capture I/O │     │  pipeline  │\n└─────────────┘     └─────────────────┘     └──────────────┘     └─────┬──────┘\n                                                                       │\n                    ┌─────────────────┐     ┌──────────────┐           │\n                    │   Claude Code   │\u003c────│ track savings│\u003c──────────┘\n                    │  sees filtered  │     │  in SQLite   │\n                    └─────────────────┘     └──────────────┘\n```\n\nNo filter match? The command passes through unchanged — zero overhead.\n\n### Token Savings by Command\n\n| Command | Before | After | Reduction |\n|---------|-------:|------:|----------:|\n| `cargo test` | 591 tokens | 5 tokens | **99.2%** |\n| `go test ./...` | 689 tokens | 16 tokens | **97.7%** |\n| `git log` | 371 tokens | 53 tokens | **85.7%** |\n| `git status` | 112 tokens | 16 tokens | **85.7%** |\n| `git diff` | 355 tokens | 66 tokens | **81.4%** |\n\nStop wasting tokens on noise. snip gives the LLM the same signal in a fraction of the context window.\n\n## Installation\n\n### Homebrew (recommended)\n\n```bash\nbrew install edouard-claude/tap/snip\n```\n\n### From GitHub Releases\n\nDownload the latest binary for your platform from [Releases](https://github.com/edouard-claude/snip/releases).\n\n```bash\n# macOS (Apple Silicon)\ncurl -Lo snip.tar.gz https://github.com/edouard-claude/snip/releases/latest/download/snip_$(curl -s https://api.github.com/repos/edouard-claude/snip/releases/latest | grep tag_name | cut -d'\"' -f4 | tr -d v)_darwin_arm64.tar.gz\ntar xzf snip.tar.gz \u0026\u0026 mv snip /usr/local/bin/\n```\n\n### From source\n\n```bash\ngo install github.com/edouard-claude/snip/cmd/snip@latest\n```\n\nOr build locally:\n\n```bash\ngit clone https://github.com/edouard-claude/snip.git\ncd snip \u0026\u0026 make install\n```\n\nRequires Go 1.25+.\n\n## Supported AI Tools\n\nsnip integrates with every major AI coding assistant. One binary, universal compatibility.\n\n| Tool | Install | Method |\n|------|---------|--------|\n| **Claude Code** | `snip init` | PreToolUse hook (native) |\n| **Cursor** | `snip init --agent cursor` | beforeShellExecution hook (native) |\n| **GitHub Copilot** | `snip init --agent copilot` | .github/copilot-instructions.md |\n| **Gemini CLI** | `snip init --agent gemini` | GEMINI.md prompt injection |\n| **Codex (OpenAI)** | `snip init --agent codex` | AGENTS.md prompt injection |\n| **Windsurf** | `snip init --agent windsurf` | .windsurfrules prompt injection |\n| **Cline / Roo Code** | `snip init --agent cline` | .clinerules prompt injection |\n| **Kilo Code** | `snip init --agent kilocode` | .kilocode/rules/ prompt injection |\n| **Antigravity** | `snip init --agent antigravity` | .agents/rules/ prompt injection |\n| **OpenCode** | [opencode-snip](https://github.com/VincentHardouin/opencode-snip) plugin | tool.execute.before hook |\n| **OpenClaw** | `openclaw plugins install openclaw-snip` | plugin |\n| **Aider** | shell aliases | prefix commands with snip |\n\n### Claude Code\n\n```bash\nsnip init\n```\n\nThis installs a `PreToolUse` hook that transparently rewrites supported commands. Claude Code never sees the substitution -- it receives compressed output as if the original command produced it.\n\nSupported commands: 126 filters covering git, go, cargo, npm, yarn, pnpm, docker, kubectl, terraform, aws, gh, and 80+ more tools.\n\n```bash\nsnip init --uninstall   # remove the hook\n```\n\n### Cursor\n\n```bash\nsnip init --agent cursor\n```\n\nThis patches `~/.cursor/hooks.json` with a `beforeShellExecution` hook. Works the same way as Claude Code.\n\n```bash\nsnip init --agent cursor --uninstall   # remove the hook\n```\n\n### Copilot / Gemini / Codex / Windsurf / Cline / Kilo Code / Antigravity\n\n```bash\nsnip init --agent copilot      # creates .github/copilot-instructions.md\nsnip init --agent gemini       # creates GEMINI.md\nsnip init --agent codex        # creates AGENTS.md\nsnip init --agent windsurf     # creates .windsurfrules\nsnip init --agent cline        # creates .clinerules\nsnip init --agent kilocode     # creates .kilocode/rules/snip-rules.md\nsnip init --agent antigravity  # creates .agents/rules/snip-rules.md\n```\n\nThese agents use prompt injection: a markdown file instructs the LLM to prefix shell commands with snip. Project-scoped (created in the current directory).\n\n### OpenCode\n\nInstall the [opencode-snip](https://github.com/VincentHardouin/opencode-snip) plugin by adding it to your OpenCode config (`~/.config/opencode/opencode.json`):\n\n```json\n{\n  \"$schema\": \"https://opencode.ai/config.json\",\n  \"plugin\": [\"opencode-snip@latest\"]\n}\n```\n\nThe plugin uses the `tool.execute.before` hook to automatically prefix all commands with `snip`. Commands not supported by snip pass through unchanged.\n\n### OpenClaw\n\n```bash\nopenclaw plugins install openclaw-snip\n```\n\n### Aider\n\nUse shell aliases to route commands through snip:\n\n```bash\n# Add to ~/.bashrc or ~/.zshrc\nalias git=\"snip git\"\nalias go=\"snip go\"\nalias cargo=\"snip cargo\"\n```\n\nOr instruct the LLM via system prompt to prefix commands with `snip`.\n\n### Standalone\n\nsnip works without any AI tool:\n\n```bash\nsnip git log -10\nsnip go test ./...\nsnip gain             # token savings report\n```\n\n## Usage\n\n```bash\nsnip \u003ccommand\u003e [args]       # filter a command\nsnip gain                   # full dashboard (summary + sparkline + top commands)\nsnip gain --daily           # daily breakdown\nsnip gain --weekly          # weekly breakdown\nsnip gain --monthly         # monthly breakdown\nsnip gain --top 10          # top N commands by tokens saved\nsnip gain --history 20      # last 20 commands\nsnip gain --no-truncate     # disable command truncation\nsnip gain --json            # machine-readable output\nsnip gain --csv             # CSV export\nsnip discover               # find missed savings in Claude Code history\nsnip discover --since 30    # scan last 30 days\nsnip discover --all         # scan all projects\nsnip -v \u003ccommand\u003e           # verbose mode (show filter details)\nsnip proxy \u003ccommand\u003e        # force passthrough (no filtering)\nsnip config                 # show config\nsnip init                       # install Claude Code hook\nsnip init --agent cursor        # install Cursor hook\nsnip init --agent copilot       # install Copilot integration\nsnip init --agent gemini        # install Gemini CLI integration\nsnip init --agent kilocode      # install Kilo Code integration\nsnip init --agent antigravity   # install Antigravity integration\nsnip init --uninstall           # remove hook\n```\n\n## Filters\n\nFilters are declarative YAML files. The binary is the engine, filters are data — the two evolve independently.\n\n```yaml\nname: \"git-log\"\nversion: 1\ndescription: \"Condense git log to hash + message\"\n\nmatch:\n  command: \"git\"\n  subcommand: \"log\"\n  exclude_flags: [\"--format\", \"--pretty\", \"--oneline\"]\n\ninject:\n  args: [\"--pretty=format:%h %s (%ar) \u003c%an\u003e\", \"--no-merges\"]\n  defaults:\n    \"-n\": \"10\"\n\npipeline:\n  - action: \"keep_lines\"\n    pattern: \"\\\\S\"\n  - action: \"truncate_lines\"\n    max: 80\n  - action: \"format_template\"\n    template: \"{{.count}} commits:\\n{{.lines}}\"\n\non_error: \"passthrough\"\n```\n\n### 126 Built-in Filters\n\nsnip ships with **126 declarative YAML filters** covering all major developer tools:\n\n| Category | Filters |\n|----------|---------|\n| **Git** (12) | status, log, diff, show, add, commit, push, pull, branch, fetch, stash, worktree |\n| **GitHub CLI** (3) | gh pr, gh issue, gh run |\n| **Go** (4) | go test, go build, go vet, golangci-lint |\n| **Rust** (7) | cargo test/build/check/clippy/install/nextest, rustc |\n| **Python** (8) | pytest, ruff, mypy, basedpyright, ty, pip, poetry, uv |\n| **JavaScript/TypeScript** (17) | jest, vitest, eslint, tsc, biome, oxlint, prettier, next, playwright, nx, turbo, npm, npx, yarn, pnpm, prisma |\n| **Ruby** (6) | rspec, rubocop, rake, bundle, rails migrate, rails routes |\n| **.NET** (3) | dotnet build/test/format |\n| **Docker/K8s** (7) | docker build/ps/images/logs/compose, kubectl get/logs |\n| **Cloud/Infra** (6) | terraform, tofu, helm, ansible-playbook, gcloud, aws |\n| **Build tools** (12) | make, gcc, g++, gradle, mvn, swift, xcodebuild, just, task, pio, trunk, mise |\n| **Files/Search** (7) | ls, find, grep, rg, diff, wc, tree |\n| **Linting** (5) | shellcheck, hadolint, markdownlint, yamllint, pre-commit |\n| **Package managers** (4) | brew, composer, poetry, uv |\n| **System/Network** (14) | curl, wget, psql, jq, ping, ssh, rsync, df, du, ps, systemctl, iptables, stat, fail2ban |\n| **Other** (11) | jira, jj, yadm, gt, ollama, sops, skopeo, shopify, quarto, liquibase, spring-boot |\n\nRun `snip discover` to see which of your commands already have filters.\n\n### 19 Pipeline Actions\n\n| Action | Description |\n|--------|-------------|\n| `keep_lines` | Keep lines matching regex |\n| `remove_lines` | Remove lines matching regex |\n| `truncate_lines` | Truncate lines to max length |\n| `strip_ansi` | Remove ANSI escape codes |\n| `head` / `tail` | Keep first/last N lines |\n| `group_by` | Group lines by regex capture |\n| `dedup` | Deduplicate with optional normalization |\n| `json_extract` | Extract fields from JSON |\n| `json_schema` | Infer schema from JSON |\n| `ndjson_stream` | Process newline-delimited JSON |\n| `regex_extract` | Extract regex captures |\n| `state_machine` | Multi-state line processing |\n| `aggregate` | Count pattern matches |\n| `format_template` | Go template formatting |\n| `compact_path` | Shorten file paths |\n| `replace` | Regex find and replace |\n| `match_output` | Conditional short-circuit (return message if pattern matches) |\n| `on_empty` | Return message if output is empty |\n\n### Custom Filters\n\n```bash\nsnip init                                    # creates ~/.config/snip/filters/\nvim ~/.config/snip/filters/my-tool.yaml      # add your filter\n```\n\nUser filters take priority over built-in ones. Later directories in the list override earlier ones.\n\n## Configuration\n\nOptional TOML config at `~/.config/snip/config.toml`:\n\n```toml\n[tracking]\ndb_path = \"~/.local/share/snip/tracking.db\"\n\n[display]\ncolor = true\nemoji = true\nquiet_no_filter = false  # suppress \"no filter\" stderr messages\n\n[filters]\ndir = \"~/.config/snip/filters\"\n\n[filters.enable]\n# git-diff = false       # disable a specific built-in filter\n\n[tee]\nenabled = true\nmode = \"failures\"    # \"failures\" | \"always\" | \"never\"\nmax_files = 20\nmax_file_size = 1048576\n```\n\n### Multiple Filter Directories\n\n`filters.dir` accepts a single string or an array of directories. This enables per-project filter rules alongside global ones:\n\n```toml\n[filters]\ndir = [\n    \"~/.config/snip/filters\",\n    \"${env.PWD}/.snip\",\n]\n```\n\nLater directories take priority: a filter in `.snip/` overrides one with the same name in `~/.config/snip/filters/`.\n\n### Environment Variable Expansion\n\nAll path values support `${env.VAR}` syntax to reference environment variables:\n\n```toml\n[filters]\ndir = \"${env.HOME}/.config/snip/filters\"\n\n[tracking]\ndb_path = \"${env.XDG_DATA_HOME}/snip/tracking.db\"\n```\n\nTilde expansion (`~/`) is also supported and applied after env var expansion.\n\n## Design\n\n- **Startup \u003c 10ms** — snip intercepts every shell command; latency is critical\n- **Graceful degradation** — if a filter fails, fall back to raw output\n- **Exit code preservation** — always propagate the underlying tool's exit code\n- **Lazy regex compilation** — `sync.Once` per pattern, reused across invocations\n- **Zero CGO** — pure Go SQLite driver, static binaries, trivial cross-compilation\n- **Goroutine concurrency** — stdout/stderr captured in parallel without thread pools\n\n## Design Philosophy\n\nsnip chose a fundamentally different approach to LLM token reduction: **filters are data, not code**. The binary is the engine, filters are YAML data files, and the two evolve independently.\n\n| | **[rtk](https://github.com/rtk-ai/rtk)** (Rust) | **snip** (Go) |\n|---|---|---|\n| Filter authoring | Write Rust, recompile, wait for release | Write YAML, drop in a folder, done |\n| Filter format | Compiled into the binary | Declarative YAML, engine and filters evolve independently |\n| Custom filters | Fork the repo, add Rust code | Create a `.yaml` file in `~/.config/snip/filters/` |\n| Concurrency | 2 OS threads | Goroutines (lightweight, no thread pool) |\n| SQLite | Requires CGO + C compiler | Pure Go driver, static binary, no dependencies |\n| Cross-compilation | Per-target C toolchain | `GOOS=linux GOARCH=arm64 go build` |\n| Pipeline actions | Built-in strategies | 19 composable actions (keep, remove, regex, JSON, state machine...) |\n| Contributing | Rust knowledge required | YAML knowledge sufficient |\n\nBoth tools solve the same problem: reducing AI token costs from verbose CLI output. snip's bet is that **extensibility wins**. When anyone can write a filter in 5 minutes without touching Go or Rust, the filter ecosystem grows faster.\n\n## Development\n\n```bash\nmake build        # static binary (CGO_ENABLED=0)\nmake test         # all tests with coverage\nmake test-race    # race detector\nmake lint         # go vet + golangci-lint\nmake install      # install to $GOPATH/bin\n```\n\n## Documentation\n\nFull documentation is available on the **[Wiki](https://github.com/edouard-claude/snip/wiki)**:\n\n- [Installation](https://github.com/edouard-claude/snip/wiki/Installation) — Homebrew, Go, binaries (macOS/Linux/Windows), from source\n- [Integration](https://github.com/edouard-claude/snip/wiki/Integration) — Claude Code, Cursor, Copilot, Gemini, Kilo Code, Antigravity, and more\n- [Gain Dashboard](https://github.com/edouard-claude/snip/wiki/Gain-Dashboard) — Token savings reports and analytics\n- [Filters](https://github.com/edouard-claude/snip/wiki/Filters) — Built-in filters, custom filters\n- [Filter DSL Reference](https://github.com/edouard-claude/snip/wiki/Filter-DSL-Reference) — All 19 pipeline actions\n- [Configuration](https://github.com/edouard-claude/snip/wiki/Configuration) — TOML config, environment variables\n- [Architecture](https://github.com/edouard-claude/snip/wiki/Architecture) — Design decisions, internals\n- [Contributing](https://github.com/edouard-claude/snip/wiki/Contributing) — Dev setup, adding filters, conventions\n\n## Credits\n\nInspired by [rtk](https://github.com/rtk-ai/rtk) (Rust Token Killer) by the rtk-ai team. rtk proved that filtering shell output before it reaches the LLM context window is a powerful idea for cutting AI coding costs. snip rebuilds the concept in Go with a focus on extensibility -- declarative YAML filters that anyone can write without touching the codebase.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedouard-claude%2Fsnip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedouard-claude%2Fsnip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedouard-claude%2Fsnip/lists"}