/snip
You are an expert at writing declarative YAML filters for **snip**, a CLI proxy that reduces LLM token consumption by filtering shell output.
$ npx -y skills add edouard-claude/snip --skill snip --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/snip
Context preview
The summary Claude sees to decide when to auto-load this skill.
You are an expert at writing declarative YAML filters for **snip**, a CLI proxy that reduces LLM token consumption by filtering shell output.
SKILL.md
snip.SKILL.mdCreating 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.
Filter Structure
Every filter is a YAML file with this structure:
name: "tool-subcommand" # Required. Unique identifier, used for registry lookup.
version: 1 # Schema version (always 1 for now).
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").
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" # What to do if the pipeline fails: "passthrough" or "empty".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 17 Pipeline Actions
Line Filtering
| Action | Params | Description | |--------|--------|-------------| | `keep_lines` | `pattern` (regex) | Keep only lines matching the pattern | | `remove_lines` | `pattern` (regex) | Remove lines matching the pattern | | `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 | | `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) | Count matches for named patterns across all input | | `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` (template, optional) | Extract fields from JSON input | | `json_schema` | `max_depth` (int, default 3) | Output JSON type schema | | `ndjson_stream` | `group_by` (string field name), `format` (template with .Key, .Count, .Events) | Process newline-delimited JSON |
Formatting
| Action | Params | Description | |--------|--------|-------------| | `format_template` | `template` (Go text/template, required) | Format output using Go template |
Template Data for `format_template`
The template receives:
- `{{.lines}}` - all current lines joined with newlines
- `{{.count}}` - number of lines
- `{{.groups}}` - map from `group_by` action (if used earlier in pipeline)
- `{{.stats}}` - map from `aggregate` action (if used earlier in pipeline)
Metadata Flow Between Actions
- `group_by` sets metadata `"groups"` (map[string]int)
- `aggregate` sets metadata `"stats"` (map[string]int)
- `format_template` can access both via `{{.groups}}` and `{{.stats}}`
- All other actions pass metadata through unchanged
Desig
Read more
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.
Filter Structure
Every filter is a YAML file with this structure:
name: "tool-subcommand" # Required. Unique identifier, used for registry lookup.
version: 1 # Schema version (always 1 for now).
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").
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" # What to do if the pipeline fails: "passthrough" or "empty".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 17 Pipeline Actions
Line Filtering
| Action | Params | Description | |--------|--------|-------------| | `keep_lines` | `pattern` (regex) | Keep only lines matching the pattern | | `remove_lines` | `pattern` (regex) | Remove lines matching the pattern | | `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 | | `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) | Count matches for named patterns across all input | | `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` (template, optional) | Extract fields from JSON input | | `json_schema` | `max_depth` (int, default 3) | Output JSON type schema | | `ndjson_stream` | `group_by` (string field name), `format` (template with .Key, .Count, .Events) | Process newline-delimited JSON |
Formatting
| Action | Params | Description | |--------|--------|-------------| | `format_template` | `template` (Go text/template, required) | Format output using Go template |
Template Data for `format_template`
The template receives:
- `{{.lines}}` - all current lines joined with newlines
- `{{.count}}` - number of lines
- `{{.groups}}` - map from `group_by` action (if used earlier in pipeline)
- `{{.stats}}` - map from `aggregate` action (if used earlier in pipeline)
Metadata Flow Between Actions
- `group_by` sets metadata `"groups"` (map[string]int)
- `aggregate` sets metadata `"stats"` (map[string]int)
- `format_template` can access both via `{{.groups}}` and `{{.stats}}`
- All other actions pass metadata through unchanged
Desig
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.

