Skip to content

AssafWoo/homebrew-pandafilter

Repository files navigation

PandaFilter

PandaFilter

The context intelligence layer for AI coding agents.

The layer between your tools and your AI. PandaFilter understands what's noise and what matters — compressing, routing, and preserving the right context so your agent thinks faster, costs less, and never loses its place.

Star PandaFilter on GitHub

Discord   License: MIT   Latest Release

Claude Code   Cursor   Windsurf   Gemini CLI   Codex   Cline   VS Code Copilot   OpenClaw


Install

brew tap AssafWoo/pandafilter
brew install pandafilter

Linux / any platform:

curl -fsSL https://raw.githubusercontent.com/AssafWoo/homebrew-pandafilter/main/install.sh | bash

First run: PandaFilter downloads the BERT model (~90 MB, all-MiniLM-L6-v2) from HuggingFace and caches it at ~/.cache/huggingface/. Subsequent runs are instant.

Then wire it in — one command installs for every AI agent you have:

panda init --agent all

Auto-detects Claude Code, Cursor, Gemini CLI, Codex, Windsurf, Cline, OpenClaw, and VS Code Copilot. Skips anything that isn't installed. Or target one specifically:

panda init                          # Claude Code (default)
panda init --agent cursor           # Cursor
panda init --agent gemini           # Gemini CLI
panda init --agent codex            # Codex (CLI + VS Code extension)
panda init --agent windsurf         # Windsurf
panda init --agent cline            # Cline
panda init --agent openclaw         # OpenClaw
panda init --agent copilot          # VS Code Copilot

What PandaFilter Does

1. Intelligent Compression

Raw command output is filtered, deduplicated, and semantically compressed by a BERT-powered pipeline that understands what matters for your task — not just what matches a regex. When your AI agent runs pip install, cargo build, or npm install, PandaFilter intercepts the output and strips download progress, module graphs, and passing test lines. The agent sees a clean summary with errors, warnings, and results. Nothing useful is dropped.

2. Adaptive Routing (new in v1.3.0)

A content-aware router analyzes each output and activates only the strategies relevant to it: error-focus for test failures, dedup for log streams, structural digest for unchanged file re-reads, semantic summarization for prose. No more one-size-fits-all.

Enable with use_router = true in panda.toml.

3. Session Intelligence

PandaFilter learns your codebase's noise patterns across sessions. It tracks what you've read, what you've changed, and where the context pressure is building — adapting its compression strategy in real time.

New in v1.3.0: File re-reads now send diffs instead of full file content. Unchanged re-reads return structural digests (function/class signatures). Both happen automatically — no config needed.

4. Compaction Survival (new in v1.3.0)

When your agent's context fills up and auto-compacts, PandaFilter preserves what matters: edited files, error signatures, key decisions. The next session starts oriented, not blank.

Requires Claude Code and is installed automatically with panda init.


How it works

When your AI agent runs a command — pip install, cargo build, npm install — PandaFilter intercepts the output and removes everything the model doesn't need: download progress, module graphs, passing test lines, spinners. The agent sees a clean summary with errors, warnings, and results. Nothing useful is dropped.

No config changes. No workflow changes. Runs 100% locally.


See it in action

Run panda gain after a session to see your cumulative savings:

panda gain output


Token savings

Numbers from ccr/tests/handler_benchmarks.rs. Run panda gain to see your own live data.

Operation Without PandaFilter With PandaFilter Savings
pip install 1,787 9 −99%
uv sync 1,574 15 −99%
playwright test 1,367 19 −99%
docker build 1,801 24 −99%
swift build 1,218 9 −99%
dotnet build 438 3 −99%
cmake 850 5 −99%
gradle build 803 17 −98%
go test 4,507 148 −97%
git merge 164 5 −97%
pytest 3,818 162 −96%
terraform plan 3,926 163 −96%
npm install 648 25 −96%
ember build 3,377 139 −96%
cargo build 1,923 93 −95%
cargo test 2,782 174 −94%
git clone 139 8 −94%
bazel build 150 12 −92%
next build 549 53 −90%
cargo clippy 786 93 −88%
make 545 72 −87%
git diff 6,370 861 −86%
git push 173 24 −86%
ls 691 102 −85%
webpack 882 143 −84%
vitest 625 103 −84%
nx run-many 1,541 273 −82%
turbo run build 597 115 −81%
ruff check 2,035 435 −79%
eslint 4,393 974 −78%
grep 2,925 691 −76%
helm install 224 54 −76%
docker ps 1,057 266 −75%
golangci-lint 3,678 960 −74%
git log 1,573 431 −73%
git status 650 184 −72%
kubectl get pods 2,306 689 −70%
vite build 526 182 −65%
jest 330 114 −65%
env 1,155 399 −65%
mvn install 4,585 1,613 −65%
brew install 368 148 −60%
gh pr list 774 321 −59%
biome lint 1,503 753 −50%
tsc 2,598 1,320 −49%
mypy 2,053 1,088 −47%
stylelint 1,100 845 −23%
Total 81,882 14,347 −82%

What's new in v1.3.0

Feature Before After (PandaFilter v1.3.0)
Bash output Full output Compressed by type (error-focus, dedup, stats, etc.)
File re-reads Full file every time Delta diff or structural digest
Context compaction 60–70% conversation lost Session digest preserved and restored
Filtering strategy Fixed pipeline always Adaptive router — right expert per content type
Quality visibility Token savings only Multi-signal quality score in panda gain
Agent support 7 agents 8 agents — OpenClaw added

Commands

panda gain — see your token savings:

panda gain                    # overall summary
panda gain --breakdown        # per-command table
panda gain --history          # last 14 days
panda gain --insight          # categorized savings + top saves

panda doctor — diagnose the full installation in one command.

panda init --uninstall — remove hooks:

panda init --uninstall                  # Claude Code
panda init --agent cursor --uninstall   # Cursor

panda focus — opt-in: tells the agent which files matter for the current prompt, preventing unnecessary reads:

panda focus --enable             # enable for this repo
panda focus --disable            # disable (keeps index data)
panda focus --status             # show status + index age
panda focus --dry-run            # preview guidance without enabling

panda index — manually rebuild the file-relationship index:

panda index                      # full/incremental build for current repo

Other commands:

panda verify                            # check hook integrity
panda discover                          # scan history for unfiltered commands
panda run git status                    # run a command through PandaFilter manually
panda proxy git status                  # run raw (no filtering), record baseline
panda read-file src/main.rs --level auto  # preview read filtering
panda expand ZI_3                       # restore a collapsed block
panda noise                             # show learned noise patterns; --reset to clear
panda compress --scan-session           # compress current conversation context

Handlers (59 handlers)

59 handlers (70+ command aliases) in ccr/src/handlers/. Lookup cascade:

  1. User filters.panda/filters.toml or ~/.config/panda/filters.toml
  2. Exact match — direct command name
  3. Static alias table — versioned binaries, wrappers, common aliases
  4. BERT routing — unknown commands matched by embedding similarity
Handler Keys Key behavior
cargo cargo build/clippy: errors (capped at 15) + warning count. test: failures + summary. nextest run: FAIL lines + Summary.
git git status: counts. log: --oneline, cap 50 with total. diff: 2 context lines, 200-line cap. clone/merge/checkout/rebase: compressed success or full conflict output.
go go test: NDJSON streaming, FAIL blocks + summary. build: errors only.
ember ember build: errors + summary; drops fingerprint/asset spam. test: failures + summary. serve: serving URL only.
tsc tsc Errors grouped by file; deduplicates repeated TS codes. Build OK on clean. Injects --noEmit.
vitest vitest FAIL blocks + summary; drops lines.
jest jest, bun, deno failure blocks + summary; drops PASS lines.
pytest pytest FAILED node IDs + AssertionError + short summary. Injects --tb=short.
rspec rspec Injects --format json; example-level failures with message + location.
rubocop rubocop Injects --format json; offenses grouped by severity, capped.
rake rake, bundle Failure/error blocks + summary; drops passing test lines.
mypy mypy Errors grouped by file, capped at 10 per file. Injects --no-color.
ruff ruff Violations grouped by error code. format: summary line only.
uv uv, uvx Strips Downloading/Fetching/Preparing noise; keeps errors + summary.
pip pip, poetry, pdm, conda install: [complete — N packages] or already-satisfied short-circuit.
python python Traceback: keep block + final error. Detects and compresses tabular/CSV, pandas DataFrames, Word (.docx), Excel (.xlsx), and PowerPoint (.pptx) output. Long output: BERT.
eslint eslint Errors grouped by file, caps at 20 + [+N more].
next next build: route table collapsed. dev: errors + ready line.
playwright playwright Failing test names + error messages; passing tests dropped. Injects --reporter=list.
prettier prettier --check: files needing formatting + count.
vite vite Asset chunk table collapsed, HMR deduplication.
webpack webpack Module resolution graph dropped; keeps assets, errors, build result.
turbo turbo Inner task output stripped; cache hit/miss per package + final summary.
nx nx, npx nx Passing tasks collapsed to [N tasks passed]; failing task output kept.
stylelint stylelint Issues grouped by file, caps at 40 + [+N more].
biome biome Code context snippets stripped; keeps file:line, rule, message.
kubectl kubectl, k get pods: aggregates to [N pods, all running] or problem-pods table with counts. Smart column selection, log anomaly scoring, describe key sections. events: warning-only, capped at 20.
terraform terraform, tofu plan: +/-/~ + summary. validate: short-circuits on success. output: compact key=value. state list: capped at 50.
aws aws, gcloud, az Resource extraction; --output json injected for read-only actions.
gh gh Compact tables for list commands; strips HTML from pr view.
helm helm list: compact table. status/diff/template: structured.
docker docker logs: ANSI strip + BERT. ps/images: formatted tables + total size. build: errors + final image ID.
make make, ninja "Nothing to be done" short-circuit; keeps errors. Injects --no-print-directory.
golangci-lint golangci-lint Diagnostics grouped by file; runner noise dropped. Detects v1 text and v2 JSON formats.
prisma prisma generate/migrate/db push structured summaries.
mvn mvn Drops [INFO] noise; keeps errors + reactor summary.
gradle gradle UP-TO-DATE tasks collapsed; FAILED tasks and errors kept.
npm/yarn npm, yarn install: package count; strips boilerplate.
pnpm pnpm install: summary; drops progress bars.
brew brew install/update: status lines + Caveats.
curl curl JSON → type schema. Non-JSON: cap 30 lines.
grep / rg grep, rg Compact paths, per-file 100-match cap, line numbers preserved, [N matches in M files] summary. Injects --no-heading --with-filename. Match-centered line truncation.
find find Groups by directory, caps at 50. Injects -maxdepth 8 if unset.
journalctl journalctl Injects --no-pager -n 200. BERT anomaly scoring.
psql psql Strips borders, caps at 20 rows.
tree tree Auto-injects -I "node_modules|.git|target|...".
diff diff +/-/@@ + 2 context lines, max 5 hunks.
jq jq Array: schema of first element + [N items].
env env Categorized sections; sensitive values redacted.
ls ls Drops noise dirs; top-3 extension summary.
log log Timestamp/UUID normalization, dedup [×N], error summary block.
rsync rsync Drops per-file transfer progress lines (to-chk=, MB/s); keeps file list and final summary.
ffmpeg ffmpeg, ffprobe Drops frame= and size= real-time progress lines; keeps input/output codec info and final size line.
wget wget Injects --quiet if no verbosity flag set.
swift swift, swift-build, swift-test build: errors/warnings + Build complete. test: failures + summary. package resolve: strips progress.
dotnet dotnet, dotnet-cli build: errors grouped by CS code + summary. Short-circuits on clean build. test: failures + summary. restore: package count.
cmake cmake, cmake3 configure: errors + final written-to line. --build: errors + [N targets built]. Auto-detects mode from args/output.
bazel bazel, bazelisk, bzl build: errors + completion summary [N actions, build OK (Xs)]. test: failures + [N passed, N failed]. query: cap at 30 targets.
Pipeline architecture
0. Hard input ceiling (200k chars — truncates before any stage)
1. Strip ANSI codes
2. Normalize whitespace
3. Global regex pre-filter (progress bars, spinners, download lines, decorators)
4. NDJSON streaming compaction (go test -json, jest JSON reporter)
5. Command-specific pattern filter
6. If over summarize_threshold_lines:
   6a. BERT noise pre-filter
   6b. Entropy-adaptive BERT summarization (up to 7 passes)
7. Hard output cap (50k chars)

Outputs under 15 tokens skip the pipeline entirely. Step 6b falls back to head+tail if BERT is unavailable.

Pre-run cache (fires before execution): git, kubectl, docker, and terraform commands are hashed against live state. A hit skips execution entirely and returns the cached output with a [PC: cached from Xm ago] marker.

Configuration

Config loaded from: ./panda.toml~/.config/panda/config.toml → embedded default.

[global]
summarize_threshold_lines = 50
head_lines = 30
tail_lines = 30
strip_ansi = true
normalize_whitespace = true
deduplicate_lines = true
input_char_ceiling = 200000
output_char_cap = 50000
# cost_per_million_tokens = 15.0

# v1.3.0: Adaptive MoE router (opt-in)
# use_router = true                  # enable adaptive expert routing
# router_exploration_noise = true    # prevent expert collapse in long sessions

[tee]
enabled = true
mode = "aggressive"   # "aggressive" | "always" | "never"

[read]
mode = "auto"   # "passthrough" | "auto" | "strip" | "aggressive" | "structural"
# v1.3.0: delta mode (re-reads send diffs) and structural mode (signature-only) are
# now active automatically — no config change needed.

[focus]
enabled = false       # disabled by default — enable with `panda focus --enable` after testing
min_files = 25        # skip for repos smaller than this
min_lines = 2000      # skip for repos with fewer source lines

[commands.git]
patterns = [
  { regex = "^(Counting|Compressing|Receiving|Resolving) objects:.*", action = "Remove" },
]

[commands.cargo]
patterns = [
  { regex = "^\\s+Compiling \\S+ v[\\d.]+", action = "Collapse" },
  { regex = "^\\s+Downloaded \\S+ v[\\d.]+", action = "Remove"   },
]

Pattern actions: Remove, Collapse, ReplaceWith = "text", TruncateLinesAt = N, HeadLines = N, TailLines = N, MatchOutput = "msg", OnEmpty = "msg".

Pricing uses cost_per_million_tokens from panda.toml if set, otherwise ANTHROPIC_MODEL env var (Opus 4.6: $15, Sonnet 4.6: $3, Haiku 4.5: $0.80), otherwise $3.00.

User-defined filters

Place filters.toml at .panda/filters.toml (project-local) or ~/.config/panda/filters.toml (global). Project-local overrides global for the same key. Runs before any built-in handler.

[commands.myapp]
patterns = [
  { regex = "^DEBUG:",            action = "Remove" },
  { regex = "^\\S+\\.ts\\(",     action = "TruncateLinesAt", max_chars = 120 },
]
on_empty = "(no relevant output)"

[commands.myapp.match_output]
pattern        = "Server started"
message        = "ok — server ready"
unless_pattern = "error"
Session intelligence

State tracked via PANDA_SESSION_ID=$PPID, stored at ~/.local/share/panda/sessions/<id>.json.

  • Result cache — post-pipeline bytes frozen per input hash; returned identically on repeat calls to prevent prompt cache busts.
  • Semantic delta — repeated commands emit only new/changed lines: [Δ from turn N: +M new, K repeated — ~T tokens saved].
  • Cross-turn dedup — identical outputs (cosine > 0.92) collapse to [same output as turn 4 (3m ago) — 1.2k tokens saved].
  • Elastic context — pipeline pressure scales with session size. At >80% pressure: [⚠ context near full — run panda compress --scan-session].
  • Intent-aware query — reads the agent's last message from the live session JSONL and uses it as the BERT query.
  • File delta re-reads (v1.3.0) — re-reading a changed file sends a unified diff instead of the full content. Unchanged re-reads send a structural digest (function/class signatures). Both save 60–95% of re-read tokens automatically.
  • Compaction digest (v1.3.0, Claude Code only) — before Claude auto-compacts, PandaFilter serializes edited files, error signatures, and top commands to ~/.local/share/panda/compacts/. On the next session start, the digest is injected into context so the agent resumes oriented.
Supported agents (7)

All agents share the same binary and filtering pipeline. panda init --agent all installs for everything detected on your machine in one shot.

Agent Install Config
Claude Code panda init ~/.claude/settings.json
Cursor panda init --agent cursor ~/.cursor/hooks.json
Gemini CLI panda init --agent gemini ~/.gemini/settings.json
Codex (CLI + VS Code) panda init --agent codex ~/.codex/hooks.json
Windsurf panda init --agent windsurf ~/.codeium/windsurf/hooks.json
Cline panda init --agent cline .clinerules (project dir)
VS Code Copilot panda init --agent copilot .github/hooks/ (project dir)

Hook-based agents (Claude Code, Cursor, Gemini, Codex, Windsurf) intercept every command before and after execution via the agent's native hook system.

Rules-based agents (Cline, Copilot) inject panda run <cmd> directives into the agent's context file, relying on the model to follow them.

PreToolUse: known handler → rewrites to panda run <cmd>; unknown → no-op; already wrapped → no double-wrap; compound commands → each segment rewritten independently.

PostToolUse: Bash → full pipeline; Read → BERT + session dedup; Glob → grouped by directory; Grep → compact paths.

UserPromptSubmit: Context Focusing module → queries file graph → injects guidance (recommended + excluded files).

Hook integrity: panda init writes SHA-256 baselines (chmod 0o444). PandaFilter verifies at every invocation and exits 1 with a warning if tampered. panda verify checks all installed agents.

Crate overview
ccr/        CLI binary (panda) — handlers, hooks, session state, commands
ccr-core/   Core library (no I/O) — pipeline, BERT summarizer, config, analytics
ccr-sdk/    Conversation compression — tiered compressor, deduplicator, Ollama
ccr-eval/   Evaluation suite — fixtures against Claude API
config/     Embedded default filter patterns
Uninstall
panda init --uninstall                            # Claude Code
panda init --agent cursor   --uninstall           # Cursor
panda init --agent gemini   --uninstall           # Gemini CLI
panda init --agent codex    --uninstall           # Codex
panda init --agent windsurf --uninstall           # Windsurf
panda init --agent cline    --uninstall           # Cline
panda init --agent copilot  --uninstall           # VS Code Copilot

brew uninstall pandafilter && brew untap AssafWoo/pandafilter   # Homebrew
# or: cargo uninstall panda

rm -rf ~/.local/share/panda                   # analytics + sessions
rm -rf ~/.cache/huggingface/hub/models--sentence-transformers--all-MiniLM-L6-v2

FAQ

Does PandaFilter change what the agent can see? It removes noise — build progress, passing test lines, module download logs. Errors, file paths, and results are always kept.

What if I don't want a specific command filtered? Add a rule to .panda/filters.toml to customize or override any handler. See the User-defined filters section. You can also use panda proxy <cmd> to run a command raw with no filtering.

What about commands PandaFilter doesn't know? Output passes through unchanged. PandaFilter never silently drops output from unknown commands.

How do I verify it's working? Run panda gain after a session. To see exactly what the agent received from a specific command: panda run git log --oneline -20.

Does PandaFilter send any data outside my machine? No. All processing is fully local. BERT runs on-device.

What is Context Focusing? An opt-in feature that tells the agent which files are relevant for the current prompt, preventing it from reading unrelated files. Enable with panda focus --enable after running panda doctor to confirm the index is ready.


Why PandaFilter? Why Panda?

AI coding sessions are expensive — not because of what you ask, but because of what the agent reads back. Every cargo build or npm install dumps thousands of tokens of noise into the context window. I built PandaFilter to strip that out automatically.

The name comes from how a panda eats: it consumes enormous amounts of raw material and extracts only what it needs.

Assaf Petronio · github.com/AssafWoo


Contributing

Open an issue or PR on GitHub. To add a handler: implement the Handler trait and register it in ccr/src/handlers/mod.rs — see git.rs as a template.


License

MIT — see LICENSE.

About

The context intelligence layer for AI coding agents. Compressing noise, routing content to the right strategy, preserving session state across compactions, and surfacing the files that actually matter.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages