{"_id":"@allansantos-dev/token-guard","_rev":"3-1d2aca3a200ec429400ec920ea4dd9d3","name":"@allansantos-dev/token-guard","dist-tags":{"latest":"2.2.2"},"versions":{"2.2.0":{"name":"@allansantos-dev/token-guard","version":"2.2.0","keywords":["tokens","context","copilot","claude-code","cursor","mcp","ai-agents","guardrails","cost"],"author":{"name":"Allan Santos"},"license":"MIT","_id":"@allansantos-dev/token-guard@2.2.0","maintainers":[{"name":"allansantos-dev","email":"allannascimentodossantos@gmail.com"}],"homepage":"https://github.com/AllanSantos-DV/token-guard#readme","bugs":{"url":"https://github.com/AllanSantos-DV/token-guard/issues"},"bin":{"token-guard":"cli.cjs"},"dist":{"shasum":"8611a074d3a8fe55f7d945cfe93cc78e5fd53267","tarball":"https://registry.npmjs.org/@allansantos-dev/token-guard/-/token-guard-2.2.0.tgz","fileCount":51,"integrity":"sha512-Q7tC1R92OX2qqQ2qD7iC+8G0902FiDpavkAUAP5fzhyA4azlQnpkZ/KtLoheDJuyS3xFerldwRscEwsZ80AkIA==","signatures":[{"sig":"MEYCIQCH805I2ECf5vY/ju/sFT3unzwnOHFVPhwBmLHCm+gp8QIhANfzk01D8/us7w0+OLCAcZc5tfQtgiX8AJEYEDcVIVpS","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":333004},"main":"./lib/decide.cjs","type":"commonjs","engines":{"node":">=16"},"exports":{".":"./lib/decide.cjs","./audit":"./lib/audit.cjs","./config":"./lib/config.cjs","./decide":"./lib/decide.cjs","./payload":"./lib/payload.cjs","./contract":"./lib/contract.cjs","./mcp-cost":"./lib/mcp-cost.cjs"},"gitHead":"860fab8837df3a0da84a16fe343dd36166804e21","scripts":{"test":"node selftest.cjs && node test/adapters.test.cjs && node test/mcp-cost.test.cjs && node test/contract.test.cjs && node test/install.test.cjs && node test/savings.test.cjs && node test/postresult.test.cjs && node test/adapters.post.test.cjs && node test/adapters.prompt.test.cjs && node test/epipe.test.cjs","audit":"node token-audit.cjs","replay":"node bench/replay-transcripts.cjs","status":"node cli.cjs status","latency":"node bench/latency.cjs","mcp-cost":"node mcp-cost.cjs","test:core":"node selftest.cjs","test:hooks":"node test/postresult.test.cjs && node test/adapters.post.test.cjs && node test/adapters.prompt.test.cjs && node test/epipe.test.cjs","test:install":"node test/install.test.cjs","test:savings":"node test/savings.test.cjs","savings-bench":"node bench/savings.cjs","test:adapters":"node test/adapters.test.cjs","test:contract":"node test/contract.test.cjs","test:mcp-cost":"node test/mcp-cost.test.cjs"},"_npmUser":{"name":"allansantos-dev","email":"allannascimentodossantos@gmail.com"},"repository":{"url":"git+https://github.com/AllanSantos-DV/token-guard.git","type":"git"},"_npmVersion":"11.11.0","description":"Economia de contexto para agentes de IA, agnóstico de IDE: mede o custo real do repositório em tokens, barra as chamadas que estouram a janela devolvendo sempre a alternativa barata, mede o preâmbulo dos servidores MCP e governa o contrato de saída. Adapt","directories":{},"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/token-guard_2.2.0_1787659380109_0.3863279961673718","host":"s3://npm-registry-packages-npm-production"}},"2.2.1":{"name":"@allansantos-dev/token-guard","version":"2.2.1","keywords":["tokens","context","copilot","claude-code","cursor","mcp","ai-agents","guardrails","cost"],"author":{"name":"Allan Santos"},"license":"MIT","_id":"@allansantos-dev/token-guard@2.2.1","maintainers":[{"name":"allansantos-dev","email":"allannascimentodossantos@gmail.com"}],"homepage":"https://github.com/AllanSantos-DV/token-guard#readme","bugs":{"url":"https://github.com/AllanSantos-DV/token-guard/issues"},"bin":{"token-guard":"cli.cjs"},"dist":{"shasum":"bb98c321e9b93cf4f7a384d48ed97ae8c663bf35","tarball":"https://registry.npmjs.org/@allansantos-dev/token-guard/-/token-guard-2.2.1.tgz","fileCount":51,"integrity":"sha512-Sng2IHy0FoNflO3Q8VSamL7krzmbqTvPmA+WcWtzotzF0hmuZu+8D/IInlkFYUUzNcFG72J7Rb2B18RJzFkh9w==","signatures":[{"sig":"MEQCIFLOOZEXejtC8enjIh92drA8pLodXj3Nr5zI6/7jriU6AiBftaMJKlj06Qybpxwbgj3EWtKR0KXf16hsMIu8zstcGg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@allansantos-dev%2ftoken-guard@2.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":325524},"main":"./lib/decide.cjs","type":"commonjs","engines":{"node":">=16"},"exports":{".":"./lib/decide.cjs","./audit":"./lib/audit.cjs","./config":"./lib/config.cjs","./decide":"./lib/decide.cjs","./payload":"./lib/payload.cjs","./contract":"./lib/contract.cjs","./mcp-cost":"./lib/mcp-cost.cjs"},"gitHead":"a36927fa8612bbcb018d8df155a5ddff3678f87d","scripts":{"test":"node selftest.cjs && node test/adapters.test.cjs && node test/mcp-cost.test.cjs && node test/contract.test.cjs && node test/install.test.cjs && node test/savings.test.cjs && node test/postresult.test.cjs && node test/adapters.post.test.cjs && node test/adapters.prompt.test.cjs && node test/epipe.test.cjs","audit":"node token-audit.cjs","replay":"node bench/replay-transcripts.cjs","status":"node cli.cjs status","latency":"node bench/latency.cjs","mcp-cost":"node mcp-cost.cjs","test:core":"node selftest.cjs","test:hooks":"node test/postresult.test.cjs && node test/adapters.post.test.cjs && node test/adapters.prompt.test.cjs && node test/epipe.test.cjs","test:install":"node test/install.test.cjs","test:savings":"node test/savings.test.cjs","savings-bench":"node bench/savings.cjs","test:adapters":"node test/adapters.test.cjs","test:contract":"node test/contract.test.cjs","test:mcp-cost":"node test/mcp-cost.test.cjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:758e769a-51f0-4c47-866f-48cc13294a28"}},"repository":{"url":"git+https://github.com/AllanSantos-DV/token-guard.git","type":"git"},"_npmVersion":"11.17.0","description":"Economia de contexto para agentes de IA, agnóstico de IDE: mede o custo real do repositório em tokens, barra as chamadas que estouram a janela devolvendo sempre a alternativa barata, mede o preâmbulo dos servidores MCP e governa o contrato de saída. Adapt","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/token-guard_2.2.1_1787662232314_0.18317210055976263","host":"s3://npm-registry-packages-npm-production"}},"2.2.2":{"name":"@allansantos-dev/token-guard","version":"2.2.2","publishConfig":{"access":"public"},"description":"Economia de contexto para agentes de IA, agnóstico de IDE: mede o custo real do repositório em tokens, barra as chamadas que estouram a janela devolvendo sempre a alternativa barata, mede o preâmbulo dos servidores MCP e governa o contrato de saída. Adapt","bin":{"token-guard":"cli.cjs"},"main":"./lib/decide.cjs","exports":{".":"./lib/decide.cjs","./decide":"./lib/decide.cjs","./payload":"./lib/payload.cjs","./config":"./lib/config.cjs","./audit":"./lib/audit.cjs","./mcp-cost":"./lib/mcp-cost.cjs","./contract":"./lib/contract.cjs"},"type":"commonjs","engines":{"node":">=16"},"scripts":{"test":"node selftest.cjs && node test/adapters.test.cjs && node test/mcp-cost.test.cjs && node test/contract.test.cjs && node test/install.test.cjs && node test/savings.test.cjs && node test/postresult.test.cjs && node test/adapters.post.test.cjs && node test/adapters.prompt.test.cjs && node test/epipe.test.cjs","test:core":"node selftest.cjs","test:adapters":"node test/adapters.test.cjs","test:mcp-cost":"node test/mcp-cost.test.cjs","test:contract":"node test/contract.test.cjs","test:install":"node test/install.test.cjs","test:savings":"node test/savings.test.cjs","test:hooks":"node test/postresult.test.cjs && node test/adapters.post.test.cjs && node test/adapters.prompt.test.cjs && node test/epipe.test.cjs","audit":"node token-audit.cjs","mcp-cost":"node mcp-cost.cjs","replay":"node bench/replay-transcripts.cjs","latency":"node bench/latency.cjs","savings-bench":"node bench/savings.cjs","status":"node cli.cjs status"},"keywords":["tokens","context","copilot","claude-code","cursor","mcp","ai-agents","guardrails","cost"],"author":{"name":"Allan Santos"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/AllanSantos-DV/token-guard.git"},"bugs":{"url":"https://github.com/AllanSantos-DV/token-guard/issues"},"homepage":"https://github.com/AllanSantos-DV/token-guard#readme","gitHead":"bce890ead820da1607a4f0b3e79e4bab2834d8f8","_id":"@allansantos-dev/token-guard@2.2.2","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-TpD1jI9IxT2BT8oL/Zs4431ZePQ4aA9oymVjquOFS/UpikR+kLM8xbMbW4c45rWMsWKjJVgmQZv9p/rEcB4HnQ==","shasum":"0c052989b37d8acb8599047e36c77cc11467e538","tarball":"https://registry.npmjs.org/@allansantos-dev/token-guard/-/token-guard-2.2.2.tgz","fileCount":52,"unpackedSize":331611,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@allansantos-dev%2ftoken-guard@2.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCVoRb4vhmqPEmX5uH7llqzNIKZ/5jMTWNTgjg3u9EyCAIgWCb7lzBBiQs3E14HwkRsVtRsC0ZPtMWS7HGqq/MmlQc="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:758e769a-51f0-4c47-866f-48cc13294a28"}},"directories":{},"maintainers":[{"name":"allansantos-dev","email":"allannascimentodossantos@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/token-guard_2.2.2_1787665823080_0.6341681286941669"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-25T12:02:59.841Z","modified":"2026-08-25T13:50:23.534Z","2.2.0":"2026-08-25T12:03:00.270Z","2.2.1":"2026-08-25T12:50:32.455Z","2.2.2":"2026-08-25T13:50:23.211Z"},"bugs":{"url":"https://github.com/AllanSantos-DV/token-guard/issues"},"author":{"name":"Allan Santos"},"license":"MIT","homepage":"https://github.com/AllanSantos-DV/token-guard#readme","keywords":["tokens","context","copilot","claude-code","cursor","mcp","ai-agents","guardrails","cost"],"repository":{"type":"git","url":"git+https://github.com/AllanSantos-DV/token-guard.git"},"description":"Economia de contexto para agentes de IA, agnóstico de IDE: mede o custo real do repositório em tokens, barra as chamadas que estouram a janela devolvendo sempre a alternativa barata, mede o preâmbulo dos servidores MCP e governa o contrato de saída. Adapt","maintainers":[{"name":"allansantos-dev","email":"allannascimentodossantos@gmail.com"}],"readme":"# token-guard\n\n[![ci](https://github.com/AllanSantos-DV/token-guard/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/AllanSantos-DV/token-guard/actions/workflows/ci.yml)\n[![release](https://img.shields.io/github/v/release/AllanSantos-DV/token-guard)](https://github.com/AllanSantos-DV/token-guard/releases)\n[![npm](https://img.shields.io/npm/v/%40allansantos-dev/token-guard?label=npm&color=C2402A)](https://www.npmjs.com/package/@allansantos-dev/token-guard)\n[![site](https://img.shields.io/badge/site-allansantos-dv.github.io%2Ftoken--guard-1E7F4F)](https://allansantos-dv.github.io/token-guard/)\n\n**[Site &raquo;](https://allansantos-dv.github.io/token-guard/)** &middot; com medidor interativo de janela de contexto, n&uacute;meros medidos e matriz de cobertura.\n\n**Economia de contexto para agentes de IA — agnóstico de IDE, como configuração versionada, não como produto.**\n\nUm kit portátil que qualquer pessoa instala em qualquer repositório, em qualquer IDE.\nSem plugin proprietário, sem marketplace, sem servidor, sem licença, sem dependência npm.\nSó Node stdlib e arquivos de texto que entram no seu git.\n\nFunciona em **Copilot CLI/App, Claude Code, Cursor** e — via MCP — em qualquer IDE que\nfale o protocolo (VS Code, Windsurf, Zed, JetBrains).\nA cobertura varia por harness e está documentada sem maquiagem em [docs/IDES.md](docs/IDES.md).\n\n---\n\n## O problema, em um número\n\nRode isto num repositório grande de verdade:\n\n```bash\nnode token-audit.cjs /caminho/do/repo\n```\n\nVocê vai descobrir, entre outras coisas, quanto custa **só a lista de nomes dos arquivos** —\nantes de o agente ler uma única linha de código. Em monorepos, essa listagem sozinha\ncostuma valer dezenas de janelas de contexto.\n\nA janela é fixa. O repositório não. Portanto **a seleção do que entra é a arquitetura** —\ne é exatamente ela que este kit governa.\n\n---\n\n## O que vem na caixa\n\n### Núcleo — não conhece nenhum IDE\n\n| Peça | O que faz |\n|---|---|\n| `lib/decide.cjs` | A decisão, compartilhada por **todos** os adapters — para que nunca divirjam. |\n| `lib/payload.cjs` | Leitor de payload agnóstico: normaliza o envelope de 4+ runtimes. |\n| `lib/rules.cjs` | As quatro regras: `broadScan`, `blindRead`, `noisePath`, `shellDump`. |\n| `lib/config.cjs` | Config subindo a árvore, com fallback global (4 homes) e escape hatch por env. |\n| `lib/audit.cjs` | A medição de custo de contexto. |\n| `lib/mcp-cost.cjs` | A medição do preâmbulo MCP: quanto os servidores declarados custam por sessão — com recomendações acionáveis por servidor e ferramenta. |\n| `lib/contract.cjs` | O contrato de saída: regras por gatilho de evidência, injetadas 1×/sessão via UserPromptSubmit ([docs](docs/CONTRACT.md)). |\n| `lib/postresult.cjs` | A regra `bigResult`: resultado de ferramenta gigante vira stub + versão integral em disco + alternativa barata. |\n\n### Adapters — só tradução de envelope, zero regra de negócio\n\n| Adapter | Harness | Bloqueia? |\n|---|---|---|\n| `adapters/copilot-cli.mjs` | Copilot CLI / Copilot App (in-process, ~0,15 ms) | ✅ |\n| `adapters/hook-cmd.cjs` | Copilot CLI (`hooks.json`) e Claude Code (`settings.json`) | ✅ |\n| `adapters/cursor-hook.cjs` | Cursor — `preToolUse` genérico (recente) + os 3 eventos nomeados | ✅ todas as 4 |\n| `adapters/mcp-server.cjs` | Qualquer IDE com MCP — VS Code, Windsurf, Zed, JetBrains | ❌ só orienta |\n\n### Ferramentas e procedimento\n\n| Peça | O que faz |\n|---|---|\n| `token-audit.cjs` | Mede o custo de contexto de qualquer repositório e grava o cache que calibra os guards. |\n| `mcp-cost.cjs` | Mede o custo fixo de preâmbulo dos servidores MCP declarados, por handshake real. |\n| `agents/scout.agent.md` | Sub-agente de investigação com contexto descartável. |\n| `skills/token-economy/SKILL.md` | O procedimento, em divulgação progressiva. |\n| `cli.cjs` | `init`, `audit`, `status`, `mcp`, `mcp-cost`, `contract`, `test` — a porta de entrada do `npx`. |\n| `install.cjs` | Instala em 5 alvos, com **merge** seguro de todo arquivo de config. |\n| `selftest.cjs` | o núcleo contra o hook real, nos formatos de payload dos runtimes. |\n| `test/adapters.test.cjs` | tradução dos adapters Cursor e MCP. |\n| `test/mcp-cost.test.cjs` | handshake, descoberta e diagnóstico do medidor de MCP. |\n| `test/contract.test.cjs` | parsing, evidência e estado do contrato. |\n| `test/install.test.cjs` | integração do instalador: idempotência, reparo de registro obsoleto e preservação de assets. |\n| `test/savings.test.cjs` | a promessa central travada: economia líquida > 0. |\n| `test/postresult.test.cjs` | a regra bigResult (truncar sem perder o destino). |\n| `test/adapters.post.test.cjs` / `test/adapters.prompt.test.cjs` | os hooks PostToolUse e UserPromptSubmit ponta a ponta. |\n\nCada suíte imprime a própria contagem — não confie em números copiados daqui.\n\n---\n\n## Instalação\n\n```bash\n# 1. veja o tamanho do problema antes de instalar qualquer coisa\nnpx @allansantos-dev/token-guard audit\n\n# 2. instale onde você trabalha, começando sem atrito\nnpx @allansantos-dev/token-guard init --target all --mode warn\n\n# 3. confirme que responde neste ambiente\nnpx @allansantos-dev/token-guard test\n```\n\nAlvos disponíveis:\n\n```bash\nnpx @allansantos-dev/token-guard init --target copilot   # Copilot CLI / App    (bloqueia)\nnpx @allansantos-dev/token-guard init --target claude    # Claude Code          (bloqueia)\nnpx @allansantos-dev/token-guard init --target cursor    # Cursor (recente)      (bloqueia)\nnpx @allansantos-dev/token-guard init --target mcp       # VS Code, Windsurf…   (só orienta)\nnpx @allansantos-dev/token-guard init --target repo      # .github/ do repo     (viaja no git)\nnpx @allansantos-dev/token-guard init --target all       # tudo que é de máquina\n```\n\nDepois:\n\n```bash\nnpx @allansantos-dev/token-guard audit     # veja o tamanho do problema neste repo\nnpx @allansantos-dev/token-guard test      # todas as suítes\nnpx @allansantos-dev/token-guard status    # confira a configuração ativa\n```\n\nReinicie a sessão do agente para carregar o hook.\n\n**Trabalha em repositório do cliente?** Use só alvos de máquina (`copilot`, `claude`,\n`cursor`, `mcp`): nada é escrito dentro do repositório, tudo vai para o seu perfil.\n\nO instalador **nunca sobrescreve** um `hooks.json`, um `settings.json`, um\n`token-guard.config.json`, um agente ou uma skill que já existam — ele preserva e faz\nmerge. Rodar de novo é idempotente. Exceção honesta: um registro de hook apontando\npara script que **não existe mais** (layout de versão antiga) é reparado, não\nmascarado — deixar no lugar seria guard desligado em silêncio.\n\nDetalhes em [docs/INSTALL.md](docs/INSTALL.md).\n\n### O que fica no repositório (alvo `repo`)\n\n```\n.github/\n  hooks/hooks.json                    ← merge: suas entradas + token-guard\n  token-guard/\n    token-guard.cjs                   ← o hook (shim → adapters/hook-cmd.cjs)\n    token-audit.cjs                   ← o medidor\n    selftest.cjs                      ← a bateria de testes\n    cli.cjs                           ← init/audit/status/mcp-cost/contract/test\n    adapters/{copilot-cli.mjs, hook-cmd.cjs, cursor-hook.cjs, mcp-server.cjs}\n    lib/{payload,config,rules,decide,audit,mcp-cost,contract}.cjs\n  agents/scout.agent.md\n  skills/token-economy/SKILL.md\ntoken-guard.config.json               ← ajustes deste repositório\n.token-guard/                         ← cache e estado de sessão (entra no .gitignore)\n```\n\nTudo isso é versionado. **Quem clonar o repositório herda a economia** — não há\nmáquina para configurar, nem passo manual de onboarding.\n\n---\n\n## A regra de ouro: nunca um deny cego\n\nTodo bloqueio devolve ao agente a **alternativa barata, pronta para reexecutar**.\nUm guard que só diz \"não\" transfere o problema para a pessoa; um guard que ensina\nresolve o problema e treina o agente ao mesmo tempo.\n\nExemplo real de bloqueio:\n\n```\ntoken-guard/broadScan: the pattern \"**/*\" is unbounded in both breadth and type,\nso it returns the path of about 215.112 files. A bare file listing is pure overhead:\nit answers \"what exists\", never \"where is the thing I need\".\nDO THIS INSTEAD: bound it on at least one axis — (a) by type: \"**/*.java\";\n(b) by directory: pass paths=[\"src/main/java\"]; (c) by name: \"**/*Service*.java\".\nTo find code by meaning rather than by filename, search content instead of listing paths.\n(PT-BR) ...\n```\n\nO agente lê isso, corrige e segue. Não há intervenção humana no meio.\n\n---\n\n## As quatro regras\n\n| Regra | Barra | Libera |\n|---|---|---|\n| **broadScan** | `glob \"**/*\"` sem escopo; busca em modo conteúdo sem teto nem filtro | `**/*.java`, `src/**`, `paths:[\"src\"]`, `head_limit`, modo `files_with_matches` |\n| **blindRead** | Ler arquivo > 50 KB sem faixa de linhas | Qualquer leitura com `view_range` / `offset+limit`; arquivos pequenos |\n| **noisePath** | Caminhos em `node_modules`, `target`, `dist`, `.git`, `venv`, `.mcp-memory`… | Qualquer caminho na `allowlist` |\n| **shellDump** | `Get-ChildItem -Recurse`, `ls -R`, `dir /s`, `find .`, `tree`, `grep -r` sem limite | Os mesmos comandos com filtro (`-name`) ou teto (`\\| head -50`, `\\| Select-Object -First 50`) |\n\n### Por que não barramos toda busca ampla\n\nO custo de uma busca não é a varredura — é a **saída**. Um `grep` em todo o repositório\nque devolve três linhas é barato e é frequentemente o movimento certo. Por isso\n`files_with_matches` passa sempre, e só o modo conteúdo *sem teto e sem filtro* é barrado.\n\nRepositórios com menos de 400 arquivos ficam livres dos guards de varredura:\nabaixo disso o custo é irrelevante e a disciplina só atrapalha.\n\n---\n\n## Configuração\n\n`token-guard.config.json` na raiz do repositório. Tudo é opcional.\n\n```json\n{\n  \"mode\": \"block\",\n  \"rules\": { \"noisePath\": true, \"blindRead\": true, \"broadScan\": true, \"shellDump\": true },\n  \"limits\": { \"readBytesWithoutRange\": 51200, \"minRepoFilesForScanGuard\": 400 },\n  \"noiseDirsExtra\": [\"generated\", \"protos-out\"],\n  \"allowlist\": [\"node_modules/@minha-lib/types\"]\n}\n```\n\n- `mode`: `block` (nega e corrige) · `warn` (pede confirmação mostrando a correção) · `off`\n- `noiseDirsExtra` / `sourceExtExtra` **somam** aos defaults.\n  Use `noiseDirs` / `sourceExt` (sem `Extra`) só para substituir a lista inteira.\n- `allowlist`: substrings de caminho sempre liberadas.\n\n### Escape hatches\n\n| Situação | Como sair |\n|---|---|\n| Emergência pontual | `TOKEN_GUARD=off` no ambiente |\n| Testar sem atrito | `TOKEN_GUARD=warn` |\n| Uma regra não serve a este repo | `\"rules\": { \"shellDump\": false }` |\n| Um caminho específico é legítimo | `\"allowlist\": [\"...\"]` |\n\nUm guard sem saída de emergência vira dívida. Estas quatro existem de propósito.\n\n---\n\n## O outro custo: o preâmbulo MCP\n\nA auditoria mede o que o agente **lê durante** a sessão. Ela não vê o que já estava\ncarregado **antes da primeira pergunta**: o schema de cada ferramenta de cada servidor MCP\ndeclarado. Esse custo é fixo, silencioso e pago em toda sessão, use você a ferramenta ou não.\n\n```bash\nnpx @allansantos-dev/token-guard mcp-cost --list      # só inventaria: nada é executado\nnpx @allansantos-dev/token-guard mcp-cost             # mede de verdade, por handshake\n```\n\nNão há como estimar isso de fora: o tamanho do schema só existe depois que o servidor\nresponde `tools/list`. Então o medidor faz o handshake real do protocolo —\n`initialize` → `notifications/initialized` → `tools/list` — sobre stdio, e conta os\ncaracteres do que voltou. **Isso significa que os servidores declarados são executados.**\nUse `--list` quando quiser apenas o inventário.\n\nUma medição real, nesta máquina:\n\n```\n7 declarados · 4 sondados · 3 sem resposta\n\nGitHub          26 ferram.   3.957 tok\nPlaywright      33 ferram.   3.454 tok\nfirebase-mcp    12 ferram.   1.883 tok\ntoken-guard      3 ferram.     400 tok\n\n74 ferramentas em 4 servidores ≈ 9.695 tokens = 0,048 janela(s), em toda sessão\n```\n\nServidores que não respondem aparecem numa seção própria, com o motivo — eles continuam\ncustando janela, só não sabemos quanto. Transporte HTTP não é sondável por stdio e é\ndeclarado como tal, em vez de ser contado como zero.\n\n| Flag | Efeito |\n|---|---|\n| `--list` | Inventaria sem executar nada. |\n| `--server NOME` | Mede um servidor só. |\n| `--timeout MS` | Teto por handshake (padrão 15000). |\n| `--json` | Dados crus. |\n\nO medidor **só mede**. Não instala, não desinstala, não desliga servidor nenhum — a decisão\nde cortar uma ferramenta é sua, e depende de quanto você a usa.\n\n---\n\n## A economia, medida (e a limitação dela)\n\nA promessa central tem número próprio — e premissas declaradas:\n\n```bash\nnode bench/savings.cjs        # simulação da economia líquida por sessão\nnode test/savings.test.cjs    # a promessa travada: se virar 0, a suíte falha\n```\n\nNo repositório de referência (~215 mil arquivos), com truncamento real de\ntool result (~25 k tokens) e o custo dos próprios denies contado na conta,\na simulação de sessões mostra **economia líquida de ~85–205 k tokens por sessão**\n(0,4–1 janela de contexto), conforme o agente aprenda rápido ou repita o erro.\nO overhead das mensagens de deny é ruído (<2% do evitado). Em repos pequenos o\nkit não atrapalha por design. O ponto de equilíbrio é alto: os guards só deixam\nde valer se **~94% dos bloqueios forem falsos positivos**.\n\nLimitação honesta: é simulação paramétrica ancorada em tamanhos medidos com\nsequência sintética de chamadas — não replay de transcripts vivos. Os três\nnúmeros que sustentam as premissas são medidos por este mesmo kit:\n`token-audit` (tamanho do repo), `mcp-cost` (preâmbulo) e o bench acima.\n\n---\n\n## Escopo, ciclo de vida e custo\n\n**Não existe escopo \"por sessão\".** Não há daemon do guard, versão residente nem\nestado entre sessões. Há dois modos de execução, e a diferença é de política:\n\n| | **Máquina** (`--target copilot\\|claude\\|cursor\\|mcp`) | **Repositório** (`--target repo`) |\n|---|---|---|\n| Onde | `~/.copilot/`, `~/.claude/`, `~/.cursor/`, `~/.token-guard/` | `.github/` do repo |\n| Alcance | Todos os repos **desta máquina** | Só este repo, **mas viaja no git** |\n| Quem herda | só você | **quem clonar** |\n| Execução | in-process (Copilot) ou comando (Claude/Cursor) | comando por chamada |\n| Custo por chamada | **0,15 ms** in-process · **330 ms** por comando | **330 ms** |\n| Extras | expõe `token_audit` e `token_guard_status` ao agente | — |\n| Repositório do cliente | ✅ nada é commitado | ❌ exige commit |\n\nOs modos podem coexistir: todos importam a mesma decisão de `lib/decide.cjs`, então\no veredito é idêntico — apenas avaliado duas vezes. Para o dia a dia, escolha um.\n\n### Custo de latência (meça na sua máquina)\n\nUm kit de eficiência precisa declarar o próprio custo. O README não publica\nconstantes: publique a SUA medição.\n\n```bash\nnode bench/latency.cjs        # plugin vs hook de comando vs piso do Node\n```\n\nNa máquina do autor (Windows corporativo, Node 25, antivírus ativo) a mediana\nfoi **0,153 ms** in-process contra **330 ms** por spawn — quase todo o custo do\nmodo comando é o runtime (`node -e \"0\"` custava 216 ms ali), não o guard. Em\nmáquina sem antivírus corporativo os dois números caem juntos; a razão entre\neles permanece. Duas defesas, nesta ordem:\n\n1. **Use o modo plugin** quando o alcance de máquina servir. O custo desaparece.\n2. **No modo repositório**, o `matcher` do `hooks.json` impede o processo de nascer\n   para ferramentas que nunca seriam barradas (`edit`, `create`, PR, issue). Com ele,\n   supondo ~40% das chamadas nas famílias vigiadas, o custo fica em torno de\n   **5 segundos por sessão**. Sem ele, ~12 s.\n\n---\n\n- **Extensão `.cjs` em todos os arquivos**, de propósito: `.js` viraria ESM num repo com\n  `\"type\": \"module\"` e o hook quebraria. `.cjs` é CommonJS sempre.\n- **Payload lido por cascata**, cobrindo quatro runtimes:\n  `toolCall.toolName/input` (VS Code Chat) · `tool_name/tool_input` (Claude Code CLI) ·\n  `toolName/toolInput` (legado) · `toolName/toolArgs/workingDirectory` (extensão in-process).\n- **Nunca faz spawn de `process.execPath`.** Dentro de um harness empacotado esse caminho\n  aponta para o binário do harness, não para o Node — por isso a auditoria é uma\n  biblioteca (`lib/audit.cjs`) que a extensão chama in-process.\n- **`package-lock.json` é artefato de desenvolvimento** (integridade do repositório);\n  em runtime o kit não tem dependência nenhuma para instalar. O import do SDK no\n  adapter Copilot (`@github/copilot-sdk`) é provido pelo próprio host na hora em\n  que a extensão carrega — nunca via npm deste pacote. O campo `\"extensions\": [\".\"]`\n  do `plugin.json` declara ao Copilot CLI que a extensão se aplica a qualquer\n  diretório de trabalho.\n- **Ferramentas casadas por família**, não por nome exato:\n  `view`/`read_file`/`Read`, `grep`/`grep_search`/`Grep`, `glob`/`file_search`/`Glob`,\n  `bash`/`powershell`/`run_in_terminal`. Harness novo costuma cair numa família existente.\n- **Falha sempre para o lado seguro.** Regra quebrada, payload inválido, stdin ausente,\n  config corrompido: tudo resulta em liberar. Um guard de economia jamais pode\n  derrubar a sessão que deveria baratear.\n\n---\n\n## Adoção sugerida\n\n| Quando | O quê | Esforço |\n|---|---|---|\n| Dia 1 | `token-guard init --target all --mode warn` + rodar a auditoria | nenhum |\n| Semana 1 | Ler os avisos que apareceram, ajustar `allowlist` e `noiseDirsExtra` | baixo |\n| Semana 2 | Virar para `\"mode\": \"block\"` | nenhum |\n| Contínuo | Rodar a auditoria a cada release e acompanhar a tendência | baixo |\n\nComece medindo. Sem o número de antes, não há como provar o de depois.\n\n---\n\n## Testes\n\n```bash\nnpm test                          # todas as suítes\nnode selftest.cjs                 # o núcleo, contra o hook real\nnode test/adapters.test.cjs       # a tradução dos adapters\nnode test/mcp-cost.test.cjs       # o medidor de preâmbulo MCP\nnode test/contract.test.cjs       # o contrato de saída\nnode test/install.test.cjs        # o instalador contra o FS real\nnode test/savings.test.cjs        # a economia líquida travada\nnpm run test:hooks                # bigResult + UserPromptSubmit ponta a ponta\n```\n\nCada suíte imprime a própria contagem e sai com código 1 se qualquer caso falhar.\nO CI roda todas em Linux e Windows sobre Node 16, 18, 20 e 22 — mais a simulação de\ninstalação (`--dry-run`) e a auditoria do próprio repositório.\n\n**Núcleo:** os quatro guards nos três formatos de payload (mais o envelope do SDK\nin-process), os caminhos que **devem** passar (o mais importante: falso positivo é\npior que falso negativo aqui) e os escape hatches. Inclui as regressões do gate\nadversarial: dumps modernos (`rg --files`, `fd`, `gci -r`), falsos positivos de\npalavra solta (`tree` num commit), casing de filesystem e resolução de caminho\nrelativo contra o cwd do payload.\n\n**Adapters:** a tradução de envelope do Cursor e o protocolo JSON-RPC do MCP —\nincluindo fail-open sob entrada corrompida, que é onde um guard mal escrito derruba a sessão.\n\n**MCP cost:** o handshake contra servidores stdio sintéticos — servidor que loga texto\npuro no stdout, que devolve erro JSON-RPC, que morre no boot, e que responde mas **nunca\nencerra** (medido no timeout, não descartado). Mais a descoberta sem executar nada e o\ndiagnóstico: o motivo relatado tem que ser a causa, não o rodapé de versão do Node.\n\n**Contrato:** parsing por seção, evidência acumulada, estado por sessão no disco,\npoda por TTL e id de sessão que não escapa do diretório.\n\n**Instalação:** idempotência real, reparo de registro apontando para script morto\ne preservação de agente/skill personalizados.\n\n---\n\n## Contrato de saída\n\nA economia tem dois lados. Os guards cuidam da **entrada**; o contrato cuida da\n**saída**: regras de forma (`contract.default.md`) divididas por gatilho de\nevidência — `sempre`, `quando: codigo` quando a sessão tocou código-fonte,\n`quando: teste`, `quando: docs` — mais um bloco `subagente` para contexto descartável.\n\nUm `contract.md` na raiz substitui seções inteiras do padrão. Inspecione com:\n\n```bash\nnpx @allansantos-dev/token-guard contract                          # seções, custo e ordem\nnpx @allansantos-dev/token-guard contract --touched src/a.ts       # simula a evidência da sessão\nnpx @allansantos-dev/token-guard contract --subagente              # bloco pronto p/ colar no scout\n```\n\nEstado honesto: a camada \"sempre\" entra automaticamente — Claude Code injeta via\n`UserPromptSubmit` e o Copilot via `onUserPromptSubmitted`, com os gatilhos por\nevidência (`codigo`/`teste`/`docs`) alimentados pelos arquivos que a sessão tocou.\nNos harnesses sem hook de prompt (Cursor, MCP), o consumo é manual\n(`--subagente` no prompt do scout). Detalhes em [docs/CONTRACT.md](docs/CONTRACT.md).\n\n---\n\n## Documentação\n\n| Documento | Conteúdo |\n|---|---|\n| [docs/INSTALL.md](docs/INSTALL.md) | Instalação, desinstalação completa, repositórios de cliente |\n| [docs/IDES.md](docs/IDES.md) | Cobertura real por IDE/harness, sem maquiagem |\n| [docs/CONFIG.md](docs/CONFIG.md) | Referência de toda chave de config + estado em disco |\n| [docs/CONTRACT.md](docs/CONTRACT.md) | O contrato de saída, mecanismo e status |\n| [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) | Guard silencioso, config ignorada, diagnósticos |\n| [SECURITY.md](SECURITY.md) | O que executa, o que lê, o que grava — dados e privacidade |\n\n---\n\n## Licença\n\nMIT. Use, copie, modifique e distribua à vontade.\n","readmeFilename":"README.md"}