Skip to content
Development
Skill

/snip

You are an expert at writing declarative YAML filters for **snip**, a CLI proxy that reduces LLM token consumption by filtering shell output.

From plugin
snip
4731 skill

Claude Code

$ npx -y skills add edouard-claude/snip --skill snip --agent claude-code

SKILL.md

snip.SKILL.md

Creating snip Filters

You are an expert at writing declarative YAML filters for **snip**, a CLI proxy that reduces LLM token consumption by filtering shell output.

Filter File Location

  • **Built-in filters**: `filters/*.yaml` (embedded in the binary at build time)
  • **User filters**: `~/.config/snip/filters/*.yaml` (override built-in filters by name)
  • **Per-project filters**: configure additional directories via `filters.dir` array in `~/.config/snip/config.toml` (e.g. `dir = ["~/.config/snip/filters", "${env.PWD}/.snip"]`). Later directories take priority.

**Trust store**: filters in any directory outside `~/.config/snip/` are ignored (with a stderr warning) until approved once with `snip trust <dir>`, which pins each file's SHA-256. Re-run `snip trust` after editing a trusted file.

Filter Structure

Every filter is a YAML file with this structure:

name: "tool-subcommand"          # Required. Unique identifier, used for registry lookup.
version: 1                       # Informational revision number of the filter (bump on behavior change).
description: "What this filter does"  # Human-readable purpose.

match:                           # Required. When to apply this filter.
  command: "tool"                # Required. The CLI tool name (e.g., "git", "go", "npm").
  subcommand: "sub"             # Optional. First non-flag argument (e.g., "test", "log").
                                # Also accepts a list: ["install", "add", "i"]; include ""
                                # in the list to match the bare command invocation too.
  exclude_flags: ["-v", "--json"]  # Optional. Skip filter if user passes any of these.
  require_flags: ["--all"]      # Optional. Only apply if user passes ALL of these.

inject:                          # Optional. Modify command args before execution.
  args: ["--json"]              # Arguments to append to the command.
  defaults:                     # Flag defaults, only added if flag not already present.
    "-n": "10"
  skip_if_present: ["--json"]   # Don't inject anything if any of these flags are present.

streams: ["stdout", "stderr"]    # Optional. Which streams to filter. Default: ["stdout"].
                                 # Use ["stderr"] for tools that output to stderr (e.g., bun test).
                                 # Use ["stdout", "stderr"] to filter both streams merged together.

pipeline:                        # Required. Ordered list of transformation actions.
  - action: "keep_lines"
    pattern: "\\S"
  - action: "head"
    n: 20

on_error: "passthrough"          # Descriptive convention: the engine ALWAYS falls back to raw
                                 # output when a pipeline fails; no other value is implemented.

Match Rules

  • `command` is matched exactly against the first token of the shell command.
  • `subcommand` is matched against the first non-flag argument.
  • Flag matching uses **prefix matching**: `"-v"` matches both `-v` and `-verbose`.
  • Registry lookup is O(1) by key `"command"` or `"command:subcommand"`.

Inject Behavior

  • Injected `args` are inserted before any `--` separator, otherwise appended.
  • `defaults` only apply if their flag key is not already present in the user's args.
  • If any flag in `skip_if_present` is found, the entire inject block is skipped.

The 20 Pipeline Actions

Line Filtering

| Action | Params | Description | |--------|--------|-------------| | `keep_lines` | `pattern` (regex), `removed_msg` (fmt string with `%d`, optional) | Keep only lines matching the pattern. `removed_msg` appends a marker with the dropped count when N > 0 | | `remove_lines` | `pattern` (regex), `removed_msg` (fmt string with `%d`, optional) | Remove lines matching the pattern. `removed_msg` appends a marker with the dropped count when N > 0 | | `head` | `n` (int, default 10), `overflow_msg` (string, default "+{remaining} more lines") | Keep first N lines | | `tail` | `n` (int, default 10), `overflow_msg` (string, default "+{dropped} earlier lines") | Keep last N lines | | `dedup` | `normalize` ([]string of regexes to strip before comparing), `top` (int, 0=all) | Deduplicate lines, output "text (xN)" for repeats |

Line Transformation

| Action | Params | Description | |--------|--------|-------------| | `truncate_lines` | `max` (int, default 80), `ellipsis` (string, default "...") | Truncate long lines | | `replace` | `pattern` (regex), `replacement` (string, supports $1, $2...) | Regex find and replace on each line | | `truncate_bytes` | `max` (int, 0=disabled), `overflow_msg` (string, default "... truncated at {max} bytes") | Cap the whole output at `max` bytes, cutting on a UTF-8 rune boundary. The marker is paid for out of `max`, and is dropped when it alone would not fit | | `strip_ansi` | (none) | Remove ANSI escape codes | | `compact_path` | (none) | Strips a leading `src/`/`lib/`/`internal/`/`pkg/`/`vendor/` segment. The result may not resolve from the cwd, and carries no marker saying so — no bundled filter uses it. Display-only paths only. |

Extraction & Grouping

| Action | Params | Description | |--------|--------|-------------| | `regex_extract` | `pattern` (regex with capture groups), `format` (string using $0, $1, $2...) | Extract data via regex capture groups | | `group_by` | `pattern` (regex with capture group), `format` (template, default "{{.Key}}: {{.Count}}"), `top` (int) | Group lines by capture group, count occurrences | | `aggregate` | `patterns` (map of name->regex), `format` (Go template), `append` (bool) | Count lines matching named patterns. **Replaces** the input lines with the summary unless `append: true` (forgetting it caused bugs #134/#136: a correct count and no content) | | `state_machine` | `states` (map of state definitions with `keep`, `until`, `next`) | Stateful line filtering with transitions |

JSON Processing

| Action | Params | Description | |--------|--------|-------------| | `json_extract` | `fields` ([]string), `format` (

Read more
@edouard-claude
Ships withsnip

CLI proxy that filters shell output before it reaches your AI coding assistant's context window.

Stars on GitHub

Momentum

stars in total
473
Star history of edouard-claude/snip on GitHub, a chart by star-history.com

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about snip.

Which coding agents can use snip?
snip installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.