MCPcopy Index your code
hub / github.com/AgusRdz/chop

github.com/AgusRdz/chop @v1.38.7

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.38.7 ↗ · + Follow
1,547 symbols 4,480 edges 270 files 336 documented · 22%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

chop

chop logo

CLI output compressor for Claude Code, Gemini CLI, Codex CLI, and Antigravity IDE.

Claude Code and other AI agents waste 50-90% of their context window on verbose CLI output — build logs, test results, container listings, git diffs. chop compresses that output before Claude sees it, saving tokens and keeping conversations focused.

The name comes from chop chop: the sound of something eating through all that verbosity before it ever reaches the context window.


How It Works

When Claude Code runs a Bash command, the raw output is fed back into the conversation as a tool_result — part of the input of the next API call. chop intercepts that result and compresses it before it enters the context.

sequenceDiagram
    participant CC as Claude Code
    participant H as PreToolUse Hook
    participant CH as chop
    participant API as Claude API

    CC->>H: bash("docker ps")
    H->>CH: raw output (850 tokens)
    CH-->>H: compressed output (250 tokens)
    H->>API: tool_result (250 tokens)
    API-->>CC: response

The Cascade Effect

The savings aren't one-time. Every tool_result that enters the context stays there for the rest of the session — included in the input of every subsequent API call. A bloated command result compounds across turns.

graph TD
    T1["Turn 1: docker ps → 850 tokens added"]
    T2["Turn 2: +850 tokens carried forward"]
    T3["Turn 3: +850 tokens carried forward"]
    TN["Turn N: +850 tokens carried forward"]
    COMPACT["Compaction triggered early ⚠️"]

    T1 --> T2 --> T3 --> TN --> COMPACT

    style COMPACT fill:#f66,color:#fff
graph TD
    T1C["Turn 1: chop docker ps → 250 tokens added"]
    T2C["Turn 2: +250 tokens carried forward"]
    T3C["Turn 3: +250 tokens carried forward"]
    TNC["Turn N: +250 tokens carried forward"]
    SESSION["Longer session, more context budget ✅"]

    T1C --> T2C --> T3C --> TNC --> SESSION

    style SESSION fill:#2a2,color:#fff

Why Output Tokens Also Benefit

API output tokens cost 5× more than input tokens and are slower to generate (higher TTFB). A larger, noisier context causes the model to produce longer, more verbose responses — more recapitulation, more hedging. Keeping the context lean produces tighter, faster output naturally.

Input token price:   $3.00 / MTok  (Sonnet 4.6)
Output token price: $15.00 / MTok  (Sonnet 4.6)

⚠️ 200K threshold: Once input exceeds 200K tokens, pricing jumps to $6.00 input / $22.50 output — applied to the entire request, not just the excess. Staying compressed avoids crossing that threshold.


Before & After

# Without chop (247 tokens)
$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   src/app.ts
        modified:   src/auth/login.ts
        modified:   config.json

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        src/utils/helpers.ts

no changes added to commit (use "git add" and/or "git commit")

# With chop (12 tokens — 95% savings)
$ chop git status
modified(3): src/app.ts, src/auth/login.ts, config.json
untracked(1): src/utils/helpers.ts
# Without chop (850+ tokens)
$ docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED        STATUS        PORTS                    NAMES
a1b2c3d4e5f6   nginx:1.25-alpine      "/docker-entrypoint.…"   2 hours ago    Up 2 hours    0.0.0.0:80->80/tcp       web
f6e5d4c3b2a1   postgres:16-alpine     "docker-entrypoint.s…"   2 hours ago    Up 2 hours    0.0.0.0:5432->5432/tcp   db
...

# With chop (compact table — 70% savings)
$ chop docker ps
web        nginx:1.25-alpine     Up 2h    :80->80
db         postgres:16-alpine    Up 2h    :5432->5432
# Without chop (1,200+ tokens)
$npm test

> @acme/ui@1.0.0 test
> jest

 PASS  src/lib/button/button.component.spec.ts
 PASS  src/lib/modal/modal.component.spec.ts
...58 more passing suites...

Test Suites: 59 passed, 59 total
Tests:       2 skipped, 1679 passed, 1681 total
Time:        12.296 s

# With chop (5 tokens — 99% savings)
$chop npm test
all 1681 tests passed

Install

macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/AgusRdz/chop/main/install.sh | sh

Specific version or custom directory:

curl -fsSL https://raw.githubusercontent.com/AgusRdz/chop/main/install.sh | CHOP_VERSION=v1.0.0 sh
curl -fsSL https://raw.githubusercontent.com/AgusRdz/chop/main/install.sh | CHOP_INSTALL_DIR=/usr/local/bin sh

The installer places the binary in ~/.local/bin by default. If it is not in your PATH, it is added automatically to ~/.zshrc or ~/.bashrc. Reload your shell after installing:

source ~/.zshrc  # or ~/.bashrc

Windows (PowerShell):

irm https://raw.githubusercontent.com/AgusRdz/chop/main/install.ps1 | iex

The installer places the binary in %LOCALAPPDATA%\Programs\chop by default and adds it to your user PATH automatically. Restart your terminal after installing.

With Homebrew (macOS / Linux):

brew install AgusRdz/tap/chop

With Go:

go install github.com/AgusRdz/chop@latest

Update to latest:

chop update

Verification

All release binaries are signed with GitHub Artifact Attestations, providing cryptographic proof that a given binary was built from this repository at a specific commit.

Requires the GitHub CLI.

gh attestation verify chop-darwin-arm64 --repo AgusRdz/chop

macOS note: If downloaded manually (not via Homebrew), macOS may block the binary on first run. Remove the quarantine flag before running: bash xattr -d com.apple.quarantine ./chop Installing via Homebrew avoids this entirely.


Quick Start

chop git status          # compressed git status
chop docker ps           # compact container list
chop npm test            # just failures and summary
chop kubectl get pods    # essential columns only
chop terraform plan      # resource changes, no attribute noise
chop curl https://api.io # JSON compressed to structure + types
chop anything            # auto-detects and compresses any output

Agent Integration

Claude Code

Register a PreToolUse hook that automatically wraps every Bash command:

chop init --global       # install hook
chop init --uninstall    # remove hook
chop init --status       # check if installed

After this, every command Claude Code runs gets compressed transparently. You'll see chop git status in the tool calls — that's the hook working.

Gemini CLI

chop init --gemini             # install hook
chop init --gemini --uninstall # remove hook
chop init --gemini --status    # check if installed

Codex CLI

chop init --codex              # install hook
chop init --codex --uninstall  # remove hook
chop init --codex --status     # check if installed

Antigravity IDE

chop init --antigravity              # install hook
chop init --antigravity --uninstall  # remove hook
chop init --antigravity --status     # check if installed

AI Agent Discovery

chop writes a discovery file at ~/.chop/path.json on every install, update, or hook registration, so AI agents can always locate the binary without searching:

{
  "version": "v1.15.0",
  "path": "/home/user/.local/bin/chop"
}

Two commands support agent-first workflows:

chop agent-info               # output JSON metadata (path, version, installed hooks)
chop init --agent-handshake   # print a high-signal discovery message agents recognize

setup is also available as an alias for init, useful when working with Gemini CLI where /init conflicts with a built-in command:

chop setup --global           # same as chop init --global

Supported Commands (60+)

Category Commands Savings
Git git status/log/diff/branch/push, gh pr/issue/run 50-90%
JavaScript npm install/list/test/view, pnpm, yarn, bun, npx, tsc, eslint, biome 70-95%
Angular/Nx ng build/test/serve, nx build/test, npx nx 70-90%
.NET dotnet build/test 70-90%
Rust cargo test/build/check/clippy 70-90%
Go go test/build/vet 75-90%
Python pytest, pip, uv, mypy, ruff, flake8, pylint 70-90%
Java mvn, gradle/gradlew 70-85%
Ruby bundle, rspec, rubocop 70-90%
PHP composer install/update 70-85%
Containers docker ps/build/images/logs/inspect/stats/rmi/etc., docker compose 60-85%
Kubernetes kubectl get/describe/logs/top, helm 60-85%
Infrastructure terraform plan/apply/init 70-90%
Build make, cmake, gcc/g++/clang 60-80%
Cloud aws, az, gcloud 60-85%
HTTP curl, http (HTTPie) 50-80%
Search grep, rg 50-70%
System ping, ps, ss/netstat, df/du, systemctl 50-80%
Files/Logs cat, tail, less, more, ls, find 60-95%
Atlassian acli jira list/get-issue 60-80%

Any command not listed above still gets compressed via auto-detection (JSON, CSV, tables, log lines).

Log Pattern Compression

When reading log files with cat, tail, or any log-producing command, chop groups structurally similar lines by replacing variable parts (UUIDs, IPs, timestamps, numbers, key=value pairs) with a fingerprint, then shows a representative line with a repeat count:

# Before (51 lines)
2024-03-11 10:00:00 INFO Processing request id=req0001 duration=31ms status=200
2024-03-11 10:00:01 INFO Processing request id=req0002 duration=32ms status=200
... (48 more identical-structure lines)
2024-03-11 11:00:00 ERROR Connection timeout to 10.0.0.5:3306

# After (2 lines)
2024-03-11 11:00:00 ERROR Connection timeout to 10.0.0.5:3306
2024-03-11 10:00:49 INFO Processing request id=req0049 duration=79ms status=200 (x50)

Errors and warnings are always shown in full and floated to the top.


Configuration

Global config

~/.config/chop/config.yml — configure editor preference and disable built-in filters globally:

chop config                        # show current config
chop config init                   # create a starter config.yml
chop config set editor <vim|code|nano|...>  # set preferred editor
chop config edit                   # open config.yml in your editor
chop config export                 # export config + filters to stdout (for syncing)
chop config import <file>          # import a previously exported config
# ~/.config/chop/config.yml

# Preferred editor for all "chop * edit" commands.
# Falls back to $VISUAL, $EDITOR, then auto-detects (code, vim, nano, notepad).
# Set without opening a file: chop config set editor vim
editor: vim

# Disable built-in filters for specific commands.
# Matching is prefix-based: "git diff" disables all git diff variants.
# Both formats are supported:
disabled:
  - git diff            # disables git diff, git diff HEAD, git diff --cached, etc.
  - curl                # disables all curl commands

Why disable git diff? chop compresses diff output by default, which is useful for AI agents but breaks interactive use. Adding git diff to disabled ensures you always see the full diff when running it yourself.

Local config (per-project)

Override the global disabled list for the current project:

chop local                      # show current local config
chop local add "git diff"       # disable git diff in this project
chop local remove "git diff"    # re-enable git diff
chop local clear                # remove local config entirely
chop local edit                 # open .chop.yml in your editor

The first chop local add creates .chop.yml and adds it to .gitignore automatically.

Custom Filters

Define your own compression rules for any command — keep/drop regex, head/tail truncation, or pipe through an external script.

chop filter new "myctl deploy"                          # scaffold + guided workflow (recommended)
chop filter add "myctl deploy" --keep "ERROR,WARN" --drop "DEBUG"  # add directly
chop filter test "myctl deploy"                         # test against stdin

→ Full reference: docs/custom-filters.md


Token Tracking

Every command is tracked locally. See how many tokens you're saving:

chop gain                  # overall savings summary
chop gain --history        # last 20 commands with per-command savings
chop gain --summary        # per-command breakdown
chop gain --projects       # per-project breakdown
chop gain --unchopped      # commands with no filter — new candidates
chop gain --export json    # export history as JSON or CSV

→ Full reference: docs/token-tracking.md


Shell Completions

Enable tab-completion for all chop commands and flags:

source <(chop completion bash)        # bash — add to ~/.bashrc
source <(chop completion zsh)         # zsh  — add to ~/.zshrc
chop completion fish | source         # fish
chop completion powershell | Invoke-Expression  # PowerShell

→ Setup instructions: docs/shell-completions.md


Maintenance

```bash chop doctor # check and auto-fix common issues chop update # update to the latest version ch

Extension points exported contracts — how you extend this code

FilterFunc (FuncType)
FilterFunc takes raw command output and returns filtered output.
filters/filters.go

Core symbols most depended-on inside this repo

outputSanityCheck
called by 137
filters/sanity_guards.go
registerRouter
called by 39
filters/registry.go
Track
called by 39
tracking/tracker.go
registerFilter
called by 30
filters/registry.go
Init
called by 25
tracking/tracker.go
atoi
called by 24
filters/docker_build.go
extractColumn
called by 24
filters/docker_ps.go
readSettings
called by 23
hooks/install.go

Shape

Function 1,463
Struct 72
Method 8
FuncType 2
TypeAlias 2

Languages

Go100%

Modules by API surface

filters/sanity_guards.go91 symbols
main.go53 symbols
tracking/tracker.go50 symbols
tracking/tracking_coverage_test.go38 symbols
filters/filters_coverage_test.go37 symbols
filters/filters.go30 symbols
tracking/tracker_test.go29 symbols
hooks/install.go25 symbols
config/config_coverage_test.go25 symbols
main_test.go23 symbols
config/config_test.go21 symbols
hooks/install_test.go20 symbols

For agents

$ claude mcp add chop \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact