1import{u as d,j as e,G as a,c as l,H as o,P as r,I as i,D as c,C as t,a as p}from"./index-w5Cc7F-Q.js";import{u as m}from"./seo-CUHZUJgV.js";const h=[["VCS","git, gh, jj","80â95%","Diff summaries, log abbreviation, status compaction"],["Build","cargo, go, make, typescript, gradle, bazel, zig, flutter, swift, vite, nx, buf, rustfmt, django, dotnet, turbo","65â90%","Error extraction, warning deduplication, progress stripping"],["Test","jest, playwright, pytest, vitest, ruby, rspec","70â90%","Failure-first output, passing test collapse, stack trace trimming"],["Lint","clippy, eslint, ruff, mypy, golangci, biome, prettier, stylelint, hadolint, trivy, semgrep, grype, cosign, syft, swiftlint, rubocop, pylint, flake8","55â85%","Severity grouping, duplicate warning collapse, line-number anchoring"],["Package","npm, pnpm, yarn, bun, pip, poetry, uv, deno, gem, composer, mix","60â80%","Install log compression, version table compaction, audit summary"],["Infra","kubectl, docker, helm, terraform, aws, az, gcloud, ansible, pulumi, argocd, vercel, fly, supabase, wrangler, skaffold, linkerd","60â85%","Resource table compaction, event stream filtering, apply-plan diffing"],["Database","mysql, psql, prisma, redis, mongosh","55â75%","Query result pagination, schema diff compaction, migration log trimming"],["AI / Data","mlflow, ollama, dbt, spark, alembic, flyway","50â70%","Training log sampling, metric table filtering, lineage compaction"],["Security","trivy, grype, syft, cosign, snyk","50â75%","CVE deduplication, severity grouping, suppressed-item collapse"],["System","curl, wget, env, jq, sysinfo, systemd, mise","50â75%","Header stripping, JSON key filtering, service table compaction"]],u=[["BCTX_BYPASS=1 <cmd>","Skip compression for a single command in the current shell"],[".bctx-bypass (file)","Place in project root â disables bctx for that entire directory"],["bctx read --mode full -- <cmd>","Run a command through bctx but apply the passthrough (no-op) lens"],["BCTX_MODE=full","Shell-wide default â routes all commands through bctx but skips compression"]],b=()=>{const{dark:s}=d([{id:"how-it-works",label:"How it works"},{id:"ecosystem",label:"Full ecosystem"},{id:"examples",label:"Compression examples"},{id:"recipes",label:"Custom recipes"},{id:"bypass",label:"Bypass methods"}]);return m({title:"Shell hook â betterCTX",description:"Transparent token compression at the shell layer. Drop-in for fish, zsh, and bash. Compresses agent context before it hits the model.",path:"/shell-hook"}),e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.3em] font-semibold mb-3",style:{color:"#ff6f00"},children:"Core Concepts · Shell compression"}),e.jsxs("h1",{className:"text-4xl lg:text-5xl font-semibold tracking-[-0.025em] leading-[1.05] mb-4",children:["Compresses every command."," ",e.jsx(a,{children:"Before any model sees it."})]}),e.jsx("p",{className:l("text-[16px] leading-[1.65] mb-8 max-w-2xl",s?"text-white/60":"text-black/60"),children:"The shell hook intercepts CLI output transparently. git diffs, npm installs, cargo builds, docker logs â all compressed to their essential information before your agent reads them. No aliases to memorise, no flags to remember."}),e.jsxs("div",{className:"flex gap-8 mb-12 font-mono text-[13px]",children:[e.jsxs("span",{children:[e.jsx("span",{className:"text-2xl font-semibold tracking-tight",children:e.jsx(a,{children:"10"})})," categories"]}),e.jsxs("span",{children:[e.jsx("span",{className:"text-2xl font-semibold tracking-tight",children:e.jsx(a,{children:"110+"})})," patterns"]}),e.jsxs("span",{children:[e.jsx("span",{className:"text-2xl font-semibold tracking-tight",children:e.jsx(a,{children:"60â90%"})})," reduction"]})]}),e.jsx(o,{id:"how-it-works",dark:s,children:"How it works"}),e.jsxs(r,{dark:s,children:["When you install the shell hook via"," ",e.jsx(i,{dark:s,children:"bctx init --agent <shell> --shell-hook"}),", bctx writes a shell function that wraps interceptable commands. When you run"," ",e.jsx(i,{dark:s,children:"git status"}),", the hook routes it through"," ",e.jsx(i,{dark:s,children:"bctx git status"})," automatically. The FilterMesh matches the command pattern to a domain-specific compressor, applies the Lens pipeline, and returns the compressed output. Your terminal sees the compressed version; your agent sees the compressed version."]}),e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3 mb-8",children:[{n:"1",t:"Command runs",b:"Agent or user runs git status"},{n:"2",t:"Hook intercepts",b:"bctx receives the raw output"},{n:"3",t:"FilterMesh matches",b:"Domain compressor identified"},{n:"4",t:"Agent sees compressed",b:"60â95% fewer tokens"}].map(n=>e.jsxs("div",{className:l("p-4 rounded-xl border text-center",s?"bg-white/[0.02] border-white/[0.06]":"bg-white border-black/[0.06]"),children:[e.jsxs("div",{className:"text-[10px] uppercase tracking-[0.3em] font-bold mb-1",style:{color:"#ff6f00"},children:["Step ",n.n]}),e.jsx("div",{className:"text-[13px] font-semibold mb-1",children:n.t}),e.jsx("p",{className:l("text-[11.5px] leading-snug",s?"text-white/55":"text-black/55"),children:n.b})]},n.n))}),e.jsx(o,{id:"ecosystem",dark:s,children:"Full ecosystem â 110+ patterns across 10 categories"}),e.jsx(r,{dark:s,children:"Each tool has a domain-specific compressor that understands its output structure â not generic line-trimming. The FilterMesh routes by command prefix to the right compressor automatically."}),e.jsx(c,{dark:s,headers:["Category","Tools","Savings","Compression approach"],rows:h}),e.jsx(o,{id:"examples",dark:s,children:"Compression examples"}),e.jsx(r,{dark:s,children:"Three real before/after comparisons showing what the compressor str
1ips vs. keeps."}),e.jsxs("div",{className:"space-y-4 mb-6",children:[e.jsxs("div",{className:"grid md:grid-cols-2 gap-3",children:[e.jsx(t,{dark:s,filename:"git status â raw · ~580 tokens",code:`On branch feature/auth 2Your branch is ahead of 'origin/feature/auth' 3by 3 commits. 4 (use "git push" to publish your local commits) 5 6Changes to be committed: 7 (use "git restore --staged <file>..." to unstage) 8 new file: src/session.ts 9 modified: src/login.ts 10 modified: src/api.ts 11 12Changes not staged for commit: 13 modified: src/session.ts 14 15Untracked files: 16 src/session.test.ts`}),e.jsx(t,{dark:s,filename:"git status â compressed · ~75 tokens",code:`feature/auth â3 17staged: +session.ts ~login.ts ~api.ts 18unstaged: ~session.ts 19untracked: session.test.ts 20 21[534 tok saved · 87%]`})]}),e.jsxs("div",{className:"grid md:grid-cols-2 gap-3",children:[e.jsx(t,{dark:s,filename:"cargo test â raw · ~3,200 tokens",code:` Compiling bctx v0.1.7 (/home/user/project) 22 Finished test [unoptimized + debuginfo] target(s) in 4.83s 23 Running unittests src/lib.rs (target/debug/deps/bctx-abc123) 24 25running 47 tests 26test vault::tier::test_immediate_trace_eviction ... ok 27test vault::tier::test_resonant_promotion ... ok 28test vault::tier::test_crystallize_after_3_confirmations ... ok 29[... 42 more ok lines ...] 30test auth::jwt::test_expired_token ... FAILED 31 32failures: 33 34---- auth::jwt::test_expired_token stdout ---- 35thread 'auth::jwt::test_expired_token' panicked at 'assertion failed: ... 36 left: Err(TokenExpired { exp: 1715000000, now: 1716000000 }) 37 right: Ok(Claims { sub: "user123", exp: 1715000000 }) 38note: run with RUST_BACKTRACE=1 for a backtrace. 39 40test result: FAILED. 46 passed; 1 failed; 0 ignored`}),e.jsx(t,{dark:s,filename:"cargo test â compressed · ~280 tokens",code:`cargo test · 47 tests 41â auth::jwt::test_expired_token 42 panicked: assertion failed 43 left: Err(TokenExpired { exp: 1715000000, now: 1716000000 }) 44 right: Ok(Claims { sub: "user123" }) 45 46result: 46 passed, 1 FAILED 47 48[2,920 tok saved · 91%]`})]}),e.jsxs("div",{className:"grid md:grid-cols-2 gap-3",children:[e.jsx(t,{dark:s,filename:"kubectl get pods â raw · ~940 tokens",code:`NAME READY STATUS RESTARTS AGE 49api-deployment-7d4f8b9c6-xk2pq 1/1 Running 0 2d 50api-deployment-7d4f8b9c6-mn8rt 1/1 Running 0 2d 51api-deployment-7d4f8b9c6-pq7ws 1/1 Running 0 2d 52worker-deployment-6c5d7b8a9-ab1cd 0/1 Pending 0 14m 53worker-deployment-6c5d7b8a9-ef2gh 1/1 Running 0 2d 54redis-statefulset-0 1/1 Running 0 5d 55postgres-statefulset-0 1/1 Running 0 5d 56postgres-statefulset-1 1/1 Running 0 5d`}),e.jsx(t,{dark:s,filename:"kubectl get pods â compressed · ~140 tokens",code:`pods: 8 total 7 Running 1 Pending 57 58â worker-deployment-6c5d7b8a9-ab1cd Pending 14m 59 60api à 3 · redis à 1 · postgres à 2 · worker à 2 61 62[800 tok saved · 85%]`})]})]}),e.jsx(o,{id:"recipes",dark:s,children:"Custom recipes"}),e.jsxs(r,{dark:s,children:["Domain compressors are written in the Recipe DSL â TOML files that define pattern matching rules for specific commands. You can add project-level recipes in"," ",e.jsx(i,{dark:s,children:".bctx/recipes/"})," or global recipes in"," ",e.jsx(i,{dark:s,children:"~/.config/bctx/recipes/"}),". Recipes stack on top of the built-in compressors."]}),e.jsx(t,{dark:s,lang:"toml",filename:".bctx/recipes/my-build.toml",code:`# Suppress verbose webpack output from a custom build script 63[[rule]] 64match = ["./scripts/build.sh"] 65lens = "aggressive" 66strip_prefix = ["webpack", "HMR", "asset"] 67keep_pattern = ["ERROR", "WARNING", "Built in"]`}),e.jsxs(p,{type:"tip",title:"FilterMesh auto-selects for 110+ commands",dark:s,children:["You only need custom recipes for commands that bctx doesn't already intercept. Run ",e.jsx(i,{dark:s,children:"bctx modes --demo signatures"})," to see what the built-in compressors produce before writing a recipe. The shell hook installs with ",e.jsx(i,{dark:s,children:"bctx init --agent <shell> --shell-hook"}),"."]}),e.jsx(o,{id:"bypass",dark:s,children:"Bypass methods"}),e.jsx(r,{dark:s,children:"Compression is opt-out per command â never silent and never sticky. Use any of the methods below when you need unmodified output."}),e.jsx(c,{dark:s,headers:["Method","Scope"],rows:u}),e.jsx(t,{dark:s,lang:"bash",code:`# Skip compression for one command 68BCTX_BYPASS=1 git log --oneline -50 69 70# No compression for this entire project 71touch .bctx-bypass 72 73# Full passthrough lens â bctx runs but applies no transforms 74bctx read --mode full -- cat src/generated.rs`})]})};export{b as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.