Skip to content

Repository files navigation

██████╗ ███████╗    ██╗  ██╗ ██████╗  ██████╗ ██╗  ██╗███████╗
██╔══██╗██╔════╝    ██║  ██║██╔═══██╗██╔═══██╗██║ ██╔╝██╔════╝
██████╔╝███████╗    ███████║██║   ██║██║   ██║█████╔╝ ███████╗
██╔═══╝ ╚════██║    ██╔══██║██║   ██║██║   ██║██╔═██╗ ╚════██║
██║     ███████║    ██║  ██║╚██████╔╝╚██████╔╝██║  ██╗███████║
╚═╝     ╚══════╝    ╚═╝  ╚═╝ ╚═════╝  ╚═════╝ ╚═╝  ╚═╝╚══════╝
         Claude Code hooks exclusivos para ProStaff API

Node License Project


╔══════════════════════════════════════════════════════════════════════════════╗
║  PS-HOOKS - Claude Code Developer Toolkit para ProStaff API                  ║
╠══════════════════════════════════════════════════════════════════════════════╣
║  Comprime output de CLI, injeta contexto de dominio e gerencia modo de       ║
║  trabalho - exclusivo para sessoes no repositorio prostaff-api.              ║
║                                                                              ║
║  reducao medida contra saida real: rspec 99%, rubocop 91%, brakeman 91%      ║
║  reproduza com `npm run measure`; os numeros sao testados, não estimativa    ║
╚══════════════════════════════════════════════════════════════════════════════╝

▶ Funcionalidades (clique para expandir)
┌─────────────────────────────────────────────────────────────────────────────┐
│  [■] Command Compressor   - rspec, brakeman, rubocop, docker logs filtrados │
│  [■] Domain Detector      - git status detecta modulo ativo automaticamente │
│  [■] Context Injector     - injeta so o slice relevante do CLAUDE.md        │
│  [■] Mode Commander       - skills de plugin: /ps:domain, /ps:check, ...    │
│  [■] Statusline Badge     - [PS:AI] / [PS:AUTH] / [PS:MATCHES] etc          │
│  [■] Zero Dependencies    - Node.js stdlib apenas, sem npm install          │
│  [■] Project-scoped       - ativa exclusivamente em sessoes prostaff-api    │
│  [■] Fail-safe            - erro no filtro cai para output bruto, sem perda │
└─────────────────────────────────────────────────────────────────────────────┘

Sumario

┌──────────────────────────────────────────────────────┐
│  01 · Como Funciona                                  │
│  02 · Instalacao                                     │
│  03 · Hooks Implementados                            │
│  04 · Filtros de Comandos                            │
│  05 · Dominios ProStaff                              │
│  06 · Comandos /ps:                                  │
│  07 · Statusline                                     │
│  08 · Estrutura do Projeto                           │
│  09 · Referencia de Inspiracao                       │
└──────────────────────────────────────────────────────┘

01 · Como Funciona

Tres hooks independentes atuam em momentos diferentes da sessao Claude Code:

SESSION START
─────────────
  session-start.js
    → git status do prostaff-api
    → detecta dominio ativo (auth / ai / matches / ...)
    → injeta contexto minimo especifico ao dominio
    → escreve flag para statusline

DURANTE A SESSAO (por tool call Bash)
──────────────────────────────────────
  pre-tool-use.js (PreToolUse hook)
    → le o comando Bash que Claude quer executar
    → verifica se e um comando ProStaff conhecido
    → reescreve para: node ps-filter.js <tipo> -- <comando original>
    → ps-filter.js executa o comando real + comprime output

POR COMANDO
───────────
  skills/<nome>/SKILL.md (skill do plugin ps)
    → /ps:help, /ps:domain, /ps:check, /ps:full
    → /ps:domain executa bin/ps-domain.js e grava o estado da sessao

Fluxo do command compressor em detalhe:

Claude executa:  bundle exec rspec spec/controllers/players_controller_spec.rb
                              |
               pre-tool-use.js intercepta (PreToolUse)
                              |
                    reescreve o comando para:
        node /path/bin/ps-filter.js rspec -- bundle exec rspec spec/...
                              |
          ps-filter.js roda o comando original via sh -c
                              |
              lib/filters/rspec.js comprime o output
                              |
Claude ve:
  FAILURES (1):

  1) PlayersController GET /players returns players list
     Error: expected the response to have status code 200 but it was 401
     At: ./spec/controllers/api/v1/players_controller_spec.rb:45

  SUMMARY: 45 examples, 1 failure

02 · Instalacao

Os comandos /ps: sao skills de plugin. Um comando com : no nome so existe nesse formato: o TUI resolve qualquer texto que comece com / contra o registry de comandos antes de submeter, e aborta com Unknown command se nao achar. Um hook de UserPromptSubmit nunca chega a ver o texto.

Instalar como plugin (carrega hooks e comandos juntos):

# permanente, carrega em toda sessao como ps@skills-dir
ln -s /caminho/para/prostaff-hooks ~/.claude/skills/prostaff-hooks

# ou so na sessao atual, para testar
claude --plugin-dir /caminho/para/prostaff-hooks

Conferir o que foi carregado:

claude plugin list
claude plugin details ps

Statusline (opcional, e o unico passo que o plugin nao cobre): o manifesto de plugin nao tem campo para statusLine, entao o badge continua vindo do install.sh.

bash /caminho/para/prostaff-hooks/install.sh /caminho/para/prostaff-api
npm test

O install.sh tambem serve para quem prefere registrar os hooks direto no settings.json do projeto em vez de instalar o plugin. Ele faz backup do arquivo existente, aborta se nao for JSON valido, e e idempotente. Nesse caminho os comandos /ps: nao existem, porque dependem do plugin.

03 · Hooks Implementados

╔══════════════════════╦════════════════════════════════════════════════════════╗
║  HOOK                ║  ARQUIVO                                               ║
╠══════════════════════╬════════════════════════════════════════════════════════╣
║  SessionStart        ║  hooks/session-start.js                                ║
║                      ║  → detecta dominio via git status                      ║
║                      ║  → injeta contexto minimo do dominio ativo             ║
╠══════════════════════╬════════════════════════════════════════════════════════╣
║  PreToolUse (Bash)   ║  hooks/pre-tool-use.js                                 ║
║                      ║  → reescreve comandos conhecidos para ps-filter        ║
║                      ║  → ativa so em sessoes prostaff-api                    ║
╠══════════════════════╬════════════════════════════════════════════════════════╣
║  (removido)          ║  UserPromptSubmit nao existe mais: o TUI intercepta    ║
║                      ║  /ps: antes do hook. Virou skill de plugin.            ║
╚══════════════════════╩════════════════════════════════════════════════════════╝

Ativacao condicional: os hooks verificam o cwd que o runtime manda no payload (com fallback para transcript_path e process.cwd()) - se nao incluirem prostaff-api, fazem process.exit(0) imediatamente sem interferir em outros projetos.

Veredito pelo exit code: o ps-filter.js propaga o codigo de saida real do comando, e comando morto por sinal ou timeout vira codigo diferente de zero. O filtro so extrai detalhe; quem decide se passou e o exit code. Quando o comando falha e o filtro nao consegue explicar por que, a saida bruta e preservada.


04 · Filtros de Comandos

╔═══════════════════════════════╦═══════════════╦══════════════════════════════╗
║  COMANDO ORIGINAL             ║  FILTRO       ║  OUTPUT                      ║
╠═══════════════════════════════╬═══════════════╬══════════════════════════════╣
║  bundle exec rspec            ║  rspec.js     ║  Failures + summary apenas   ║
║  rspec                        ║               ║                              ║
╠═══════════════════════════════╬═══════════════╬══════════════════════════════╣
║  brakeman                     ║  brakeman.js  ║  HIGH/MEDIUM apenas          ║
║  (injeta -f json -q auto)     ║               ║                              ║
╠═══════════════════════════════╬═══════════════╬══════════════════════════════╣
║  bundle exec rubocop          ║  rubocop.js   ║  Agrupado por cop, top 10    ║
║  rubocop                      ║               ║                              ║
╠═══════════════════════════════╬═══════════════╬══════════════════════════════╣
║  docker compose logs          ║  docker.js    ║  Erros + ultimas 30 linhas   ║
║  docker <container> logs      ║               ║                              ║
╠═══════════════════════════════╬═══════════════╬══════════════════════════════╣
║  rails db:migrate             ║  rails.js     ║  Migrations + erros apenas   ║
║  bundle exec rails db:migrate ║               ║                              ║
╚═══════════════════════════════╩═══════════════╩══════════════════════════════╝

Reducao medida

npm run measure roda os filtros contra saida real, guardada em tests/fixtures/, e imprime esta tabela. Os mesmos cenarios rodam no npm test, cobrando dois criterios: a reducao nao caiu e o sinal sobreviveu.

cenario antes depois reducao
rspec, suite nao carrega (203 erros) 194.551 1.604 99,2%
rubocop, 61 offenses em 553 arquivos 17.201 1.491 91,3%
rails db:migrate, 138 migrations 103.678 9.491 90,8%
brakeman, 1 warning HIGH 2.335 214 90,8%
rspec, 43 falhas em 3330 exemplos 129.707 16.585 87,2%
docker logs, postgres em 222 linhas 18.851 3.631 80,7%
rspec, 4 falhas em 40 exemplos 1.904 1.069 43,9%

Caracteres, nao tokens. Capturado contra prostaff-api com RuboCop 1.81, Brakeman 8.0 e RSpec 3.13; a proveniencia de cada arquivo esta em tests/fixtures/PROVENIENCIA.md.

Nao ha um numero unico, e a ultima linha e a mais honesta. A reducao depende de quanto a ferramenta fala: a saida comprimida tem tamanho quase constante, entao quanto maior a saida original, maior a reducao. Suite pequena que falha em quatro exemplos economiza pouco, porque nao havia muito a economizar. O ganho aparece onde doi, que e a saida de 190 KB.

Estes numeros so existem porque a medicao encontrou quatro filtros quebrados. Antes dela, o compressor do brakeman entregava 500 caracteres de metadata de scan e escondia o unico warning HIGH do projeto, com otimos 76% de reducao. Um filtro que apaga tudo reduz 100%: e por isso que o teste cobra o sinal junto com a taxa.

O rails db:migrate era o oposto: guardava toda linha de DDL e todo tempo por operacao, entao num banco zerado reduzia 5,8% - passthrough justamente onde a janela precisava dele. Agora o corpo de cada migration vira contagem quando o run passa de cinco, e a migration que nao concluiu mantem o corpo inteiro, porque e a que se quer ver.

▶ Exemplos de output comprimido

RSpec (antes: ~400 linhas, depois: ~10 linhas)

FAILURES (2):

1) Api::V1::PlayersController GET /api/v1/players returns players list
   Error: expected the response to have status code 200 but it was 401
   At: ./spec/controllers/api/v1/players_controller_spec.rb:45

2) Player model validates presence of summoner_name
   Error: expected #<Player summoner_name: nil> to be valid
   At: ./spec/models/player_spec.rb:12

SUMMARY: 89 examples, 2 failures

Brakeman (antes: ~200 linhas JSON, depois: ~8 linhas)

BRAKEMAN: 3 warnings (H:1 M:1 L:1)

HIGH:
  app/controllers/players_controller.rb:45 [SQL Injection] Possible SQL injection
    code: Player.where("summoner_name LIKE '#{params[:search]}'")

MEDIUM:
  app/services/riot_sync_service.rb:12 [SSRF] Request to user-supplied URL

RuboCop (antes: ~500 linhas, depois: ~12 linhas)

RUBOCOP: 219 offenses em 145 files

TOP COPS:
  [C] Metrics/MethodLength: 34x  (app/services/riot_sync_service.rb:45, app/models/player.rb:120, ...)
  [C] Metrics/CyclomaticComplexity: 18x  (app/controllers/analytics/..., ...)
  [C] Layout/TrailingWhitespace: 15x  (app/controllers/..., ...)
  ...

05 · Dominios ProStaff

O session-start.js detecta o dominio ativo lendo git status --short do prostaff-api e mapeando os arquivos modificados:

╔═════════════╦══════════════════════════════════╦══════════════════════════════╗
║  DOMINIO    ║  DETECTADO POR                   ║  AGENT INDICADO              ║
╠═════════════╬══════════════════════════════════╬══════════════════════════════╣
║  ai         ║  modules/ai_intelligence/        ║  ai-intelligence-specialist  ║
║  auth       ║  modules/authentication/         ║  security-specialist         ║
║  analytics  ║  analytics/                      ║  rails-api-engineer          ║
║  scouting   ║  scouting/                       ║  rails-api-engineer          ║
║  matches    ║  matches/                        ║  rails-api-engineer          ║
║             ║                                  ║  lol-domain-expert           ║
║  players    ║  players/                        ║  rails-api-engineer          ║
║  infra      ║  docker-compose, Gemfile,        ║  devops-infra-specialist     ║
║             ║  .github/workflows/              ║                              ║
║  testing    ║  spec/                           ║  qa-specialist               ║
║  general    ║  (default)                       ║  rails-api-engineer          ║
╚═════════════╩══════════════════════════════════╩══════════════════════════════╝

Cada dominio injeta um contexto minimo (~5-8 linhas) em vez do CLAUDE.md completo (~300 linhas).


06 · Comandos /ps:

/ps:help              # lista todos os comandos
/ps:domain            # mostra o dominio detectado na sessao atual
/ps:domain <nome>     # forca um dominio manualmente (ex: /ps:domain ai)
/ps:check             # roda brakeman + rubocop com saida comprimida
/ps:full              # mostra como ver a saida bruta dos comandos

Para rodar os filtros manualmente (sem hooks ativos):

node /home/bullet/PROJETOS/prostaff-hooks/bin/ps-filter.js rspec    -- bundle exec rspec
node /home/bullet/PROJETOS/prostaff-hooks/bin/ps-filter.js brakeman -- brakeman
node /home/bullet/PROJETOS/prostaff-hooks/bin/ps-filter.js rubocop  -- bundle exec rubocop --format json

07 · Statusline

O statusline.sh le o arquivo flag ~/.claude/.ps-domain e exibe o badge do dominio ativo:

[PS:AI]  [PS:AUTH]  [PS:ANALYTICS]  [PS:SCOUTING]
[PS:MATCHES]  [PS:PLAYERS]  [PS:INFRA]  [PS:TEST]

Configurar em ~/.claude/settings.json:

{
  "statusCommand": "/home/bullet/PROJETOS/prostaff-hooks/statusline.sh"
}

08 · Estrutura do Projeto

prostaff-hooks/
├── PRD.md                        # Product Requirements Document
├── README.md
├── package.json                  # Sem dependencias externas
├── install.sh                    # Injeta hooks no prostaff-api/.claude/settings.json
├── statusline.sh                 # Badge [PS:DOMINIO] para statusline
│
├── hooks/
│   ├── pre-tool-use.js           # PreToolUse: reescreve comandos -> ps-filter
│   ├── session-start.js          # SessionStart: dominio + contexto minimo
│   └── hooks.json                # registro dos hooks no plugin
│
├── bin/
│   ├── ps-filter.js              # CLI: executa cmd original + aplica filtro
│   └── ps-domain.js              # CLI: le ou define o dominio da sessao
│
├── lib/
│   ├── domain-detector.js        # git status -> dominio (modulo isolado p/ testes)
│   ├── domain-store.js           # dominio da sessao em disco
│   ├── domains.js                # lista de dominios validos
│   ├── project.js                # raiz do projeto e versao do Rails pelo lockfile
│   ├── shell.js                  # quoting de caminho que vira linha de comando
│   └── filters/
│       ├── rspec.js              # Failures + summary
│       ├── brakeman.js           # HIGH/MEDIUM apenas (parse JSON)
│       ├── rubocop.js            # Agrupado por cop, top 10
│       ├── bundler_audit.js      # Advisories por gem
│       ├── docker.js             # Erros + ultimas 30 linhas significativas
│       ├── rails.js              # Migrations executadas + erros
│       └── outcome.js            # Veredito por exit code, nao por texto
│
└── skills/                       # Comandos /ps: do plugin
    ├── ps-help/SKILL.md          # /ps:help
    ├── ps-domain/SKILL.md        # /ps:domain
    ├── ps-check/SKILL.md         # /ps:check
    └── ps-full/SKILL.md          # /ps:full

09 · Referencia de Inspiracao

╔══════════════════╦═════════════════════════════════════════════════════════════╗
║  PROJETO         ║  CONTRIBUICAO PARA PROSTAFF-HOOKS                           ║
╠══════════════════╬═════════════════════════════════════════════════════════════╣
║  RTK             ║ Arquitetura PreToolUse rewrite - ps-filter.js segue o       ║
║  (Rust Token     ║ mesmo padrao: interceptar, executar real, comprimir,        ║
║   Killer)        ║ preservar exit code. 100+ comandos genericos → 6 especificos║
╠══════════════════╬═════════════════════════════════════════════════════════════╣
║  Caveman         ║  SessionStart hook para injecao de contexto. Flag file para ║
║                  ║  comunicar estado entre hooks (session-start → statusline). ║
║                  ║  O /ps: veio depois, e como skill de plugin.                ║
╚══════════════════╩═════════════════════════════════════════════════════════════╝

Diferenciais exclusivos do prostaff-hooks:

  • Filtros escritos para o formato exato de output do ProStaff (brakeman com -f json, rubocop --format json)
  • Domain detection mapeada para os 8 modulos do ProStaff API
  • Contexto de dominio inclui regras de segurança especificas (organization_scoped, SHA256, SSRF whitelist) e o agente Claude Code indicado para cada modulo
  • Project-scoped: zero interferencia em outros projetos
  • Nenhuma dependencia npm - startup < 20ms por invocacao

Projeto privado · ProStaff.gg · 2026

About

claude code hooks for ProStaff API

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages