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.
- package/CHANGELOG.md +51 -0
- package/README.es.md +142 -50
- package/README.ja.md +142 -50
- package/README.ko.md +143 -51
- package/README.md +142 -50
- package/README.pt-BR.md +142 -50
- package/README.zh-CN.md +154 -62
- package/hooks/hooks.json +68 -8
- package/package.json +5 -2
- package/src/agent-hook.js +162 -0
- package/src/agent-setup.js +256 -0
- package/src/agents.js +89 -0
- package/src/allow-cli.js +65 -0
- package/src/allow-hint.js +62 -0
- package/src/allow-once.js +152 -0
- package/src/auto-queue.js +93 -0
- package/src/bash-guards.js +36 -0
- package/src/basics.js +46 -27
- package/src/checkout-guard.js +342 -74
- package/src/cli-util.js +13 -1
- package/src/cli.js +40 -4
- package/src/config-check.js +21 -4
- package/src/config-cli.js +75 -10
- package/src/config.js +106 -9
- package/src/dev-servers.js +361 -61
- package/src/disk-guard.js +8 -8
- package/src/doctor-enforcement.js +273 -0
- package/src/doctor.js +19 -9
- package/src/edit-guard.js +196 -0
- package/src/events.js +30 -5
- package/src/explain.js +251 -0
- package/src/git-info.js +55 -0
- package/src/gitargs.js +82 -0
- package/src/hook.js +38 -6
- package/src/kill-extras.js +219 -0
- package/src/kill-guard.js +228 -77
- package/src/kill-owners.js +116 -0
- package/src/log-cli.js +15 -10
- package/src/mcp.js +131 -0
- package/src/memory-guard.js +126 -24
- package/src/memory.js +21 -2
- package/src/notices.js +95 -0
- package/src/orphan-reaper.js +58 -11
- package/src/port-cli.js +78 -3
- package/src/port-guard.js +80 -68
- package/src/port-kills.js +198 -0
- package/src/pressure.js +75 -0
- package/src/processes.js +44 -12
- package/src/scan-report.js +166 -0
- package/src/scan.js +87 -18
- package/src/secrets-guard.js +301 -0
- package/src/self-allow.js +73 -0
- package/src/session-info.js +121 -0
- package/src/session-state.js +176 -0
- package/src/sessions.js +109 -20
- package/src/shell.js +279 -19
- package/src/slot-cli.js +92 -21
- package/src/slots.js +61 -13
- package/src/stable-port.js +61 -0
- package/src/status.js +55 -17
- package/src/statusline.js +45 -16
- package/src/subagent-guard.js +24 -0
- package/src/top.js +36 -11
- package/src/wait-guard.js +96 -32
- package/src/worktree-cli.js +454 -0
- 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
|
|
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`).
|
|
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.
|
|
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)
|
|
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
|
-
| **[
|
|
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
|
|
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>:
|
|
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
|
|
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
|
|
308
|
-
18672
|
|
309
|
-
:3000 node
|
|
310
|
-
21888
|
|
311
|
-
26448
|
|
312
|
-
:3001 node
|
|
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ê),
|
|
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
|
|
382
|
-
OK
|
|
383
|
-
OK state dir
|
|
384
|
-
OK config
|
|
385
|
-
OK
|
|
386
|
-
OK
|
|
387
|
-
OK
|
|
388
|
-
OK
|
|
389
|
-
OK
|
|
390
|
-
OK
|
|
391
|
-
OK
|
|
392
|
-
OK
|
|
393
|
-
OK
|
|
394
|
-
OK
|
|
395
|
-
OK
|
|
396
|
-
OK
|
|
397
|
-
OK
|
|
398
|
-
OK
|
|
399
|
-
OK
|
|
400
|
-
|
|
401
|
-
|
|
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
|
|
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.
|
|
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
|
|
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
|