snip
Health Pass
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 110 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
This tool is a CLI proxy that intercepts verbose shell command outputs and condenses them into concise summaries before they reach an AI coding assistant. By stripping unnecessary noise from commands like `go test` or `git log`, it significantly reduces wasted LLM tokens and lowers API costs.
Security Assessment
Risk: Medium. The tool functions by acting as an intermediary between your AI coding agent (like Claude Code or Cursor) and your system's shell. Consequently, it must execute shell commands and inherently processes all the text output generated by those commands, which can sometimes include sensitive data like file paths or local environment variables. A light code scan of 12 files found no dangerous patterns, hardcoded secrets, or excessive network request capabilities. However, because the software actively executes and intercepts shell outputs, users should inherently trust the tool before installing it.
Quality Assessment
The project appears to be actively maintained, with its most recent push occurring today. It benefits from a solid early-stage community following, boasting 110 GitHub stars. The development standards look reliable, featuring a continuous integration (CI) pipeline and clear documentation. Furthermore, it is fully open-source under the permissive MIT license, providing clear usage rights and allowing for independent code review.
Verdict
Use with caution. The codebase itself is clean and actively maintained, but its core architecture requires intercepting your shell output. Verify its configuration and ensure you are comfortable granting it proxy access to your terminal before integrating it into your workflow.
CLI proxy that reduces LLM token usage by 60-90%. Declarative YAML filters for Claude Code, Cursor, Copilot, Gemini. rtk alternative in Go.
snip
CLI proxy that cuts LLM token waste from shell output.
AI 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.
snip sits between your AI tool and the shell, filtering output through declarative YAML pipelines before it reaches the context window.
snip — Token Savings Report
══════════════════════════════
Commands filtered 128
Tokens saved 2.3M
Avg savings 99.8%
Efficiency Elite
Total time 725.9s
███████████████████░ 100%
14-day trend ▁█▇
Top commands by tokens saved
Command Runs Saved Savings Impact
───────────────────────── ──── ────── ─────── ────────────
go test ./... 8 806.2K 99.8% ████████████
go test ./pkg/... 3 482.9K 99.8% ███████░░░░░
go test ./... -count=1 3 482.0K 99.8% ███████░░░░░
Measured on a real Claude Code session — 128 commands, 2.3M tokens saved.
Quick Start
# Homebrew (macOS/Linux)
brew install edouard-claude/tap/snip
# Or with Go
go install github.com/edouard-claude/snip/cmd/snip@latest
# Then hook into Claude Code
snip init
# That's it. Every shell command Claude runs now goes through snip.
How It Works
Before — Claude Code sees this (689 tokens):
$ go test ./...
ok github.com/edouard-claude/snip/internal/cli 3.728s coverage: 14.4% of statements
ok github.com/edouard-claude/snip/internal/config 2.359s coverage: 65.0% of statements
ok github.com/edouard-claude/snip/internal/display 1.221s coverage: 72.6% of statements
ok github.com/edouard-claude/snip/internal/engine 1.816s coverage: 47.9% of statements
ok github.com/edouard-claude/snip/internal/filter 4.306s coverage: 72.3% of statements
ok github.com/edouard-claude/snip/internal/initcmd 2.981s coverage: 59.1% of statements
ok github.com/edouard-claude/snip/internal/tee 0.614s coverage: 70.6% of statements
ok github.com/edouard-claude/snip/internal/tracking 5.355s coverage: 75.0% of statements
ok github.com/edouard-claude/snip/internal/utils 5.515s coverage: 100.0% of statements
After — snip returns this (16 tokens):
10 passed, 0 failed
That's 97.7% fewer tokens. The LLM gets the same signal — all tests pass — without the noise.
┌─────────────┐ ┌─────────────────┐ ┌──────────────┐ ┌────────────┐
│ Claude Code │────>│ snip intercept │────>│ run command │────>│ filter │
│ runs git │ │ match filter │ │ capture I/O │ │ pipeline │
└─────────────┘ └─────────────────┘ └──────────────┘ └─────┬──────┘
│
┌─────────────────┐ ┌──────────────┐ │
│ Claude Code │<────│ track savings│<──────────┘
│ sees filtered │ │ in SQLite │
└─────────────────┘ └──────────────┘
No filter match? The command passes through unchanged — zero overhead.
Savings by Command
| Command | Before | After | Savings |
|---|---|---|---|
cargo test |
591 tokens | 5 tokens | 99.2% |
go test ./... |
689 tokens | 16 tokens | 97.7% |
git log |
371 tokens | 53 tokens | 85.7% |
git status |
112 tokens | 16 tokens | 85.7% |
git diff |
355 tokens | 66 tokens | 81.4% |
Installation
Homebrew (recommended)
brew install edouard-claude/tap/snip
From GitHub Releases
Download the latest binary for your platform from Releases.
# macOS (Apple Silicon)
curl -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
tar xzf snip.tar.gz && mv snip /usr/local/bin/
From source
go install github.com/edouard-claude/snip/cmd/snip@latest
Or build locally:
git clone https://github.com/edouard-claude/snip.git
cd snip && make install
Requires Go 1.24+ and jq (for the hook script).
Integration
Claude Code
snip init
This 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.
Supported commands: git, go, cargo, npm, npx, yarn, pnpm, docker, kubectl, make, pip, pytest, jest, tsc, eslint, rustc.
snip init --uninstall # remove the hook
OpenCode
Install the opencode-snip plugin by adding it to your OpenCode config (~/.config/opencode/opencode.json):
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-snip@latest"]
}
The plugin uses the tool.execute.before hook to automatically prefix all commands with snip. Commands not supported by snip pass through unchanged.
Cursor
Cursor supports hooks since v1.7 via ~/.cursor/hooks.json:
{
"version": 1,
"hooks": {
"beforeShellExecution": [
{ "command": "~/.claude/hooks/snip-rewrite.sh" }
]
}
}
Aider / Windsurf / Other Tools
Use shell aliases:
# Add to ~/.bashrc or ~/.zshrc
alias git="snip git"
alias go="snip go"
alias cargo="snip cargo"
Or instruct the LLM via system prompt to prefix commands with snip.
Standalone
snip works without any AI tool:
snip git log -10
snip go test ./...
snip gain # token savings report
Usage
snip <command> [args] # filter a command
snip gain # full dashboard (summary + sparkline + top commands)
snip gain --daily # daily breakdown
snip gain --weekly # weekly breakdown
snip gain --monthly # monthly breakdown
snip gain --top 10 # top N commands by tokens saved
snip gain --history 20 # last 20 commands
snip gain --json # machine-readable output
snip gain --csv # CSV export
snip -v <command> # verbose mode (show filter details)
snip proxy <command> # force passthrough (no filtering)
snip config # show config
snip init # install Claude Code hook
snip init --uninstall # remove hook
Filters
Filters are declarative YAML files. The binary is the engine, filters are data — the two evolve independently.
name: "git-log"
version: 1
description: "Condense git log to hash + message"
match:
command: "git"
subcommand: "log"
exclude_flags: ["--format", "--pretty", "--oneline"]
inject:
args: ["--pretty=format:%h %s (%ar) <%an>", "--no-merges"]
defaults:
"-n": "10"
pipeline:
- action: "keep_lines"
pattern: "\\S"
- action: "truncate_lines"
max: 80
- action: "format_template"
template: "{{.count}} commits:\n{{.lines}}"
on_error: "passthrough"
Built-in Filters
| Filter | What it does |
|---|---|
git-status |
Categorized status with file counts |
git-diff |
Stat summary, truncated to 30 files |
git-log |
One-line per commit: hash + message + author + date |
go-test |
Pass/fail summary with failure details |
cargo-test |
Pass/fail summary with failure details |
16 Pipeline Actions
| Action | Description |
|---|---|
keep_lines |
Keep lines matching regex |
remove_lines |
Remove lines matching regex |
truncate_lines |
Truncate lines to max length |
strip_ansi |
Remove ANSI escape codes |
head / tail |
Keep first/last N lines |
group_by |
Group lines by regex capture |
dedup |
Deduplicate with optional normalization |
json_extract |
Extract fields from JSON |
json_schema |
Infer schema from JSON |
ndjson_stream |
Process newline-delimited JSON |
regex_extract |
Extract regex captures |
state_machine |
Multi-state line processing |
aggregate |
Count pattern matches |
format_template |
Go template formatting |
compact_path |
Shorten file paths |
Custom Filters
snip init # creates ~/.config/snip/filters/
vim ~/.config/snip/filters/my-tool.yaml # add your filter
User filters take priority over built-in ones.
Configuration
Optional TOML config at ~/.config/snip/config.toml:
[tracking]
db_path = "~/.local/share/snip/tracking.db"
[display]
color = true
emoji = true
quiet_no_filter = false # suppress "no filter" stderr messages
[filters]
dir = "~/.config/snip/filters"
[filters.enable]
# git-diff = false # disable a specific built-in filter
[tee]
enabled = true
mode = "failures" # "failures" | "always" | "never"
max_files = 20
max_file_size = 1048576
Design
- Startup < 10ms — snip intercepts every shell command; latency is critical
- Graceful degradation — if a filter fails, fall back to raw output
- Exit code preservation — always propagate the underlying tool's exit code
- Lazy regex compilation —
sync.Onceper pattern, reused across invocations - Zero CGO — pure Go SQLite driver, static binaries, trivial cross-compilation
- Goroutine concurrency — stdout/stderr captured in parallel without thread pools
Why Go over Rust?
| rtk (Rust) | snip (Go) | |
|---|---|---|
| Filters | Compiled into the binary | Declarative YAML — no code needed |
| Concurrency | 2 OS threads | Goroutines |
| SQLite | Requires CGO + C compiler | Pure Go driver — static binary |
| Cross-compilation | Per-target C toolchain | GOOS=linux GOARCH=arm64 go build |
| Contributing a filter | Write Rust, wait for release | Write YAML, drop in a folder |
Development
make build # static binary (CGO_ENABLED=0)
make test # all tests with coverage
make test-race # race detector
make lint # go vet + golangci-lint
make install # install to $GOPATH/bin
Documentation
Full documentation is available on the Wiki:
- Installation — Homebrew, Go, binaries (macOS/Linux/Windows), from source
- Integration — Claude Code, Cursor, Aider, standalone
- Gain Dashboard — Token savings reports and analytics
- Filters — Built-in filters, custom filters
- Filter DSL Reference — All 16 pipeline actions
- Configuration — TOML config, environment variables
- Architecture — Design decisions, internals
- Contributing — Dev setup, adding filters, conventions
Credits
Inspired by rtk by the rtk-ai team. rtk proved that filtering shell output before it reaches the LLM context is a powerful idea. snip rebuilds it in Go with a focus on extensibility — declarative YAML filters that anyone can write without touching the codebase.
License
MIT
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found