AI 코딩 어시스턴트의 컨텍스트 창으로 전달되는 쉘 출력을 필터링하는 CLI 프록시
요약
CLI 프록시 도구인 snip은 AI 코딩 어시스턴트가 쉘 명령의 과도한 출력을 받는 것을 방지합니다. 이 도구는 YAML 파이프라인을 통해 쉘 출력에 대한 필터링 기능을 제공하여, LLM이 불필요한 노이즈 대신 핵심 신호만 받도록 토큰 사용량을 최적화합니다.
핵심 포인트
- snip은 AI 코딩 어시스턴트와 쉘 사이에 위치하는 CLI 프록시입니다.
- YAML 기반의 선언적 파이프라인으로 출력을 필터링하여 노이즈를 제거합니다.
- go test, cargo test 등에서 토큰 사용량을 최대 99%까지 절감할 수 있습니다.
- LLM에게 필요한 핵심 신호만 전달하여 컨텍스트 창을 효율적으로 관리합니다.
CLI 프록시가 AI 코딩 어시스턴트의 컨텍스트 창에 도달하기 전에 쉘 출력을 필터링합니다. Claude Code, Cursor, Copilot, Gemini CLI, Windsurf, Cline, Codex, Pi, Grok Build, Kilo Code, Antigravity, OpenCode, OpenClaw, Aider 및 쉘 명령을 실행하는 모든 도구와 함께 작동합니다.
AI 코딩 에이전트는 신호가 전혀 없는 장황한 쉘 출력에 토큰을 소모합니다. 통과하는 go test는 LLM이 절대 사용하지 않을 수백 줄의 출력을 생성합니다. git log는 커밋당 한 줄로 충분할 때 전체 커밋 메타데이터를 덤프합니다.
snip은 AI 도구와 쉘 사이에 위치하여 선언적 YAML 파이프라인을 통해 출력을 필터링합니다. YAML 파일을 작성하고 폴더에 넣기만 하면 됩니다. 확장 가능한 LLM 토큰 최적화기: 필터는 컴파일된 코드가 아닌 YAML 데이터 파일입니다.
snip — 토큰 절약 보고서
══════════════════════════════
Commands filtered 128
...
실제 Claude Code 세션에서 측정됨 — 128개 명령, 2.3M 토큰 절약.
# Quick install (macOS/Linux)
curl -fsSL https://raw.githubusercontent.com/edouard-claude/snip/master/install.sh | sh
# 또는 Homebrew를 통해
...
이전(Before) — Claude Code가 이것을 봅니다 (275 토큰):
$ go test ./...
ok github.com/edouard-claude/snip 13.697s
? github.com/edouard-claude/snip/cmd/snip [no test files]
...
이후(After) — snip은 이것을 반환합니다 (8 토큰):
1125 passed, 0 failed
이는 97% 적은 토큰이며, 이 저장소에서 측정되었습니다. 필터는 -json을 주입하고 개별 테스트 결과를 계산하여 LLM이 공간의 일부만을 차지하는 것이 아니라 더 많은 신호(18개 패키지가 아닌 1125개 테스트 통과)를 얻도록 합니다.
┌─────────────┐ ┌─────────────────┐ ┌──────────────┐ ┌────────────┐
│ Claude Code │────>│ snip intercept │────>│ run command │────>│ filter │
│ runs git │ │ match filter │ │ capture I/O │ │ pipeline │
...
필터 일치 항목이 없으면? 명령은 변경 없이 통과합니다 — 오버헤드 없음.
| Command | 이전 (Before) | 이후 (After) | 감소율 (Reduction) |
|---|---|---|---|
cargo test | 591 토큰 | 5 토큰 | 99.2% |
go test ./... | 275 토큰 | 8 토큰 | 97.1% |
git log | 371 토큰 | 53 토큰 | 85.7% |
git status | 112 토큰 | 16 토큰 | 85.7% |
git diff | 355 토큰 | 66 토큰 | 81.4% |
노이즈에 토큰을 낭비하지 마세요. snip은 LLM에게 컨텍스트 창의 극히 일부만으로 동일한 신호를 제공합니다.
brew install edouard-claude/tap/snip
릴리스(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'
| Tool | 설치 방법 | 방식 |
|---|---|---|
| Claude Code | `snip init` | PreToolUse hook (네이티브) |
| Cursor | `snip init --agent cursor` | beforeShellExecution hook (네이티브) |
| GitHub Copilot | `snip init --agent copilot` | preToolUse hook (네이티브) |
| Gemini CLI | `snip init --agent gemini` | GEMINI.md 프롬프트 주입 |
| Codex (OpenAI) | `snip init --agent codex` | PreToolUse hook (네이티브) |
| Pi (pi.dev) | `snip init --agent pi` | PreToolUse hook (via pi-hooks) |
| Grok Build (xAI) | `snip init --agent grok` | PreToolUse hook (거부 + 재실행 제안) |
| Windsurf | `snip init --agent windsurf` | .windsurfrules 프롬프트 주입 |
| Cline / Roo Code | `snip init --agent cline` | .clinerules 프롬프트 주입 |
| Kilo Code | `snip init --agent kilocode` | .kilocode/rules/ 프롬프트 주입 |
| Antigravity | `snip init --agent antigravity` | PreToolUse hook (네이티브) |
| OpenCode | opencode-snip 플러그인 | tool.execute.before hook |
| OpenClaw | `openclaw plugins install openclaw-snip` | 플러그인 |
| Aider | 셸 별칭(shell aliases) | snip으로 접두사 지정한 명령어 사용 |
`snip init`
이것은 지원되는 명령어를 투명하게 재작성하는 `PreToolUse` hook을 설치합니다. Claude Code는 치환을 절대 볼 수 없으며, 마치 원래 명령어가 출력한 것처럼 압축된 출력을 받습니다.
지원되는 명령어: git, go, cargo, npm, yarn, pnpm, docker, kubectl, terraform, aws, gh, dotnet 등 100개의 고유한 명령어를 포괄하는 132개의 필터가 있습니다.
`snip init --uninstall # hook 제거`
`snip init --agent cursor`
이것은 `~/.cursor/hooks.json` 파일을 `beforeShellExecution` hook으로 패치합니다. Claude Code와 동일하게 작동합니다.
`snip init --agent cursor --uninstall # hook 제거`
`snip init --agent pi`
이것은 `~/.pi/agent/settings.json` 파일을 `bash` tool에 일치하는 `PreToolUse` 항목으로 패치합니다. 런타임 hook은 커뮤니티 확장 프로그램인 `@hsingjui/pi-hooks`에 의해 해석되며, 이는 Claude Code의 `hookSpecificOutput` 형식을 미러링합니다 (updatedInput을 통한 명령어 재작성 포함). 한 번 설치하세요:
`pi install npm:@hsingjui/pi-hooks`
그런 다음 `/reload`를 실행합니다.
(또는 Pi를 재시작합니다). 활성화되면 snip이 지원되는 명령어를 투명하게 재작성합니다.
`snip init --agent pi --uninstall # 훅 제거`
`snip init --agent grok`
이는 `~/.grok/hooks/snip.json` 파일을 작성하며, 셸 도구와 일치하는 `PreToolUse` 훅을 포함합니다. Grok Build 훅은 명령어를 제자리에서 재작성할 수 없습니다 (훅 계약은 허용/거부만 가능하므로), 따라서 snip은 일치하는 명령어를 재실행 제안(`"…/snip" run -- <command>`)과 함께 거부합니다. 일치하지 않는 명령어는 변경 없이 통과되며, 이 훅은 fail-open(실패 시 개방) 방식으로 작동합니다: 만약 snip에 문제가 생기면, 명령어는 단순히 필터링되지 않은 상태로 실행됩니다.
대신 프롬프트 주입(prompt injection)을 선호하십니까? Grok Build는 `AGENTS.md`를 네이티브하게 읽습니다:
snip init --agent grok --mode prompt # AGENTS.md 생성
snip init --agent grok --uninstall # 훅 제거
`AGENTS.md` 파일은 Codex와 공유되므로, `--uninstall`을 실행해도 이 파일을 삭제하지 않고 대신 알림 메시지를 출력합니다.
`snip init --agent codex`
이는 `~/.codex/hooks.json`에 네이티브 `PreToolUse` 훅을 패치합니다. 지원되는 셸 명령어는 Codex의 `updatedInput` 계약을 통해 snip으로 투명하게 재작성되므로, 모델은 명령어를 정상적으로 실행하고 필터링된 출력만 보게 됩니다.
안전을 위해, 지원되지 않는 세그먼트가 포함되고, 검사되지 않은 끝단(tail)을 가진 파이프라인 및 명령어 치환을 포함하는 혼합 명령어는 변경 없이 통과되어 Codex가 네이티브 권한 흐름을 유지할 수 있도록 합니다.
전체 필터링되지 않은 출력이 필요할 때는 `snip proxy -- <command>`를 사용하십시오.
`snip init --agent codex --uninstall`
`PreToolUse` 입력 재작성을 위해서는 Codex CLI 0.131.0 이상이 필요합니다. 이전 버전의 경우, 레거시 프로젝트 범위 프롬프트 통합을 사용하십시오:
`snip init --agent codex --mode prompt`
`snip init --agent copilot`
이는 `~/.copilot/hooks/snip.json`에 네이티브 `preToolUse` 훅을 패치하며, Claude Code처럼 지원되는 명령어를 투명하게 재작성합니다.
대신 프롬프트 주입(prompt injection)을 선호하십니까? 레거시 프로젝트 범위 모드를 사용하십시오:
snip init --agent copilot --mode prompt # .github/copilot-instructions.md 생성
snip init --agent copilot --uninstall # 훅 제거
`PreToolUse`가 지원됩니다. 이는 `~/.gemini/config/hooks.json`을 패치합니다.
`snip init --agent antigravity`
snip init --agent gemini # GEMINI.md 생성
snip init --agent windsurf # .windsurfrules 생성
snip init --agent cline # .clinerules 생성
...
이 에이전트들은 프롬프트 주입(prompt injection)을 사용합니다: 마크다운 파일이 LLM에게 셸 명령 앞에 `snip`을 붙여서 실행하도록 지시합니다. 프로젝트 범위(현재 디렉터리에서 생성됨)입니다.
OpenCode 설정(`~/.config/opencode/opencode.json`)에 추가하여 opencode-snip 플러그인을 설치하세요:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-snip@latest"]
...
이 플러그인은 `tool.execute.before` 훅을 사용하여 모든 명령 앞에 자동으로 `snip`을 붙입니다. snip에서 지원하지 않는 명령어는 변경 없이 통과합니다.
`openclaw plugins install openclaw-snip`
셸 별칭(shell aliases)을 사용하여 명령을 snip으로 라우팅하세요:
~/.bashrc 또는 ~/.zshrc에 추가
alias git="snip git"
alias go="snip go"
...
또는 시스템 프롬프트(system prompt)를 통해 LLM에게 명령 앞에 `snip`을 붙이도록 지시할 수 있습니다.
snip은 어떤 AI 도구 없이도 작동합니다:
snip git log -10
snip go test ./...
snip gain # 토큰 절약 보고서
snip <명령어> [인수] # 명령 필터링 (암시적)
snip run -- <명령어> # 동일, 명시적 구분자 사용
snip check -- <명령어> # 명령이 필터링될지 확인
...
전역 플래그: `-v` /`-vv` (상세 모드, 중첩 가능), `-u` (초압축), `--skip-env`, `--version`, `--help`.
필터는 선언적 YAML 파일입니다. 바이너리는 엔진이고, 필터는 데이터입니다 — 이 둘은 독립적으로 진화합니다.
name: "git-log"
version: 1
description: "git log을 해시 + 메시지로 간소화"
...
`match.subcommand`는 스칼라 문자열(위와 같이)일 수도 있고, 정확한 하위 명령어 목록일 수도 있습니다:
match:
command: "npm"
subcommand: ["install", "add", "i"]
만약 `subcommand`이
생략되면 해당 명령어의 모든 하위 명령어가 일치합니다. 특정 베어 명령어 호출만 일치시키려면 빈 문자열을 명시적으로 포함하세요. 예를 들어, `subcommand: ["", "install"]`와 같습니다.
`yarn`과 `yarn install`는 일치시키지만, `yarn why`는 일치시키지 않으려면 이렇게 합니다.
snip은 모든 주요 개발 도구를 포괄하는 **132개의 선언적 YAML 필터**를 포함합니다:
| 카테고리 | 필터 |
|---|---|
Git (12) | status, log, diff, show, add, commit, push, pull, branch, fetch, stash, worktree |
GitHub CLI (3) | gh pr, gh issue, gh run |
Go (4) | go test, go build, go vet, golangci-lint |
Rust (7) | cargo test/build/check/clippy/install/nextest, rustc |
Python (11) | pytest, ruff, mypy, basedpyright, ty, pip, poetry, uv add/lock/remove/sync |
JavaScript/TypeScript (17) | jest, vitest, eslint, tsc, biome, oxlint, prettier, next, playwright, nx, turbo, npm, npx, yarn, pnpm install/list, prisma |
Ruby (6) | rspec, rubocop, rake, bundle, rails migrate, rails routes |
.NET (3) | dotnet build/test/format |
Elixir (2) | mix compile, mix format |
Docker/K8s (7) | docker build/ps/images/logs/compose, kubectl get/logs |
클라우드/인프라 (6) | terraform, tofu, helm, ansible-playbook, gcloud, aws |
빌드 도구 (14) | make, gcc, g++, gradle, gradlew, gradlew.bat, mvn, swift, xcodebuild, just, task, pio, trunk, mise |
파일/검색 (7) | ls, find, grep, rg, diff, wc, tree |
린팅 (6) | shellcheck, hadolint, markdownlint, markdownlint-cli2, yamllint, pre-commit |
패키지 관리자 (2) | brew, composer |
시스템/네트워크 (14) | curl, wget, psql, jq, ping, ssh, rsync, df, du, ps, systemctl, iptables, stat, fail2ban |
기타 (11) | jira, jj, yadm, gt, ollama, sops, skopeo, shopify, quarto, liquibase, spring-boot |
`snip discover`를 실행하여 이미 필터가 적용된 명령어를 확인하세요.
| Action | 설명 |
|---|---|
`keep_lines` | 정규식과 일치하는 라인 유지 |
`remove_lines` | 정규식과 일치하는 라인 제거 |
`truncate_lines` | 최대 길이로 라인 자르기 |
`truncate_bytes` | 바이트 단위 출력 크기에 하드 캡 적용 |
`strip_ansi` | ANSI 이스케이프 코드 제거 |
`head` / `tail` | 처음/마지막 N 라인 유지 |
`group_by` | 정규식 캡처로 라인 그룹화 |
`dedup` | 선택적 정규화를 통한 중복 제거 |
`json_extract` | JSON에서 필드 추출 |
`json_schema` | JSON에서 스키마 추론 |
`ndjson_stream` | 줄 바꿈 구분된 JSON 처리 |
`regex_extract` | 정규식 캡처 추출 |
`state_machine` | 다중 상태 라인 처리 |
`aggregate` | 패턴 일치 횟수 계산 |
`format_template` | Go 템플릿 형식 지정 |
`compact_path` | 파일 경로 단축 (아래 주의사항 참조) |
`replace` | 정규식 찾기 및 바꾸기 |
`match_output` | 조건부 쇼트 서킷 (패턴 일치 시 메시지 반환) |
`on_empty` | 출력이 비어 있을 경우 메시지 반환
이것은 선행 `compact_path`를 제거합니다.
명령어가 실행된 디렉터리에서 `src/`, `lib/`, `internal/`, `pkg/` 또는 `vendor/` 세그먼트를 마커 없이 무조건적으로 제거하여, `internal/soak/report.go`가 `soak/report.go`로 변환됩니다.
— 이는 `ENOENT`에서 비롯된 것입니다. 이 필터는 번들링되지 않았습니다. 경로가 표시 전용이며 절대 열리지 않을 때만 사용하세요.
snip init # ~/.config/snip/filters/ 생성
vim ~/.config/snip/filters/my-tool.yaml # 필터 추가
사용자 정의 필터는 내장 필터보다 우선합니다. 목록의 나중 디렉터리가 이전 것을 덮어씁니다.
`~/.config/snip/` 아래의 필터는 항상 로드됩니다. 다른 곳에 있는 필터(예: 프로젝트의 `.snip/`)
AI 자동 생성 콘텐츠
본 콘텐츠는 GitHub AI Coding Assistants의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기