claude-bulkhead 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.es.md +142 -50
  3. package/README.ja.md +142 -50
  4. package/README.ko.md +143 -51
  5. package/README.md +142 -50
  6. package/README.pt-BR.md +142 -50
  7. package/README.zh-CN.md +154 -62
  8. package/hooks/hooks.json +68 -8
  9. package/package.json +5 -2
  10. package/src/agent-hook.js +162 -0
  11. package/src/agent-setup.js +256 -0
  12. package/src/agents.js +89 -0
  13. package/src/allow-cli.js +65 -0
  14. package/src/allow-hint.js +62 -0
  15. package/src/allow-once.js +152 -0
  16. package/src/auto-queue.js +93 -0
  17. package/src/bash-guards.js +36 -0
  18. package/src/basics.js +46 -27
  19. package/src/checkout-guard.js +342 -74
  20. package/src/cli-util.js +13 -1
  21. package/src/cli.js +40 -4
  22. package/src/config-check.js +21 -4
  23. package/src/config-cli.js +75 -10
  24. package/src/config.js +106 -9
  25. package/src/dev-servers.js +361 -61
  26. package/src/disk-guard.js +8 -8
  27. package/src/doctor-enforcement.js +273 -0
  28. package/src/doctor.js +19 -9
  29. package/src/edit-guard.js +196 -0
  30. package/src/events.js +30 -5
  31. package/src/explain.js +251 -0
  32. package/src/git-info.js +55 -0
  33. package/src/gitargs.js +82 -0
  34. package/src/hook.js +38 -6
  35. package/src/kill-extras.js +219 -0
  36. package/src/kill-guard.js +228 -77
  37. package/src/kill-owners.js +116 -0
  38. package/src/log-cli.js +15 -10
  39. package/src/mcp.js +131 -0
  40. package/src/memory-guard.js +126 -24
  41. package/src/memory.js +21 -2
  42. package/src/notices.js +95 -0
  43. package/src/orphan-reaper.js +58 -11
  44. package/src/port-cli.js +78 -3
  45. package/src/port-guard.js +80 -68
  46. package/src/port-kills.js +198 -0
  47. package/src/pressure.js +75 -0
  48. package/src/processes.js +44 -12
  49. package/src/scan-report.js +166 -0
  50. package/src/scan.js +87 -18
  51. package/src/secrets-guard.js +301 -0
  52. package/src/self-allow.js +73 -0
  53. package/src/session-info.js +121 -0
  54. package/src/session-state.js +176 -0
  55. package/src/sessions.js +109 -20
  56. package/src/shell.js +279 -19
  57. package/src/slot-cli.js +92 -21
  58. package/src/slots.js +61 -13
  59. package/src/stable-port.js +61 -0
  60. package/src/status.js +55 -17
  61. package/src/statusline.js +45 -16
  62. package/src/subagent-guard.js +24 -0
  63. package/src/top.js +36 -11
  64. package/src/wait-guard.js +96 -32
  65. package/src/worktree-cli.js +454 -0
  66. package/src/worktree-copy.js +82 -0
package/README.pt-BR.md CHANGED
@@ -4,7 +4,9 @@
4
4
  <strong>Impede que o Claude Code rode <code>pkill node</code> nos seus outros servidores de desenvolvimento, tome as portas deles e faça commit das edições de outra sessão com <code>git add -A</code>.</strong>
5
5
  </p>
6
6
 
7
- <p align="center">Hooks que sabem quais processos, portas e árvores git pertencem a cada sessão e subagent do Claude Code, então bloqueiam só o que prejudicaria outra coisa e dizem ao Claude qual comando seguro rodar no lugar. Zero dependências, sem telemetria.</p>
7
+ <p align="center">Hooks que sabem quais processos, portas e árvores git pertencem a cada sessão e subagent do Claude Code, então bloqueiam só o que prejudicaria outra coisa e dizem ao Claude qual comando seguro rodar no lugar.</p>
8
+
9
+ <p align="center">Windows, macOS e Linux. Sem tmux, sem sudo, sem daemon em segundo plano, sem chamadas de rede, sem dependências. Também protege Codex, Gemini CLI, Copilot CLI, Cursor e mais seis agentes.</p>
8
10
 
9
11
  <p align="center">
10
12
  <a href="https://github.com/dooly6276/claude-bulkhead/actions/workflows/test.yml"><img src="https://github.com/dooly6276/claude-bulkhead/actions/workflows/test.yml/badge.svg" alt="testes"></a>
@@ -34,7 +36,14 @@ Depois, veja o que ele teria bloqueado no seu último mês, sem mudar nada:
34
36
  /bulkhead:scan 30d
35
37
  ```
36
38
 
37
- O Node 18 ou mais recente precisa estar no `PATH` (o instalador nativo do Claude Code não o instala; confira com `node --version`). Para os comandos de terminal e a status line, rode também `npm install -g claude-bulkhead`, ou use `npx claude-bulkhead status` sem instalar.
39
+ O Node 18 ou mais recente precisa estar no `PATH` (o instalador nativo do Claude Code não o instala; confira com `node --version`).
40
+
41
+ | Instalação | O que você recebe |
42
+ |---|---|
43
+ | O plugin (acima) | Os guards, que rodam em toda chamada de Bash, PowerShell, Read e Edit; os slash commands `/bulkhead:scan`, `status`, `log`, `doctor`, `reap`, `remote`; a skill que ensina ao Claude os hábitos seguros. Essa é a parte que protege você. |
44
+ | `npm install -g claude-bulkhead` (opcional) | O comando `bulkhead` no seu próprio terminal (`status`, `top`, `explain`, `allow`, `worktree`, `scan`, `doctor`), a status line, o `bulkhead-slot` e o `bulkhead setup <agent>` para Codex, Gemini e os outros. O `npx claude-bulkhead status` funciona sem instalar. |
45
+
46
+ Não tem certeza de que está funcionando? O `bulkhead doctor` roda um comando inofensivo por cada guard e mostra que ele foi bloqueado, e quanto tempo levou.
38
47
 
39
48
  ## O que ele bloqueia
40
49
 
@@ -42,7 +51,7 @@ O Node 18 ou mais recente precisa estar no `PATH` (o instalador nativo do Claude
42
51
  |---|---|
43
52
  | Um agente reinicia o próprio dev server com `pkill node`, e o servidor de todos os outros worktrees morre junto. | O kill-guard bloqueia o comando e ensina o agente a achar e encerrar o próprio PID. |
44
53
  | Duas sessões compartilham um checkout. Uma roda `git add -A && git commit`, e as edições pela metade da outra vão parar nesse commit. | O checkout-guard bloqueia e pede os nomes dos arquivos. |
45
- | Dois worktrees rodam `npm run dev`. O segundo passa para a 3001, mas o agente dele continua testando `localhost:3000` e vê a outra branch. | O port-guard bloqueia a segunda inicialização e indica uma porta livre. O `bulkhead port` imprime uma sob demanda. |
54
+ | Dois worktrees rodam `npm run dev`. O segundo passa para a 3001, mas o agente dele continua testando `localhost:3000` e vê a outra branch. | O port-guard bloqueia a segunda inicialização e indica uma porta livre. |
46
55
  | Três sessões iniciam `next build`, `npm test` e Playwright no mesmo minuto, e a máquina trava. | O memory-guard bloqueia comandos pesados quando a RAM está baixa. Pelo `bulkhead-slot`, o terceiro job espera na fila até haver espaço. |
47
56
 
48
57
  <details>
@@ -87,7 +96,7 @@ Você não precisa adivinhar. O Claude Code guarda a transcrição de cada sess
87
96
  /bulkhead:scan 30d
88
97
  ```
89
98
 
90
- Ele só lê, mascara qualquer coisa que pareça um segredo antes de imprimir e não envia nada para lugar nenhum. O port-guard e a verificação de pouca RAM não são reproduzidos, porque as transcrições não registram quais portas e quanta RAM estavam em uso; o checkout-guard é reconstruído a partir de quais sessões estavam ativas na mesma árvore git naquele minuto. Detalhes: [docs/commands.md](docs/commands.md#bulkhead-scan).
99
+ Ele só lê, mascara qualquer coisa que pareça um segredo antes de imprimir e não envia nada para lugar nenhum. O port-guard e a verificação de pouca RAM não são reproduzidos, porque as transcrições não registram quais portas e quanta RAM estavam em uso; o checkout-guard é reconstruído a partir de quais sessões estavam ativas na mesma árvore git naquele minuto. O `bulkhead scan --share` imprime um resumo de 5 a 8 linhas só com contagens (sem caminhos, sem comandos) que você pode colar em um post ou em um chat, e o `--explain 1` mostra um exemplo completo, com o trecho que casou. Detalhes: [docs/commands.md](docs/commands.md#bulkhead-scan).
91
100
 
92
101
  ## Por que isso existe
93
102
 
@@ -115,10 +124,13 @@ O claude-bulkhead é um conjunto de hooks pequenos que bloqueiam ou limpam cada
115
124
  |---|---|
116
125
  | **[kill-guard](docs/guards/kill-guard.md)**<br>Bloqueia `pkill node`, `taskkill /IM`, `Stop-Process -Name` e outros kills por nome de programa. Kills por PID passam. | **[port-guard](docs/guards/port-guard.md)**<br>Bloqueia iniciar um dev server em uma porta que outra sessão já usa, e matar por porta o servidor dessa sessão. |
117
126
  | **[memory-guard e bulkhead-slot](docs/guards/memory-guard.md)**<br>Bloqueia comandos pesados quando a RAM está baixa e enfileira jobs pesados contra um orçamento de RAM compartilhado por todas as sessões. | **[checkout-guard](docs/guards/checkout-guard.md)**<br>Bloqueia `git checkout`, `stash`, `reset --hard`, `git add -A` e similares quando outra sessão ativa trabalha na mesma árvore, e a exclusão de uma pasta onde outra sessão trabalha. |
118
- | **[wait-guard](docs/guards/wait-guard.md)**<br>Bloqueia loops de sleep em primeiro plano com mais de 3 minutos, que fazem a próxima requisição reescrever todo o prompt cache. | **[orphan-reaper](docs/guards/orphan-reaper.md)**<br>Quando uma sessão termina, encerra os dev servers, test workers, watchers e navegadores headless que ela deixou rodando. |
119
- | **[disk-guard](docs/guards/disk-guard.md)** <sup>novo</sup><br>Bloqueia `du -sh ~`, `find /` sem `-maxdepth` e varreduras de disco em paralelo, que travam o disco que todas as sessões compartilham. | **[`bulkhead scan`](#você-precisa-disso-pergunte-às-suas-transcrições)** <sup>novo</sup><br>Reproduz suas transcrições passadas do Claude Code contra os guards: o que eles teriam bloqueado e quantas sessões rodaram ao mesmo tempo. |
127
+ | **[wait-guard](docs/guards/wait-guard.md)**<br>Bloqueia loops de sleep em primeiro plano com mais de 3 minutos, que fazem a próxima requisição reescrever todo o prompt cache. | **[orphan-reaper](docs/guards/orphan-reaper.md)**<br>Quando uma sessão termina, encerra os dev servers, test workers, watchers e navegadores headless que ela deixou rodando. Mantenha um de propósito com `BULKHEAD_KEEP=1`; túneis e bancos de dados já são mantidos. |
128
+ | **[disk-guard](docs/guards/disk-guard.md)**<br>Bloqueia `du -sh ~`, `find /` sem `-maxdepth` e varreduras de disco em paralelo, que travam o disco que todas as sessões compartilham. | **[`bulkhead scan`](#você-precisa-disso-pergunte-às-suas-transcrições)**<br>Reproduz suas transcrições passadas do Claude Code contra os guards: o que eles teriam bloqueado e quantas sessões rodaram ao mesmo tempo. |
120
129
  | **[basics](docs/guards/basics.md)**<br>Bloqueia `rm -rf` na raiz, na home ou em uma pasta diretamente dentro dela, force-push na `main`, resets que perderiam trabalho não commitado e commits com Claude como autor. | **[`bulkhead status`, `top`, `log`, `doctor`](#veja-o-que-está-rodando)**<br>Mostra cada sessão, sua RAM, suas portas, os jobs na fila e o que os guards bloquearam. |
121
- | **[Status line](#status-line)**<br>`3 sessions 2 heavy 9.1 GB free` na status line do Claude Code, em menos de 100 ms. | **[Configuração e slash commands](#configuração)**<br>Configuração por máquina e por projeto com listas de permissão, além de `/bulkhead:scan`, `/bulkhead:status`, `/bulkhead:log`, `/bulkhead:doctor` e `/bulkhead:reap`. |
130
+ | **[edit-guard](docs/guards/edit-guard.md)** <sup>novo</sup><br>Avisa o agente quando outra sessão ativa editou o mesmo arquivo nos últimos 30 minutos, nesta árvore ou em outro worktree do repositório. Apenas consultivo por padrão, sem servidor. | **[secrets-guard](docs/guards/secrets-guard.md)** <sup>novo, desativado por padrão</sup><br>Bloqueia a leitura ou a impressão de `.env`, chaves privadas, credenciais de nuvem e de todo o ambiente, pela ferramenta Read ou por um comando de shell, enquanto `.env.example`, `ls ~/.ssh` e arquivos `.pub` passam. |
131
+ | **[`bulkhead explain` e `bulkhead allow`](#quando-ele-bloqueia-algo-que-você-queria)** <sup>novo</sup><br>Veja o que cada guard diria sobre um comando antes de ele rodar e libere uma única vez um comando bloqueado com o código da mensagem de bloqueio. O Claude não consegue aprovar os próprios bloqueios. | **[`bulkhead worktree`](#worktrees-em-um-passo)** <sup>novo</sup><br>Um worktree novo em um passo, com seus arquivos `.env` copiados, as dependências instaladas e uma porta estável própria; o `prune` remove os já mesclados, inclusive por squash merge, e nunca um em que uma sessão esteja trabalhando. |
132
+ | **[Auto-queue](docs/commands.md#auto-queue)** <sup>novo</sup><br>Com `memoryGuard.autoQueue`, os comandos pesados não são recusados, mas postos na fila: o hook os envolve no `bulkhead-slot`, e eles começam quando há espaço. | **[Codex, Gemini e outros agentes](#codex-gemini-e-outros-agentes)** <sup>novo</sup><br>Os mesmos guards para Codex, Gemini CLI, Copilot CLI, Cursor, Windsurf, Droid, Devin, Cline, opencode e Amp, configurados com `bulkhead setup <agent>`. |
133
+ | **[Status line](#status-line)**<br>`3 sessions 2 heavy 9.1 GB free` na status line do Claude Code, em cerca de 100 ms. | **[Configuração e slash commands](#configuração)**<br>Configuração por máquina e por projeto com listas de permissão, além de `/bulkhead:scan`, `/bulkhead:status`, `/bulkhead:log`, `/bulkhead:doctor` e `/bulkhead:reap`. |
122
134
 
123
135
  Opcional: o **[`bulkhead remote`](#rode-tarefas-pesadas-em-outra-máquina-opcional)** roda uma suíte de testes, um build ou uma execução de navegador em outra máquina via SSH, quando esta não tem RAM sobrando.
124
136
 
@@ -132,14 +144,29 @@ Uma execução roteirizada de `bulkhead status`, port-guard, kill-guard e wait-g
132
144
 
133
145
  1. Instale o plugin como acima e inicie uma nova sessão do Claude Code.
134
146
  2. Veja o que ele teria pegado: rode `/bulkhead:scan 30d`, ou `bulkhead scan` na ferramenta Bash. Ele lê o último mês de transcrições e não altera nada.
135
- 3. Verifique a instalação. Dentro do Claude Code, rode `/bulkhead:doctor`, ou rode `bulkhead doctor` na ferramenta Bash. Todas as linhas devem dizer `OK`. Uma linha `WARN` ou `FAIL` informa o guard e o motivo.
147
+ 3. Verifique a instalação. Dentro do Claude Code, rode `/bulkhead:doctor`, ou rode `bulkhead doctor` na ferramenta Bash. Todas as linhas devem dizer `OK`. Uma linha `WARN` ou `FAIL` informa o guard e o motivo. A seção Enforcement no final prova que os hooks bloqueiam: ela executa o hook instalado com um comando de teste (canary) e confere o código de saída, a mensagem e a latência, e avisa sobre `disableAllHooks`, um plugin desativado ou a falta do `node`.
136
148
  4. Abra um terminal ao lado das suas sessões e rode `npx claude-bulkhead top` (ou `bulkhead top` depois de `npm install -g claude-bulkhead`) para acompanhar ao vivo sessões, RAM, portas e jobs pesados. Pressione `q` para sair.
137
149
 
138
150
  Depois disso não há mais nada a fazer. Os guards rodam em toda chamada de Bash e PowerShell. Para ver o que eles bloquearam, rode `bulkhead log` ou `/bulkhead:log`; `bulkhead log --summary` conta os bloqueios por guard na sua máquina. Para mudar um limite ou liberar um comando, veja [docs/configuration.md](docs/configuration.md). Todos os comandos estão listados em [docs/commands.md](docs/commands.md).
139
151
 
152
+ ## Worktrees em um passo
153
+
154
+ Quando outra sessão trabalha na sua árvore, o checkout-guard manda o agente para um worktree. Um worktree comum não tem `.env`, não tem `node_modules` e usa a mesma porta de dev server do checkout principal. O `bulkhead worktree add` resolve esses três pontos:
155
+
156
+ ```
157
+ $ bulkhead worktree add fix-login
158
+ created ~/dev/shop-fix-login on new branch fix-login from HEAD
159
+ copied .env (default set)
160
+ pnpm install --frozen-lockfile: done in 14.2s
161
+ wrote PORT=3800 to .env.local
162
+ next: cd ~/dev/shop-fix-login && claude
163
+ ```
164
+
165
+ Ele copia os arquivos indicados no `.worktreeinclude` (o arquivo que o Claude Code também lê) ou um conjunto padrão e seguro de arquivos `.env`, nunca `node_modules`, saída de build nem nada acima de 5 MB; instala com o lockfile do projeto; e dá ao worktree uma porta que é sempre a mesma. O `bulkhead worktree list` mostra cada worktree com sua branch, estado, sessão ativa e porta. O `bulkhead worktree prune` lista os que já foram mesclados, estão limpos e sem uso, e os remove com `--yes` usando `git worktree remove` e `git branch -d`, nunca com `--force`, nunca a pasta de uma sessão ativa. Detalhes em [docs/commands.md](docs/commands.md#bulkhead-worktree).
166
+
140
167
  ## Rode tarefas pesadas em outra máquina (opcional)
141
168
 
142
- Quando várias sessões rodam suítes de testes e builds ao mesmo tempo, uma máquina fica sem RAM: o memory-guard bloqueia os comandos, ou o bulkhead-slot os coloca na fila. Se você tem uma segunda máquina quase sempre ociosa, o `bulkhead remote` roda o comando pesado nela.
169
+ Quando várias sessões rodam suítes de testes e builds ao mesmo tempo, uma máquina fica sem RAM: o memory-guard bloqueia os comandos, ou o bulkhead-slot os coloca na fila (automaticamente, com `memoryGuard.autoQueue`). Se você tem uma segunda máquina quase sempre ociosa, o `bulkhead remote` roda o comando pesado nela.
143
170
 
144
171
  <p align="center">
145
172
  <img src="docs/remote.svg" alt="Esta máquina tem 1,8 GB livres, então o memory-guard segura o npm test. O bulkhead remote envia por SSH para o buildbox apenas o novo commit e os arquivos alterados, os testes rodam lá na cópia a, na porta 7172, e as últimas 20 linhas voltam. A RAM livre desta máquina não muda." width="100%">
@@ -209,12 +236,14 @@ Para desativar: `BULKHEAD_DISABLE=port-guard`. Detalhes: [docs/guards/port-guard
209
236
  O memory-guard bloqueia comandos pesados (test runners, `next build`, `tsc`, Gradle, o emulador Android, Playwright, `cargo test`, `docker build` e similares) quando a RAM livre está abaixo de 3 GB, ou abaixo de 15% da RAM em máquinas com menos de 20 GB. O `bulkhead-slot run --gb=4 -- <command>` espera até o orçamento de RAM compartilhado ter espaço, roda o comando e libera o slot quando ele termina.
210
237
 
211
238
  Para desativar: `BULKHEAD_DISABLE=memory-guard`. Detalhes: [docs/guards/memory-guard.md](docs/guards/memory-guard.md).
239
+
240
+ Com `"memoryGuard": { "autoQueue": true }`, ninguém precisa se lembrar do slot: o memory-guard reescreve todo comando pesado (testes, builds, execuções de navegador, builds de contêiner) para rodar pelo `bulkhead-slot`, e assim todas as sessões esperam em uma única fila justa em vez de serem bloqueadas. Um job em espera imprime sua posição a cada 30 segundos, e o `bulkhead status` mostra a que sessão e a que projeto cada job da fila pertence. Com `"memoryGuard": { "subagents": true }`, um novo subagent não é iniciado enquanto a pressão de memória estiver crítica. Veja [docs/commands.md](docs/commands.md#auto-queue).
212
241
  </details>
213
242
 
214
243
  <details>
215
244
  <summary><strong>checkout-guard</strong>: duas sessões na mesma árvore git</summary>
216
245
 
217
- Bloqueia `git checkout <branch>`, `switch`, `stash`, `reset --hard`, `clean -f`, `rebase`, `merge`, `restore .` e um `pull` com alterações pendentes quando outra sessão ativa trabalha na mesma árvore, e sugere `git worktree add`. Também bloqueia ali `git add -A`, `git add .` e `git commit -a` (`stage-all`), que levariam as edições pela metade da outra sessão para o seu commit, e `rm -rf` ou `git worktree remove` em uma pasta onde outra sessão ativa trabalha (`remove-session-dir`). No Windows, bloqueia `git worktree remove --force` em um worktree que contém junctions, que o git já seguiu até o checkout principal.
246
+ Bloqueia `git checkout <branch>`, `switch`, `stash`, `reset --hard`, `clean -f`, `rebase`, `merge`, `restore .` e um `pull` com alterações pendentes quando outra sessão ativa trabalha na mesma árvore, e sugere `git worktree add`. Também bloqueia ali `git add -A`, `git add .` e `git commit -a` (`stage-all`; `git add -A src/` e `git add -n` passam), que levariam as edições pela metade da outra sessão para o seu commit, e `rm -rf` ou `git worktree remove` em uma pasta onde outra sessão ativa trabalha (`remove-session-dir`). No Windows, bloqueia `git worktree remove --force` em um worktree que contém junctions, que o git já seguiu até o checkout principal.
218
247
 
219
248
  Para desativar: `BULKHEAD_DISABLE=checkout-guard`, ou uma regra só com `BULKHEAD_DISABLE=stage-all` ou `remove-session-dir`. Detalhes: [docs/guards/checkout-guard.md](docs/guards/checkout-guard.md).
220
249
  </details>
@@ -238,19 +267,30 @@ Para desativar: `BULKHEAD_DISABLE=wait-guard`, ou aumente o limite com `BULKHEAD
238
267
  <details>
239
268
  <summary><strong>orphan-reaper</strong>: processos deixados por sessões que terminaram</summary>
240
269
 
241
- Quando uma sessão termina, um waiter oculto em segundo plano encerra o que ela iniciou nos shells das ferramentas e deixou rodando: dev servers e qualquer outra coisa escutando em uma porta, test runners e seus workers (Vitest, Jest, Playwright, pytest e xdist, `cargo test`, `go test` e outros), watchers como `tsc --watch` e nodemon, builds como `next build` e navegadores headless. Uma varredura no início da sessão pega o que um crash deixou para trás. Editores, terminais, daemons compartilhados como Gradle ou adb e qualquer coisa que você mesmo iniciou nunca são tocados. O `bulkhead reap --dry-run` mostra o que ele encerraria e por quê. Windows, Linux e macOS (macOS testado com fixtures).
270
+ Quando uma sessão termina, um waiter oculto em segundo plano encerra o que ela iniciou nos shells das ferramentas e deixou rodando: dev servers e qualquer outra coisa escutando em uma porta, test runners e seus workers (Vitest, Jest, Playwright, pytest e xdist, `cargo test`, `go test` e outros), watchers como `tsc --watch` e nodemon, builds como `next build` e navegadores headless. Uma varredura no início da sessão pega o que um crash deixou para trás. Editores, terminais, daemons compartilhados como Gradle ou adb e qualquer coisa que você mesmo iniciou nunca são tocados. O `bulkhead reap --dry-run` mostra o que ele encerraria e por quê. O que você iniciou de propósito para continuar no ar é mantido com `BULKHEAD_KEEP=1 <command>` (túneis ssh, cloudflared, ngrok, Jupyter, Redis, Postgres, MySQL, MongoDB e Docker são mantidos sem isso), e a sessão seguinte informa em uma linha o que foi encerrado. Windows, Linux e macOS (macOS testado em um Mac de verdade).
242
271
 
243
272
  Para desativar: `BULKHEAD_DISABLE=orphan-reaper`. Detalhes: [docs/guards/orphan-reaper.md](docs/guards/orphan-reaper.md).
244
273
  </details>
245
274
 
246
275
  <details>
247
- <summary><strong>basics</strong>: quatro erros que não têm volta</summary>
276
+ <summary><strong>basics</strong>: cinco erros que não têm volta</summary>
248
277
 
249
- `rm-root` (`rm -rf` na raiz, em uma pasta de nível superior como `/srv`, na home, em uma pasta diretamente dentro da home como `~/Documents`, ou acima do repositório), `force-push-main` (`git push --force` para `main` ou `master`; `--force-with-lease` passa), `discard-changes` (`git reset --hard` ou `git clean -fd` que perderiam trabalho não commitado) e `agent-author` (`--author="Claude <noreply@anthropic.com>"`, `git config user.name Claude` e similares, para que seus commits continuem contando como seus).
278
+ `rm-root` (`rm -rf` na raiz, em uma pasta de nível superior como `/srv`, na home, em uma pasta diretamente dentro da home como `~/Documents`, ou acima do repositório), `force-push-main` (`git push --force` para `main` ou `master`; `--force-with-lease` passa), `protected-delete` (`git push origin :main`, `git push --delete origin main`, `git branch -D main`), `discard-changes` (`git reset --hard` ou `git clean -fd` que perderiam trabalho não commitado) e `agent-author` (`--author="Claude <noreply@anthropic.com>"`, `git config user.name Claude` e similares, para que seus commits continuem contando como seus).
250
279
 
251
280
  Para desativar: `BULKHEAD_DISABLE=basics`, ou uma regra pelo nome. Detalhes: [docs/guards/basics.md](docs/guards/basics.md).
252
281
  </details>
253
282
 
283
+ ## Codex, Gemini e outros agentes
284
+
285
+ Se você roda Codex CLI, Gemini CLI, Copilot CLI, Cursor, opencode, Amp, Cline, Factory Droid, Windsurf ou Devin na mesma máquina que o Claude Code, o bulkhead protege os comandos de shell deles com os mesmos guards e conta as sessões deles: o dev server de um agente fica protegido dos demais, e o `bulkhead status` ganha uma coluna `AGENT`.
286
+
287
+ ```
288
+ bulkhead setup codex # prints the config for ~/.codex/hooks.json
289
+ bulkhead setup codex --write # merges it (original saved as hooks.json.bulkhead-backup)
290
+ ```
291
+
292
+ O `bulkhead setup <agent>` funciona para `codex`, `gemini`, `copilot`, `cursor`, `windsurf`, `droid`, `devin`, `cline`, `opencode` e `amp`. Cada agente chama `bulkhead hook --agent <name>` antes de um comando de shell e recebe de volta o bloqueio no seu próprio formato. Os agentes, os arquivos de configuração, o que é protegido e a documentação com a qual cada linha foi conferida estão em [docs/other-agents.md](docs/other-agents.md).
293
+
254
294
  ## Como o bulkhead se relaciona com outros pacotes de hooks
255
295
 
256
296
  Pacotes gerais de segurança protegem uma sessão de comandos perigosos. Por exemplo, o [claude-forge](https://github.com/sangrokjung/claude-forge) inclui hooks que filtram segredos vazados na saída, bloqueiam scripts remotos passados por pipe e impedem SQL destrutivo, e o [dcg](https://github.com/Dicklesworthstone/destructive_command_guard) e o [cc-safety-net](https://github.com/kenryu42/claude-code-safety-net) cobrem de forma ampla comandos destrutivos de shell e git. Vale a pena usá-los.
@@ -283,7 +323,8 @@ As variáveis de ambiente continuam funcionando e vencem os dois arquivos. O lug
283
323
 
284
324
  | Variável | Padrão | Equivale a |
285
325
  |---|---|---|
286
- | `BULKHEAD_DISABLE` | vazio | Guards a desativar, separados por vírgula: `kill-guard`, `wait-guard`, `memory-guard`, `port-guard`, `checkout-guard`, `disk-guard`, `orphan-reaper`, `basics`, ou `all`. Regras individuais também podem ser desativadas: `rm-root`, `force-push-main`, `discard-changes`, `agent-author`, `stage-all`, `remove-session-dir`. Um nome aqui fica desativado, diga o que disser os arquivos |
326
+ | `BULKHEAD_DISABLE` | vazio | Guards a desativar, separados por vírgula: `kill-guard`, `wait-guard`, `memory-guard`, `port-guard`, `checkout-guard`, `disk-guard`, `orphan-reaper`, `basics`, ou `all`. Regras individuais também podem ser desativadas: `rm-root`, `force-push-main`, `protected-delete`, `discard-changes`, `agent-author`, `stage-all`, `remove-session-dir`. Um nome aqui fica desativado, diga o que disser os arquivos |
327
+ | `BULKHEAD_PRESET` | `normal` | O preset: `quiet`, `normal` ou `strict` |
287
328
  | `BULKHEAD_WAIT_MAX_SEC` | 180 | `waitGuard.limitSeconds` |
288
329
  | `BULKHEAD_MIN_FREE_GB` | 3, ou 15% da RAM se for menos | `memory.minFreeGb` |
289
330
  | `BULKHEAD_SLOT_FLOOR_GB` | 5, ou 25% da RAM se for menos | `memory.slotFloorGb` |
@@ -294,32 +335,68 @@ As variáveis de ambiente continuam funcionando e vencem os dois arquivos. O lug
294
335
 
295
336
  </details>
296
337
 
338
+ ## Quando ele bloqueia algo que você queria
339
+
340
+ Um bloqueio é uma pergunta, não um veredito. Há três saídas, da menor para a maior:
341
+
342
+ 1. Libere uma única vez. Toda mensagem de bloqueio termina com um código curto. No seu próprio terminal, rode `bulkhead allow 7F3K`. A próxima chamada idêntica do agente (mesmo comando, mesma pasta) passa, uma vez, em até 10 minutos. O agente não consegue fazer isso por você: o bulkhead bloqueia qualquer tentativa de rodar `bulkhead allow` ou de gravar nos arquivos de estado dele.
343
+ 2. Veja o motivo primeiro. O `bulkhead explain -- <command>` passa o comando por todos os guards, contra as sessões, portas e árvore git ativas, sem executá-lo, e imprime quem é dono do que está no caminho, a mensagem exata que o agente vê e como liberá-lo.
344
+ 3. Libere de vez, ou mude o quanto ele bloqueia. Coloque a regra no `.claude/bulkhead.json` (a tabela abaixo) ou escolha um preset: `bulkhead config --preset quiet` mantém só os guards entre sessões e as duas regras que não têm volta, `strict` liga tudo com limites mais apertados, e `normal` é o padrão. Suas próprias chaves e variáveis de ambiente vencem um preset.
345
+
346
+ ### Bloqueou algo que você queria? Guia rápido
347
+
348
+ A forma de liberar uma única vez é sempre `bulkhead allow <code>`, rodado por você. A forma permanente, para a regra que disparou:
349
+
350
+ | Guard | Regra | Permanente, em `.claude/bulkhead.json` |
351
+ |---|---|---|
352
+ | kill-guard | `pkill`, `taskkill-im`, `stop-process-name` e os outros kills por nome | `{"killGuard":{"allowNames":["ffmpeg"]}}` |
353
+ | kill-guard | `other-session-pid`: um PID da árvore de outra sessão | `{"killGuard":{"ownerCheck":false}}` |
354
+ | kill-guard | `mass-kill`, `docker-mass`, `device-kill`, `app-quit`, `service-stop`: as outras regras (só enquanto outra sessão roda) | `{"killGuard":{"massKill":false}}`, e assim por diante (`dockerMass`, `deviceKill`, `appQuit`, `serviceStop`) |
355
+ | wait-guard | `long-sleep`, `poll-loop`, `follow` | `{"waitGuard":{"limitSeconds":600}}` |
356
+ | memory-guard | `low-memory` | `{"memory":{"minFreeGb":1}}` |
357
+ | memory-guard | `slot-files` | `{"memoryGuard":{"enabled":false}}` |
358
+ | port-guard | `port-in-use`, `kill-by-port` | `{"portGuard":{"ignorePorts":[3000]}}` |
359
+ | checkout-guard | `stage-all` | `{"checkoutGuard":{"stageAll":false}}` |
360
+ | checkout-guard | `remove-session-dir` | `{"checkoutGuard":{"removeSessionDir":false}}` |
361
+ | checkout-guard | `git-checkout`, `git-pull` e as outras mudanças na árvore | `{"checkoutGuard":{"enabled":false}}` |
362
+ | disk-guard | `disk-wide-find`, `parallel-disk-scan`, `disk-wide-scan` | `{"diskGuard":{"enabled":false}}` |
363
+ | basics | `rm-root` | `{"basics":{"rmRoot":false}}` |
364
+ | basics | `force-push-main` | `{"basics":{"forcePushMain":false}}` |
365
+ | basics | `discard-changes` | `{"basics":{"discardChanges":false}}` |
366
+ | basics | `agent-author` | `{"basics":{"agentAuthor":false}}` |
367
+ | basics | `self-allow` | não pode ser liberada uma única vez; só você pode aprovar |
368
+
369
+ O mesmo interruptor como variável de ambiente é `BULKHEAD_DISABLE=<nome do guard ou da regra>`. Tudo está em [docs/configuration.md](docs/configuration.md) e [docs/commands.md](docs/commands.md).
370
+
297
371
  ## Veja o que está rodando
298
372
 
299
373
  O `bulkhead` está no `PATH` da ferramenta Bash, ao lado do `bulkhead-slot`. Dentro do Claude Code, `/bulkhead:scan [30d]`, `/bulkhead:status`, `/bulkhead:log [24h|7d]`, `/bulkhead:doctor` e `/bulkhead:reap` rodam o comando correspondente e resumem o resultado. No seu próprio terminal, rode `npx claude-bulkhead top`, ou instale uma vez com `npm install -g claude-bulkhead` e rode `bulkhead top`. O pacote npm é o mesmo código do plugin. Todo comando que imprime uma tabela aceita `--json`. A referência completa está em [docs/commands.md](docs/commands.md).
300
374
 
301
375
  ### bulkhead status
302
376
 
303
- Todas as sessões do Claude Code na máquina, a memória que a árvore de processos de cada uma usa, o que ela mantém escutando em uma porta, os jobs retidos no bulkhead-slot e os que estão esperando, e a RAM livre:
377
+ Todas as sessões do Claude Code na máquina: o que cada uma está fazendo (trabalhando, esperando você, precisando de permissão), sua branch git e se ela é um worktree, a memória que a árvore de processos usa, o que ela mantém escutando em uma porta, os jobs retidos no bulkhead-slot e os que estão esperando, a RAM livre e os servidores MCP que rodam em várias cópias entre as sessões:
304
378
 
305
379
  ```
306
380
  $ bulkhead status
307
- SESSION STARTED RSS PROJECT
308
- 18672 Oct 12 17:49 1.4 GB ~/src/acme-web
309
- :3000 node.exe pid 24632
310
- 21888 Oct 12 17:52 353 MB ~/src/acme-web-auth
311
- 26448 03:43 625 MB ~/src/acme-web-checkout
312
- :3001 node.exe pid 31020
381
+ SESSION STATE STARTED RSS BRANCH PROJECT
382
+ 18672 working 09:52 1.4 GB main ~/src/acme-web
383
+ :3000 node pid 24632
384
+ 21888 needs permission 4m 10:05 353 MB feat/login (wt) ~/src/acme-web-auth
385
+ 26448 waiting 3m 11:40 625 MB feat/checkout (wt) ~/src/acme-web-checkout
386
+ :3001 node pid 31020
387
+ duplicate MCP: 3 copies of @playwright/mcp, 1.2 GB (sessions 18672, 21888, 26448)
313
388
 
314
- SLOT GB PID AGE COMMAND
315
- slot-1 4 30112 6 min npx playwright test
389
+ SLOT GB PID AGE SESSION PROJECT COMMAND
390
+ slot-1 4 30112 6 min 18672 ~/src/acme-web npx playwright test
316
391
 
317
- WAITING GB PID FOR COMMAND
318
- #1 3 30200 2 min npm run build
392
+ WAITING GB PID FOR SESSION PROJECT COMMAND
393
+ #1 3 30200 2 min 26448 ~/src/acme-web-checkout npm run build
319
394
 
320
395
  9.9 GB free of 31.8 GB, commit 68%
321
396
  ```
322
397
 
398
+ O `bulkhead top` coloca primeiro as sessões que precisam de você. O `bulkhead port --stable` imprime uma porta que pertence ao worktree git atual e é sempre a mesma. Para receber uma notificação de desktop quando uma sessão começar a esperar, defina `notify.command` ([commands.md](docs/commands.md#session-state-and-notifications)).
399
+
323
400
  `bulkhead slot ...` é o mesmo que `bulkhead-slot ...`.
324
401
 
325
402
  ### bulkhead top
@@ -374,31 +451,44 @@ PROJECT COUNT
374
451
 
375
452
  ### bulkhead doctor
376
453
 
377
- Verifica o Node, os arquivos do plugin, o diretório de estado, os arquivos de configuração, cada guard (ativo ou desativado, e por quê), uma execução real de hook, o leitor de processos com seu tempo, os arquivos de sessão, os limites de RAM calculados para esta máquina, os slots retidos, o log de eventos e o git. O código de saída é 1 quando qualquer verificação falha.
454
+ Verifica o Node, os arquivos do plugin, o diretório de estado, os arquivos de configuração, cada guard (ativo ou desativado, e por quê), o leitor de processos com seu tempo, os arquivos de sessão, os limites de RAM calculados para esta máquina, os slots retidos, o log de eventos e o git. Depois, uma seção Enforcement prova que os hooks instalados bloqueiam: a instalação e o `enabledPlugins`, instalações duplicadas, configurações que desligam hooks, o `node` no `PATH` dos hooks e uma execução real do comando de hook de cada guard contra um comando de teste (canary), com sua latência. O código de saída é 1 quando qualquer verificação falha.
378
455
 
379
456
  ```
380
457
  $ bulkhead doctor
381
- OK node v24.11.0
382
- OK plugin ~/.claude/plugins/cache/bulkhead/bulkhead/0.2.2, hooks: 2 SessionStart, 1 SessionEnd, 7 PreToolUse
383
- OK state dir ~/.claude/bulkhead is writable
384
- OK config no config files, defaults in use
385
- OK kill-guard on
386
- OK wait-guard on, limit 180s
387
- OK memory-guard on
388
- OK port-guard on
389
- OK checkout-guard on
390
- OK disk-guard on
391
- OK basics on, protected branches: main, master
392
- OK orphan-reaper on, at session start and after each session ends
393
- OK hook run kill-guard blocked a test command in 90 ms
394
- OK processes 356 processes, 21 listening ports, 8 Claude sessions in 2.4s
395
- OK sessions ~/.claude/sessions (8 session files)
396
- OK memory 12.2 of 31.8 GB free, commit 43%, memory-guard blocks heavy commands below 3 GB, bulkhead-slot keeps 5 GB free for a second job, and waits while commit is above 75%
397
- OK slots none held
398
- OK event log ~/.claude/bulkhead/events.jsonl, empty so far
399
- OK git 2.52.0.windows.1
400
-
401
- 19 OK, 0 WARN, 0 FAIL
458
+ OK node v24.22.1
459
+ OK package this copy ~/.claude/plugins/cache/bulkhead/bulkhead/0.3.0, hooks: 3 SessionStart, 2 SessionEnd, 1 UserPromptSubmit, 1 Stop, 1 Notification, 2 PostToolUse, 1 PostToolUseFailure, 4 PreToolUse
460
+ OK state dir ~/.claude/bulkhead is writable
461
+ OK config no config files, defaults in use
462
+ OK preset normal (default)
463
+ OK kill-guard on
464
+ OK wait-guard on, limit 180s
465
+ OK memory-guard on
466
+ OK port-guard on
467
+ OK checkout-guard on
468
+ OK disk-guard on
469
+ OK basics on, protected branches: main, master
470
+ OK edit-guard on
471
+ OK secrets-guard off (default)
472
+ OK orphan-reaper on, at session start and after each session ends
473
+ OK session-state on
474
+ OK processes 589 processes, 11 listening ports, 10 Claude sessions (10 with a session file) in 0.2s
475
+ OK sessions ~/.claude/sessions (10 session files; a running session without one is still found from the process list, but checkout-guard cannot tell which folder it works in)
476
+ OK memory 28.3 of 48.0 GB free, memory-guard blocks heavy commands below 3 GB, bulkhead-slot keeps 5 GB free for a second job
477
+ OK slots none held
478
+ OK event log ~/.claude/bulkhead/events.jsonl, 2 events, 254 B (rotates at 1 MB)
479
+ OK git 2.56.0
480
+
481
+ Enforcement
482
+ OK install bulkhead@bulkhead 0.3.0 at ~/.claude/plugins/cache/bulkhead/bulkhead/0.3.0, enabled in user settings
483
+ OK hooks on no disableAllHooks or allowManagedHooksOnly in user, project, local or managed settings
484
+ OK hooks.json installed copy: 4 PreToolUse hooks, all synchronous
485
+ OK hook node /opt/homebrew/bin/node v24.22.1
486
+ OK hook kill-guard blocked "pkill node" (exit 2, message shown to Claude) in 71 ms
487
+ OK hook wait-guard blocked "sleep 100000" (exit 2, message shown to Claude) in 64 ms
488
+ OK hook disk-guard blocked "du -sh /" (exit 2, message shown to Claude) in 70 ms
489
+ OK hook basics blocked "rm -rf /" (exit 2, message shown to Claude) in 63 ms
490
+
491
+ 30 OK, 0 WARN, 0 FAIL
402
492
  ```
403
493
 
404
494
  ### bulkhead port
@@ -428,7 +518,7 @@ O `bulkhead-statusline` imprime uma linha para a status line do Claude Code:
428
518
  3 sessions 2 heavy 9.1 GB free
429
519
  ```
430
520
 
431
- Sessions são as entradas ativas em `~/.claude/sessions`, heavy é o número de jobs que seguram um bulkhead-slot, e free é a mesma medida que o memory-guard usa. Ele não varre processos, leva menos de 100 ms e mantém a linha em cache por 5 segundos no diretório de estado.
521
+ Sessions são as entradas ativas em `~/.claude/sessions`, heavy é o número de jobs que seguram um bulkhead-slot, e free é a mesma medida que o memory-guard usa. Quando há sessões esperando por você, a linha acrescenta `2 waiting` depois da contagem de sessões. Ele não lista todos os processos (um único `ps` só para os PIDs das sessões), leva cerca de 100 ms a frio em um Mac com 650 processos e mantém a linha em cache por 5 segundos no diretório de estado, gravada por um arquivo temporário para que sessões concorrentes nunca leiam metade dela.
432
522
 
433
523
  Um plugin não consegue definir a status line principal (as configurações de plugin só aceitam `agent` e `subagentStatusLine`), então adicione-a você mesmo ao `~/.claude/settings.json`:
434
524
 
@@ -447,7 +537,7 @@ Isso exige `npm install -g claude-bulkhead`, que coloca o `bulkhead-statusline`
447
537
  ## FAQ
448
538
 
449
539
  **Ele deixa o Claude Code mais lento?**
450
- Um pouco. Cada guard é um processo Node curto. Em um desktop com Windows 11 e Node 24, `node scripts/bench-hooks.js 15` mediu de 40 a 49 ms por guard em um comando permitido (mediana de 15 execuções), e 33 ms só para iniciar o Node. Gravar um bloqueio no log de eventos não acrescenta tempo mensurável. Os guards só fazem trabalho lento, como ler a lista de processos (um ou dois segundos no Windows), quando o comando casa: a inicialização de um dev server em uma porta que já responde, um kill, um comando pesado. A status line leva menos de 100 ms e fica em cache por 5 segundos.
540
+ Um pouco. Todos os guards do Bash rodam em um único processo Node curto e sem dependências, cerca de 76 ms por chamada de ferramenta em um MacBook Pro (Node 24), dos quais 32 ms são só para iniciar o Node. Quando 10 sessões fazem uma chamada de ferramenta no mesmo instante, cada uma espera cerca de 89 ms (318 ms quando cada guard era um processo separado, como na 0.2). Gravar um bloqueio no log de eventos não acrescenta tempo mensurável. Os guards só fazem trabalho lento, como ler a lista de processos (um ou dois segundos no Windows), quando o comando casa: a inicialização de um dev server em uma porta que já responde, um kill, um comando pesado. A status line leva cerca de 100 ms a frio e fica em cache por 5 segundos.
451
541
 
452
542
  **Ele bloqueou algo que não devia. O que eu faço?**
453
543
  Rode `bulkhead log` para ver o comando exato e o motivo. Libere-o na configuração do projeto, `<repo>/.claude/bulkhead.json`: `killGuard.allowNames` para um nome de programa, `portGuard.ignorePorts` para uma porta compartilhada, `waitGuard.limitSeconds` para uma espera mais longa, ou `"enabled": false` para o guard inteiro nesse projeto. Veja [docs/configuration.md](docs/configuration.md). Depois, por favor, abra uma [issue de falso positivo](https://github.com/dooly6276/claude-bulkhead/issues/new?template=false-positive.yml) com a linha do `bulkhead log`, para que o padrão seja corrigido para todo mundo.
@@ -456,7 +546,7 @@ Rode `bulkhead log` para ver o comando exato e o motivo. Libere-o na configuraç
456
546
  Sim. O kill-guard, o wait-guard, o memory-guard e o basics protegem uma única sessão e seus subagents da mesma forma. O port-guard e o checkout-guard só agem quando há outra sessão ativa, e o orphan-reaper limpa o que ficou de sessões que já terminaram.
457
547
 
458
548
  **Quais sistemas ele suporta?**
459
- Windows, Linux e macOS, com Node 18 ou mais recente. O orphan-reaper no macOS é testado com fixtures da saída do `ps`, mas ainda não em um Mac de verdade, e no Linux ele precisa de uma versão do Claude Code que defina `CLAUDE_PID` nos shells das ferramentas. No Windows, o `bulkhead-slot` roda comandos pelo Git Bash quando ele está instalado e pelo `cmd.exe` caso contrário.
549
+ Windows, Linux e macOS, com Node 18 ou mais recente. O orphan-reaper no macOS é testado com fixtures da saída do `ps` e em um Mac de verdade (uma sessão de mentira foi encerrada e só o que ela deixou foi parado), e no Linux ele precisa de uma versão do Claude Code que defina `CLAUDE_PID` nos shells das ferramentas. No Windows, o `bulkhead-slot` roda comandos pelo Git Bash quando ele está instalado e pelo `cmd.exe` caso contrário.
460
550
 
461
551
  **Ele envia algo para algum lugar?**
462
552
  Não. Não há telemetria nem chamadas de rede. O único socket que ele abre é a tentativa de conexão do port-guard a `localhost` para ver se uma porta responde. Os logs ficam no diretório de estado. A única exceção é o `bulkhead remote`, que se conecta por SSH a uma máquina que você configurou, e somente quando você o executa.
@@ -477,6 +567,8 @@ Mais perguntas, incluindo como os guards podem ser contornados e como os número
477
567
  /plugin marketplace remove bulkhead
478
568
  ```
479
569
 
570
+ Se você instalou o pacote npm, rode `npm uninstall -g claude-bulkhead`. Um waiter de SessionEnd que já esteja rodando termina sozinho em até 3 minutos, então nada continua rodando depois da desinstalação.
571
+
480
572
  Depois, apague o diretório de estado (`~/.claude/bulkhead`, ou `BULKHEAD_STATE_DIR` se você o definiu) e remova a entrada `statusLine` do `~/.claude/settings.json`, caso a tenha adicionado.
481
573
 
482
574
  ## Usa o bulkhead? Mostre