claude-bulkhead 0.0.0-stage → 0.2.2

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 (48) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/LICENSE +21 -0
  3. package/README.es.md +498 -0
  4. package/README.ja.md +498 -0
  5. package/README.ko.md +498 -0
  6. package/README.md +497 -2
  7. package/README.pt-BR.md +498 -0
  8. package/README.zh-CN.md +498 -0
  9. package/bin/bulkhead +3 -0
  10. package/bin/bulkhead-slot +3 -0
  11. package/bin/bulkhead-statusline +3 -0
  12. package/hooks/hooks.json +39 -0
  13. package/package.json +52 -4
  14. package/src/basics.js +236 -0
  15. package/src/checkout-guard.js +296 -0
  16. package/src/cli-util.js +79 -0
  17. package/src/cli.js +41 -0
  18. package/src/config-check.js +29 -0
  19. package/src/config-cli.js +51 -0
  20. package/src/config.js +236 -0
  21. package/src/dev-servers.js +223 -0
  22. package/src/disk-guard.js +200 -0
  23. package/src/doctor.js +255 -0
  24. package/src/events.js +108 -0
  25. package/src/hook.js +94 -0
  26. package/src/kill-guard.js +435 -0
  27. package/src/log-cli.js +146 -0
  28. package/src/memory-guard.js +145 -0
  29. package/src/memory.js +76 -0
  30. package/src/orphan-reaper.js +527 -0
  31. package/src/paths.js +31 -0
  32. package/src/port-cli.js +59 -0
  33. package/src/port-guard.js +142 -0
  34. package/src/processes.js +181 -0
  35. package/src/reap-cli.js +56 -0
  36. package/src/remote-sh.js +478 -0
  37. package/src/remote.js +1034 -0
  38. package/src/remotes.js +126 -0
  39. package/src/scan.js +604 -0
  40. package/src/sessions.js +147 -0
  41. package/src/shell.js +597 -0
  42. package/src/slot-cli.js +150 -0
  43. package/src/slots.js +168 -0
  44. package/src/status.js +111 -0
  45. package/src/statusline.js +69 -0
  46. package/src/top-worker.js +14 -0
  47. package/src/top.js +305 -0
  48. package/src/wait-guard.js +263 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,90 @@
1
+ # Changelog
2
+
3
+ ## 0.2.2 - 2026-11-11
4
+
5
+ ### Fixed
6
+
7
+ - `bulkhead scan` no longer crashes with `RangeError: Maximum call stack size exceeded` on a long history (hundreds of thousands of commands). The span is found with a loop, and a list append in the event log reader no longer spreads a whole file into one call.
8
+ - `bulkhead scan 30d` now means `--since 30d`. It used to ignore the argument and scan everything. Every subcommand now rejects an option or argument it does not know, with its usage text, instead of ignoring it.
9
+ - The status line counted session files whose pid was alive, so a reused pid counted as a session. It now counts Claude Code processes the way `bulkhead status` does, from one `ps` listing (Windows keeps the pid check).
10
+ - `git pull` in a tree another session works in gets its own advice (wait for that session to commit or stash, or pull from a clone nobody uses) instead of the worktree advice.
11
+
12
+ ### Added
13
+
14
+ - `bulkhead scan` reads about twice as fast and prints a progress line on stderr when it runs longer than 3 seconds in a terminal.
15
+ - A block message from kill-guard, wait-guard, disk-guard, checkout-guard and basics ends with one line telling the agent to ask the user when the command was meant, and that the user can allow it in `.claude/bulkhead.json`.
16
+ - checkout-guard `remove-session-dir` resolves `$PWD`, `${PWD}`, `$(pwd)` and `` `pwd` `` to the current folder, so `rm -rf "$(pwd)"` is caught like `rm -rf .`.
17
+ - port-guard checks a `PORT=3000` set in the command for `npm start`, `npm run dev` and similar scripts, and for `node server.js`, `tsx`, `nodemon`, `bun` and `deno` running a file.
18
+ - kill-guard also blocks killing by name Electron, Simulator, Xcode, postgres, Docker Desktop, Code Helper and Cursor.
19
+ - The package can be run without the plugin: `npx claude-bulkhead status`, `top`, `scan`, `doctor`. It installs a `claude-bulkhead` command next to `bulkhead`. With `npm install -g claude-bulkhead`, the status line command no longer contains the plugin version.
20
+ - The README opens with a real Claude Code recording of kill-guard blocking `pkill node` (`docs/demo.gif`, re-recorded with `docs/demo.tape`), and the install steps come first.
21
+
22
+ ## 0.2.1 - 2026-11-11
23
+
24
+ - `/bulkhead:remote` now shows what a run will upload (the current commit and every uncommitted change, deletions included) and the remote it goes to, and waits for your yes before anything is sent.
25
+ - The README says that a project's `.claude/bulkhead.json` can relax the guards for that repository, so read it in a repository you clone, and that `bulkhead config` shows where each setting came from.
26
+
27
+ ## 0.2.0 - 2026-11-08
28
+
29
+ ### New
30
+
31
+ - **`bulkhead scan`** replays the shell commands in your Claude Code transcripts (`~/.claude/projects`, subagents included) against the guards and prints what they would have stopped: hits per guard and rule, in how many sessions, how many a hook or you already stopped, the newest examples with secrets masked, and the most sessions that ran at once. checkout-guard is rebuilt from which sessions were active in the same git tree at that minute. Read-only, about 200 MB of transcripts a second. `--since`, `--project`, `--path`, `-n`, `--json`, and `/bulkhead:scan`.
32
+ - **disk-guard** blocks scans that walk the whole drive or home folder (`du -sh ~`, `du -sh ~/*`, `ncdu /`, `Get-ChildItem C:\ -Recurse`, `dir /s C:\`), `find /` and `find ~` without `-maxdepth`, and disk scans run in parallel (`xargs -P`, GNU `parallel`, `&` in a loop, `ForEach-Object -Parallel`). The disk is shared by every session, and these stall all of them for minutes.
33
+ - **checkout-guard `stage-all`** blocks `git add -A`, `git add .`, `git add -u` and `git commit -a` in a tree with changes when another live session works in it: the other session's half-finished edits would go into your commit. Named files pass.
34
+ - **checkout-guard `remove-session-dir`** blocks `rm -rf`, `Remove-Item -Recurse -Force`, `rd /s` and `git worktree remove` of the folder another live session works in, or a folder above it.
35
+ - **checkout-guard `worktree-force-links`** (Windows) blocks `git worktree remove --force` on a worktree with junctions or symlinks in its first two levels, which git has followed into the main checkout's `node_modules`.
36
+ - **basics `agent-author`** blocks commits authored as Claude or Anthropic: `--author`, `git config user.name/user.email`, `git -c user.name=`, `GIT_AUTHOR_*` and `GIT_COMMITTER_*`. A `Co-Authored-By` trailer passes.
37
+ - **basics `rm-root`** also covers a folder directly in the home directory (`~/Documents`, `~/Desktop`; caches such as `~/.cache`, `~/.npm` and `~/tmp` pass) and top-level folders of the drive (`/srv`, `/usr`).
38
+ - New config keys `diskGuard.enabled`, `checkoutGuard.stageAll`, `checkoutGuard.removeSessionDir` and `basics.agentAuthor`, and `BULKHEAD_DISABLE` names `disk-guard`, `stage-all`, `remove-session-dir` and `agent-author`. `bulkhead doctor` lists rules turned off in any guard.
39
+ - The skill covers committing by file name, not deleting another session's folder, the git identity, and the disk.
40
+
41
+ ### Changed
42
+
43
+ - The repository moved to `dooly6276/claude-bulkhead`; the old address redirects. Install with `/plugin marketplace add dooly6276/claude-bulkhead`.
44
+ - New README hero and `bulkhead scan` animations, light and dark.
45
+
46
+ ## 0.1.1 - 2026-10-13
47
+
48
+ - `/bulkhead:remote` printed nothing when no remote was configured, and `/bulkhead:doctor` printed nothing when a check failed: Claude Code drops a slash command whose shell step exits non-zero. Both now show the output.
49
+ - Each slash command pre-approves only the one `bulkhead` command it runs instead of any `node` command.
50
+ - The repository no longer ships `package-lock.json`. Claude Code installs a plugin's packages when it finds a lockfile in the plugin root, so the lint tools could be installed with the plugin. The runtime still has no dependencies.
51
+ - `PRIVACY.md` lists what bulkhead reads, stores and sends, and `plugin.json` carries the listing links.
52
+
53
+ ## 0.1.0 - 2026-10-13
54
+
55
+ First public release.
56
+
57
+ ### Guards
58
+
59
+ - **kill-guard** blocks kills by program name that would hit other sessions' processes: `pkill`, `killall`, `taskkill /IM` and `/FI`, `Stop-Process -Name`, `Get-Process ... | Stop-Process`, `wmic ... delete`, name lookups fed to `kill` through `$(...)`, `xargs`, loops or variables, wildcards and several names at once. Kills scoped to a PID, a command line, a path or a script pass.
60
+ - **wait-guard** blocks foreground waits that can hold a session longer than 180 seconds: sleep loops, inline `python -c` or `node -e` sleeps, `timeout /t`, `ping -n`, `[Threading.Thread]::Sleep`, and following a log with `tail -f`, `docker logs -f`, `journalctl -f` or `Get-Content -Wait`. Sleeps in a background job pass.
61
+ - **memory-guard** blocks heavy commands (test suites, builds, browser automation, container builds) when free RAM is below 3 GB or 15% of RAM, and points to `bulkhead-slot` or, when one is configured, `bulkhead remote`.
62
+ - **port-guard** blocks starting a dev server on a port another live session is listening on and suggests a free one. It also blocks kills by port aimed at another session's server (`npx kill-port`, `fuser -k`, `lsof -t -i:N | xargs kill`, `Get-NetTCPConnection` with `Stop-Process`, `netstat` with `taskkill`).
63
+ - **checkout-guard** blocks `git checkout`, `switch`, `stash`, `reset --hard`, `clean -f`, `rebase`, `merge` and a dirty `pull` when another live session works in the same working tree, and suggests `git worktree add`.
64
+ - **basics** blocks `rm -rf` at roots, the home directory and folders above the repository, force-pushes to protected branches, and `git reset --hard` or `git clean -fd` that would lose uncommitted work. Each rule can be turned off.
65
+ - **orphan-reaper** stops what a finished session left running: dev servers, test runners and their workers (Vitest, Jest, Mocha, AVA, `node --test`, Playwright, pytest and pytest-xdist, `cargo test`, `go test`, `dotnet test`), watchers, builders and automation browsers. It runs within seconds of a session exiting (a detached waiter started by the `SessionEnd` hook) and again at session start. Only processes started from that session's Claude tool shells are touched; editors, terminals, shared build daemons and machine services are never stopped, nor anything under them. Windows, macOS and Linux.
66
+
67
+ All guards read commands through one shared parser for Bash, PowerShell and cmd that opens wrappers (`bash -c`, `powershell -Command`, `-EncodedCommand`, `cmd /c`, `eval`, `sudo`, `env`, `timeout`, `xargs` and more) up to three levels deep. Commit, tag, pull request and release text never triggers a guard. Commands sent to another machine or container are left to that machine.
68
+
69
+ ### Commands
70
+
71
+ - `bulkhead status` and `bulkhead top`: sessions with their project, memory, child processes and ports, slot jobs and the queue, free RAM, and the latest blocks. `top` is a live full-screen view.
72
+ - `bulkhead-slot run --gb=N -- <command>` (also `bulkhead slot`): queues heavy commands against a RAM budget shared by every session on the machine.
73
+ - `bulkhead remote` (optional): runs a heavy command on another machine over SSH. It sends the commit as an incremental git bundle plus uncommitted changes, runs it in one of up to 8 copies of the repository with its own port in `BULKHEAD_PORT`, returns the exit code, and stops everything the command started when it ends or the connection drops. `--tail=N` keeps the full output in a file and prints only the end. Also `fetch`, `status`, `list`, `add` and `remove`. The remote needs only an SSH server, bash, git and tar. See `docs/remote.md`.
74
+ - `bulkhead reap [--dry-run]`: runs orphan-reaper by hand; the dry run lists what it would stop and why.
75
+ - `bulkhead log`: what the guards blocked and what orphan-reaper stopped, with `--since`, `--guard`, `--summary` and `--json`.
76
+ - `bulkhead doctor`: checks the install, the settings, each guard, the process reader, RAM limits, slots, the event log, git and configured remotes.
77
+ - `bulkhead config`: every setting, its effective value and where it came from.
78
+ - `bulkhead port [--near N]`: a port nothing listens on.
79
+ - `bulkhead-statusline`: live sessions, held slots and free RAM for the Claude Code status line.
80
+ - Slash commands `/bulkhead:status`, `/bulkhead:log`, `/bulkhead:doctor`, `/bulkhead:remote` and `/bulkhead:reap`, and a `bulkhead` skill that tells Claude how to work on a machine shared with other sessions.
81
+
82
+ ### Configuration
83
+
84
+ - `~/.claude/bulkhead/config.json` and a per-project `.claude/bulkhead.json`, merged in that order, with environment variables winning. Every guard can be turned off, and the common false positives have their own keys. A broken file is ignored and reported once at session start. Remotes can be set in the global file only. See `config.example.json` and `docs/configuration.md`.
85
+ - Every block and every stopped process is appended to `events.jsonl` in the state directory; `BULKHEAD_NO_LOG=1` turns it off.
86
+
87
+ ### Quality
88
+
89
+ - More than 2,400 tests on Linux, macOS and Windows with Node 18, 22 and 24, including a corpus of more than 900 real command lines run through the actual hooks, a fuzz test that checks every guard stays linear on 1 MB inputs, and an end-to-end `bulkhead remote` run against a real SSH server.
90
+ - No dependencies. Each guard adds about 40 to 50 ms to a tool call.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Myeongseok-Kang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.es.md ADDED
@@ -0,0 +1,498 @@
1
+ <h1 align="center">claude-bulkhead</h1>
2
+
3
+ <p align="center">
4
+ <strong>Evita que Claude Code ejecute <code>pkill node</code> sobre tus otros servidores de desarrollo, les quite los puertos y haga commit de las ediciones de otra sesión con <code>git add -A</code>.</strong>
5
+ </p>
6
+
7
+ <p align="center">Hooks que saben qué procesos, puertos y árboles de git pertenecen a cada sesión y subagente de Claude Code, así que bloquean solo lo que dañaría a otra cosa y le dicen a Claude qué comando seguro ejecutar en su lugar. Cero dependencias, sin telemetría.</p>
8
+
9
+ <p align="center">
10
+ <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="tests"></a>
11
+ <img src="https://img.shields.io/badge/node-18%2B-34d6b4?style=flat-square" alt="Node 18+">
12
+ <img src="https://img.shields.io/badge/dependencies-0-34d6b4?style=flat-square" alt="cero dependencias">
13
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-34d6b4?style=flat-square" alt="licencia MIT"></a>
14
+ </p>
15
+
16
+ <p align="center">
17
+ <img src="docs/demo.gif" alt="Dos sesiones de Claude Code trabajan en dos worktrees de una misma app. La sesión A sirve checkout en el puerto 3000. A la sesión B se le pide matar todos los procesos node y reiniciar su servidor de search; el kill-guard de bulkhead bloquea el comando, Claude reinicia solo su propio servidor y checkout sigue funcionando con el mismo PID." width="100%">
18
+ </p>
19
+
20
+ <p align="center"><sub><a href="README.md">English</a> | <a href="README.ko.md">한국어</a> | <a href="README.zh-CN.md">简体中文</a> | <a href="README.ja.md">日本語</a> | <a href="README.pt-BR.md">Português (Brasil)</a></sub></p>
21
+
22
+ ## Instalación
23
+
24
+ Dentro de Claude Code:
25
+
26
+ ```
27
+ /plugin marketplace add dooly6276/claude-bulkhead
28
+ /plugin install bulkhead@bulkhead
29
+ ```
30
+
31
+ Después, mira qué habría detenido en tu último mes, sin cambiar nada:
32
+
33
+ ```
34
+ /bulkhead:scan 30d
35
+ ```
36
+
37
+ Node 18 o superior debe estar en el `PATH` (el instalador nativo de Claude Code no lo instala; compruébalo con `node --version`). Para los comandos de terminal y la línea de estado, ejecuta también `npm install -g claude-bulkhead`, o usa `npx claude-bulkhead status` sin instalar.
38
+
39
+ ## Qué detiene
40
+
41
+ | Sin bulkhead | Con bulkhead |
42
+ |---|---|
43
+ | Un agente reinicia su dev server con `pkill node` y se caen con él los servidores de todos los demás worktrees. | kill-guard bloquea el comando y le explica al agente cómo encontrar y detener su propio PID. |
44
+ | Dos sesiones comparten un checkout. Una ejecuta `git add -A && git commit` y los cambios a medias de la otra viajan en ese commit. | checkout-guard lo bloquea y pide los nombres de archivo. |
45
+ | Dos worktrees ejecutan `npm run dev`. El segundo pasa al 3001, pero su agente sigue probando `localhost:3000` y ve la otra rama. | port-guard bloquea el segundo arranque e indica un puerto libre. `bulkhead port` imprime uno cuando lo pides. |
46
+ | Tres sesiones lanzan `next build`, `npm test` y Playwright en el mismo minuto, y la máquina se congela. | memory-guard bloquea los comandos pesados cuando queda poca RAM. Con `bulkhead-slot`, el tercer trabajo espera en una cola hasta que haya espacio. |
47
+
48
+ <details>
49
+ <summary>Cinco más</summary>
50
+
51
+ | Sin bulkhead | Con bulkhead |
52
+ |---|---|
53
+ | Una sesión cambia de rama en un árbol que otra sesión está editando. | checkout-guard lo bloquea y sugiere `git worktree add`. |
54
+ | Una sesión termina y sus dev servers, test workers y watchers siguen corriendo, ocupando RAM y puertos. | orphan-reaper los detiene a los pocos segundos de que la sesión termine. |
55
+ | Un subagente hace polling en primer plano durante diez minutos. La sesión no puede responderte y la caché del prompt caduca. | wait-guard bloquea el bucle y pide usar `run_in_background: true`. |
56
+ | Un agente quiere saber qué ocupa el disco y lanza diez `du` a la vez sobre tu carpeta personal. Los builds y el `git status` de todas las sesiones van a paso de tortuga durante minutos. | disk-guard lo bloquea y pide una carpeta cada vez. |
57
+ | Una tarea de "limpiar los worktrees" ejecuta `git worktree remove` sobre un worktree en el que otra sesión sigue trabajando. | checkout-guard lo bloquea e indica qué sesión sigue allí. |
58
+
59
+ </details>
60
+
61
+ Con una sola sesión siguen activos kill-guard, memory-guard, wait-guard, disk-guard y basics (nada de `rm -rf ~`, ni force-push a `main`, ni `reset --hard` sobre trabajo sin commit). port-guard y checkout-guard actúan cuando hay una segunda sesión o un subagente activo.
62
+
63
+ ## ¿Qué es?
64
+
65
+ <p align="center">
66
+ <picture>
67
+ <source media="(prefers-color-scheme: light)" srcset="docs/hero-light.svg">
68
+ <img src="docs/hero.svg" alt="Varias sesiones de Claude Code en git worktrees separados dentro de una misma máquina. kill-guard bloquea pkill node, port-guard mueve un segundo dev server a un puerto libre, disk-guard detiene diez escaneos du en paralelo, checkout-guard evita que git add -A arrastre a un commit los cambios de otra sesión, y bulkhead-slot pone en cola un tercer trabajo pesado para que la RAM libre se mantenga por encima del mínimo. Después, bulkhead scan cuenta lo que habría detenido en sesiones pasadas." width="100%">
69
+ </picture>
70
+ </p>
71
+
72
+ Los hooks de Claude Code son pequeños programas que Claude Code ejecuta antes de cada comando de shell y que pueden detener el comando y decirle a Claude por qué. bulkhead es un conjunto de ellos. Antes de cada llamada a Bash o PowerShell comprueba el comando contra lo que hacen las demás sesiones de la máquina: qué procesos y puertos son de cada sesión, cuánta RAM queda y en qué árbol de git trabaja cada una. Cuando el comando dañaría a otra sesión, lo bloquea y Claude recibe un mensaje con el comando más seguro que debe ejecutar. Claude lo lee y sigue adelante, normalmente sin preguntarte.
73
+
74
+ ## ¿Lo necesitas? Pregunta a tus transcripciones
75
+
76
+ No hace falta adivinar. Claude Code guarda la transcripción de cada sesión en `~/.claude/projects`, y `bulkhead scan` repite los comandos de shell que contienen contra los guards: cuántas sesiones ejecutas realmente a la vez y con qué frecuencia ya hacían lo que bulkhead bloquea.
77
+
78
+ <p align="center">
79
+ <picture>
80
+ <source media="(prefers-color-scheme: light)" srcset="docs/scan-light.svg">
81
+ <img src="docs/scan.svg" alt="bulkhead scan lee un mes de transcripciones, informa del máximo de sesiones que corrieron a la vez y lista, por guard y regla, cuántos comandos se habrían detenido, en cuántas sesiones, y cuántos ya los había detenido un hook o el usuario." width="100%">
82
+ </picture>
83
+ </p>
84
+
85
+ ```
86
+ /plugin install bulkhead@bulkhead # then, inside Claude Code:
87
+ /bulkhead:scan 30d
88
+ ```
89
+
90
+ Solo lee, enmascara todo lo que parezca un secreto antes de imprimir y no envía nada a ninguna parte. port-guard y la comprobación de poca RAM no se repiten, porque las transcripciones no registran qué puertos ni cuánta RAM estaban en uso; checkout-guard se reconstruye a partir de qué sesiones estaban activas en el mismo árbol de git en ese minuto. Detalles: [docs/commands.md](docs/commands.md#bulkhead-scan).
91
+
92
+ ## Por qué existe
93
+
94
+ Una forma habitual de acelerar el trabajo con Claude Code es ejecutar varias sesiones sobre un mismo repositorio, cada una en su propio git worktree y cada una con sus propios subagentes. git mantiene las ramas separadas. La máquina no: todas las sesiones comparten los mismos puertos, la misma tabla de procesos y la misma RAM. Ahí es donde chocan.
95
+
96
+ - Dos worktrees de la misma app ejecutan `npm run dev`. El segundo falla en el puerto 3000, o se pasa discretamente al 3001 mientras su agente sigue probando `localhost:3000` y ve la otra rama.
97
+ - Un agente reinicia su propio servidor con `pkill node` o `taskkill /IM node.exe` y tumba los dev servers y las pruebas de todos los demás worktrees, y a veces también su propia sesión.
98
+ - Tres sesiones lanzan `npm test`, `next build` y una ejecución de Playwright en el mismo minuto, y la máquina deja de responder.
99
+ - Una sesión termina y los dev servers que lanzó siguen corriendo.
100
+
101
+ El tracker de Claude Code tiene muchos reportes de exactamente esto:
102
+
103
+ - [#13941](https://github.com/anthropics/claude-code/issues/13941): al pedirle reiniciar un dev server, Claude ejecutó `taskkill //IM node.exe` o `pkill node` y mató su propia sesión.
104
+ - [#34754](https://github.com/anthropics/claude-code/issues/34754): `taskkill //F //IM python.exe` mató dos simulaciones de larga duración, después de que el usuario hubiera marcado sus PID como intocables.
105
+ - [#43225](https://github.com/anthropics/claude-code/issues/43225): al pedirle reiniciar un solo bot, Claude mató a la fuerza todos los procesos de Python de la máquina, unos 20 servicios.
106
+ - [#53229](https://github.com/anthropics/claude-code/issues/53229): a un agente se le dijo que detuviera solo los dev servers sin uso, y también mató un gateway y un proceso de Postgres que no había identificado.
107
+ - [#15487](https://github.com/anthropics/claude-code/issues/15487): 24 procesos de subagentes saturaron un VPS de 4 GB hasta que hubo que reiniciarlo; un comentarista congeló un Mac de 24 GB de la misma manera.
108
+ - [#11502](https://github.com/anthropics/claude-code/issues/11502) y [#25180](https://github.com/anthropics/claude-code/issues/25180): los procesos lanzados por agentes sobreviven a estos, 60 procesos de Node en un reporte y 550 workers de pytest en el otro.
109
+
110
+ claude-bulkhead es un conjunto de pequeños hooks que bloquean o limpian cada uno de estos casos. Cada uno se puede desactivar por separado. El nombre viene del patrón bulkhead (mamparo): que un compartimento se inunde no debe hundir el barco.
111
+
112
+ ## Qué hace
113
+
114
+ | | |
115
+ |---|---|
116
+ | **[kill-guard](docs/guards/kill-guard.md)**<br>Bloquea `pkill node`, `taskkill /IM`, `Stop-Process -Name` y otras formas de matar por nombre de programa. Matar por PID pasa. | **[port-guard](docs/guards/port-guard.md)**<br>Bloquea arrancar un dev server en un puerto que otra sesión ya sirve, y matar por puerto el servidor de esa sesión. |
117
+ | **[memory-guard y bulkhead-slot](docs/guards/memory-guard.md)**<br>Bloquea los comandos pesados cuando queda poca RAM y pone en cola los trabajos pesados contra un único presupuesto de RAM compartido por todas las sesiones. | **[checkout-guard](docs/guards/checkout-guard.md)**<br>Bloquea `git checkout`, `stash`, `reset --hard`, `git add -A` y similares cuando otra sesión activa trabaja en el mismo árbol, y el borrado de una carpeta en la que trabaja otra sesión. |
118
+ | **[wait-guard](docs/guards/wait-guard.md)**<br>Bloquea los bucles de sleep en primer plano de más de 3 minutos, que hacen que la siguiente petición reescriba toda la caché del prompt. | **[orphan-reaper](docs/guards/orphan-reaper.md)**<br>Cuando una sesión termina, detiene los dev servers, test workers, watchers y navegadores headless que dejó corriendo. |
119
+ | **[disk-guard](docs/guards/disk-guard.md)** <sup>new</sup><br>Bloquea `du -sh ~`, `find /` sin `-maxdepth` y los escaneos de disco en paralelo, que bloquean el disco que comparten todas las sesiones. | **[`bulkhead scan`](#lo-necesitas-pregunta-a-tus-transcripciones)** <sup>new</sup><br>Repite tus transcripciones pasadas de Claude Code contra los guards: qué habrían detenido y cuántas sesiones corrieron a la vez. |
120
+ | **[basics](docs/guards/basics.md)**<br>Bloquea `rm -rf` en una raíz, en el home o en una carpeta directamente dentro de él, los force-push a `main`, los reset que perderían trabajo sin commitear y los commits con Claude como autor. | **[`bulkhead status`, `top`, `log`, `doctor`](#ver-qué-se-está-ejecutando)**<br>Muestra cada sesión, su RAM, sus puertos, los trabajos en cola y lo que han bloqueado los guards. |
121
+ | **[Línea de estado](#línea-de-estado)**<br>`3 sessions 2 heavy 9.1 GB free` en la línea de estado de Claude Code, en menos de 100 ms. | **[Configuración y slash commands](#configuración)**<br>Configuración por máquina y por proyecto con listas de permitidos, más `/bulkhead:scan`, `/bulkhead:status`, `/bulkhead:log`, `/bulkhead:doctor` y `/bulkhead:reap`. |
122
+
123
+ Opcional: **[`bulkhead remote`](#ejecutar-trabajos-pesados-en-otra-máquina-opcional)** ejecuta una suite de pruebas, un build o una ejecución de navegador en otra máquina por SSH, cuando esta no tiene RAM de sobra.
124
+
125
+ ## Más demos
126
+
127
+ ![bulkhead status, y luego port-guard, kill-guard y wait-guard bloqueando a un agente](docs/demo.svg)
128
+
129
+ Una ejecución guionizada de `bulkhead status`, port-guard, kill-guard y wait-guard, grabada con [docs/demo.sh](docs/demo.sh). Las dos sesiones son procesos de relleno llamados `claude`; todo lo que se imprime viene de los scripts de los hooks y de `bulkhead status`. La grabación de la parte superior de esta página es una sesión real de Claude Code; cómo se hizo está en [docs/demo.tape](docs/demo.tape).
130
+
131
+ ## Inicio rápido
132
+
133
+ 1. Instala el plugin como se indica arriba y abre una sesión nueva de Claude Code.
134
+ 2. Mira qué habría detectado: ejecuta `/bulkhead:scan 30d`, o `bulkhead scan` en la herramienta Bash. Lee tus transcripciones del último mes y no cambia nada.
135
+ 3. Comprueba la instalación. Dentro de Claude Code ejecuta `/bulkhead:doctor`, o ejecuta `bulkhead doctor` en la herramienta Bash. Todas las líneas deben decir `OK`. Una línea `WARN` o `FAIL` indica el guard y el motivo.
136
+ 4. Abre una terminal junto a tus sesiones y ejecuta `npx claude-bulkhead top` (o `bulkhead top` tras `npm install -g claude-bulkhead`) para ver en vivo las sesiones, la RAM, los puertos y los trabajos pesados. Pulsa `q` para salir.
137
+
138
+ Después no hay nada más que hacer. Los guards se ejecutan en cada llamada a Bash y PowerShell. Para ver qué detuvieron, ejecuta `bulkhead log` o `/bulkhead:log`; `bulkhead log --summary` cuenta los bloqueos por guard en tu máquina. Para cambiar un umbral o permitir un comando, consulta [docs/configuration.md](docs/configuration.md). Todos los comandos están listados en [docs/commands.md](docs/commands.md).
139
+
140
+ ## Ejecutar trabajos pesados en otra máquina (opcional)
141
+
142
+ Cuando varias sesiones ejecutan suites de pruebas y builds a la vez, una sola máquina se queda sin RAM: memory-guard bloquea los comandos, o bulkhead-slot los hace esperar en cola. Si tienes una segunda máquina que está casi siempre libre, `bulkhead remote` ejecuta allí el comando pesado.
143
+
144
+ <p align="center">
145
+ <img src="docs/remote.svg" alt="Esta máquina tiene 1,8 GB libres, así que memory-guard retiene npm test. bulkhead remote envía por SSH a buildbox solo el commit nuevo y los archivos modificados, las pruebas se ejecutan allí en la copia a, en el puerto 7172, y vuelven las últimas 20 líneas. La RAM libre de esta máquina no cambia." width="100%">
146
+ </p>
147
+
148
+ ```
149
+ bulkhead remote add buildbox dev@192.168.1.20 --ssh-option=IdentityFile=~/.ssh/buildbox
150
+ bulkhead remote run -- npm test
151
+ ```
152
+
153
+ ```
154
+ [bulkhead remote] buildbox: 3f2a1c9 already there, 3 changed files (24 KB), 1 deleted
155
+ [bulkhead remote] buildbox copy a /home/dev/bulkhead-remote/acme-web-3f9a1c port 7172
156
+ ...test output...
157
+ [bulkhead remote] exit 0 after 1m 12s (copy a)
158
+ ```
159
+
160
+ - **Qué se envía.** El commit actual como git bundle (solo los commits que el remoto aún no tiene) y tus cambios sin commitear, incluidos los borrados. Los archivos ignorados se quedan aquí salvo que los indiques con `--files`. No se envía nada de fuera del repositorio.
161
+ - **Dónde se ejecuta.** En una de hasta 8 copias del repositorio en el remoto, de modo que las ejecuciones en paralelo no comparten árbol de trabajo. `node_modules` se conserva entre ejecuciones. Cada ejecución recibe su propio puerto en `$BULKHEAD_PORT`.
162
+ - **Espacio.** Los locks en el remoto reservan una copia y un hueco de trabajo, y `--gb=N` espera hasta que haya N GB libres allí. Si no hay sitio en `--wait` minutos, termina con código 3.
163
+ - **Limpieza.** Cuando el comando termina, o la conexión SSH se cae (Ctrl-C, un timeout de la herramienta), todo lo que lanzó en el remoto se detiene, incluido un servidor que haya quedado en su puerto.
164
+ - **El remoto** solo necesita un servidor SSH, `bash`, `git` y `tar`. Funcionan Linux, macOS y Windows con Git for Windows.
165
+
166
+ `bulkhead remote fetch PATH` trae archivos de vuelta desde la copia que usó la última ejecución, y `bulkhead remote status` muestra la RAM libre y los trabajos en curso de cada remoto. En Claude Code, `/bulkhead:remote <command>` ejecuta allí un comando en segundo plano. Configuración, opciones y códigos de salida: [docs/remote.md](docs/remote.md).
167
+
168
+ ## Cómo funciona
169
+
170
+ ```mermaid
171
+ flowchart LR
172
+ CC["Claude Code session"] -->|"PreToolUse: Bash, PowerShell"| G["kill-guard, wait-guard, memory-guard,<br>port-guard, checkout-guard, disk-guard, basics"]
173
+ CC -->|"SessionEnd, SessionStart"| R["orphan-reaper (background)"]
174
+ G -->|"read"| P["process table, listening ports,<br>~/.claude/sessions"]
175
+ G <-->|"read, append"| S[("state dir ~/.claude/bulkhead<br>slots, guards.log, events.jsonl")]
176
+ B["bulkhead-slot"] <--> S
177
+ G -->|"exit 2 + message: blocked"| CC
178
+ G -->|"exit 0: allowed"| CC
179
+ G -.->|"any error: exit 0"| CC
180
+ ```
181
+
182
+ Cada guard es un script de Node independiente y sin dependencias. Claude Code le pasa la llamada a la herramienta como JSON. El guard lee el texto del comando y solo investiga más a fondo cuando el comando coincide: la tabla de procesos, los puertos en escucha, los archivos de sesión que Claude Code guarda en `~/.claude/sessions`, la RAM libre o `git status`. Un bloqueo es un código de salida 2 con un mensaje que le dice a Claude qué hacer en su lugar. Cualquier error dentro de un guard deja pasar la llamada, así que un guard roto nunca detiene tu trabajo.
183
+
184
+ Todas las sesiones de la máquina comparten un único directorio de estado. bulkhead-slot guarda allí sus reservas de RAM, y allí se registra cada bloqueo. Hay más detalle, incluida la estructura del directorio de estado y cómo se encuentran las sesiones en cada sistema operativo, en [docs/architecture.md](docs/architecture.md).
185
+
186
+ ## Guards
187
+
188
+ Cada guard tiene una página con los comandos exactos que bloquea, lo que deja pasar, el mensaje que ve Claude y sus límites. La versión corta:
189
+
190
+ <details>
191
+ <summary><strong>kill-guard</strong>: matar por nombre de programa</summary>
192
+
193
+ Bloquea `taskkill /IM`, `taskkill /FI` sin PID, `Stop-Process -Name`, `Get-Process node | Stop-Process`, `pkill`, `killall`, `kill $(pgrep node)`, `wmic ... delete` y similares cuando apuntan a un programa que comparten otras sesiones, como `node`, `python`, `java`, `chrome`, `git` o `vite`. Matar por PID y por ruta de proyecto pasa. Matar por puerto también pasa, salvo que el puerto sea de otra sesión; eso lo comprueba port-guard. A Claude se le indica cómo encontrar sus propios PID.
194
+
195
+ Desactivar: `BULKHEAD_DISABLE=kill-guard`. Detalles: [docs/guards/kill-guard.md](docs/guards/kill-guard.md).
196
+ </details>
197
+
198
+ <details>
199
+ <summary><strong>port-guard</strong>: puertos de otra sesión</summary>
200
+
201
+ Bloquea arrancar un dev server (`npm run dev`, `next dev`, `vite`, `uvicorn`, `rails s` y más) en un puerto en el que escucha el árbol de procesos de otra sesión de Claude, y sugiere un puerto libre. También bloquea los comandos que matan por puerto, como `npx kill-port 3000`, `fuser -k 3000/tcp` y `lsof -ti :3000 | xargs kill`, cuando ese puerto es de otra sesión.
202
+
203
+ Desactivar: `BULKHEAD_DISABLE=port-guard`. Detalles: [docs/guards/port-guard.md](docs/guards/port-guard.md).
204
+ </details>
205
+
206
+ <details>
207
+ <summary><strong>memory-guard y bulkhead-slot</strong>: RAM</summary>
208
+
209
+ memory-guard bloquea los comandos pesados (test runners, `next build`, `tsc`, Gradle, el emulador de Android, Playwright, `cargo test`, `docker build` y similares) cuando la RAM libre es inferior a 3 GB, o inferior al 15 % de la RAM en máquinas con menos de 20 GB. `bulkhead-slot run --gb=4 -- <command>` espera a que haya espacio en el presupuesto de RAM compartido, ejecuta el comando y libera el hueco cuando termina.
210
+
211
+ Desactivar: `BULKHEAD_DISABLE=memory-guard`. Detalles: [docs/guards/memory-guard.md](docs/guards/memory-guard.md).
212
+ </details>
213
+
214
+ <details>
215
+ <summary><strong>checkout-guard</strong>: dos sesiones en un mismo árbol de git</summary>
216
+
217
+ Bloquea `git checkout <branch>`, `switch`, `stash`, `reset --hard`, `clean -f`, `rebase`, `merge`, `restore .` y un `pull` con cambios sin commitear cuando otra sesión activa trabaja en el mismo árbol, y sugiere `git worktree add`. También bloquea allí `git add -A`, `git add .` y `git commit -a` (`stage-all`), que arrastrarían a tu commit los cambios a medias de la otra sesión, y `rm -rf` o `git worktree remove` sobre una carpeta en la que trabaja otra sesión activa (`remove-session-dir`). En Windows bloquea `git worktree remove --force` sobre un worktree que contiene junctions, que git ha seguido hasta el checkout principal.
218
+
219
+ Desactivar: `BULKHEAD_DISABLE=checkout-guard`, o una sola regla con `BULKHEAD_DISABLE=stage-all` o `remove-session-dir`. Detalles: [docs/guards/checkout-guard.md](docs/guards/checkout-guard.md).
220
+ </details>
221
+
222
+ <details>
223
+ <summary><strong>disk-guard</strong>: escaneos de disco completo y en paralelo</summary>
224
+
225
+ Bloquea `du`, `ncdu`, `dust`, `ls -R`, `Get-ChildItem -Recurse` y `dir /s` sobre la unidad entera, la carpeta personal o la de todos los usuarios (`du -sh ~`, `du -sh ~/*`, `ncdu /`), `find /` y `find ~` sin `-maxdepth`, y los escaneos de disco en paralelo, sea cual sea su destino: `xargs -P 10 du`, GNU `parallel`, `du ... &` en un bucle, `ForEach-Object -Parallel`. Una carpeta cada vez pasa (`du -sh node_modules`, `du -sh ~/Library/Caches`).
226
+
227
+ Desactivar: `BULKHEAD_DISABLE=disk-guard`. Detalles: [docs/guards/disk-guard.md](docs/guards/disk-guard.md).
228
+ </details>
229
+
230
+ <details>
231
+ <summary><strong>wait-guard</strong>: esperas largas en primer plano</summary>
232
+
233
+ Bloquea un comando en primer plano cuyos sleeps pueden sumar más de 180 segundos. La caché del prompt caduca tras unos cinco minutos sin peticiones, así que un subagente que hace polling en primer plano reescribe todo el contexto cada vez que despierta. A Claude se le indica que ejecute el bucle con `run_in_background: true`. Los sleeps en un trabajo en segundo plano (`sleep 600 &`) pasan. Con el timeout de herramienta por defecto de 120 segundos, una espera no puede superar el límite por defecto, así que solo bloquea cuando la llamada sube el timeout.
234
+
235
+ Desactivar: `BULKHEAD_DISABLE=wait-guard`, o sube el límite con `BULKHEAD_WAIT_MAX_SEC`. Detalles: [docs/guards/wait-guard.md](docs/guards/wait-guard.md).
236
+ </details>
237
+
238
+ <details>
239
+ <summary><strong>orphan-reaper</strong>: procesos que dejan las sesiones que terminaron</summary>
240
+
241
+ Cuando una sesión termina, un proceso de espera oculto en segundo plano detiene lo que ella lanzó desde sus shells de herramientas y dejó corriendo: dev servers y cualquier otra cosa que escuche en un puerto, test runners y sus workers (Vitest, Jest, Playwright, pytest y xdist, `cargo test`, `go test` y más), watchers como `tsc --watch` y nodemon, builds como `next build` y navegadores headless. Una pasada al iniciar la sesión recoge lo que dejó un crash. Los editores, las terminales, los daemons compartidos como Gradle o adb y todo lo que hayas lanzado tú nunca se tocan. `bulkhead reap --dry-run` muestra qué detendría y por qué. Windows, Linux y macOS (macOS probado con fixtures).
242
+
243
+ Desactivar: `BULKHEAD_DISABLE=orphan-reaper`. Detalles: [docs/guards/orphan-reaper.md](docs/guards/orphan-reaper.md).
244
+ </details>
245
+
246
+ <details>
247
+ <summary><strong>basics</strong>: cuatro errores que no se pueden deshacer</summary>
248
+
249
+ `rm-root` (`rm -rf` en una raíz, en una carpeta de primer nivel como `/srv`, en el home, en una carpeta directamente dentro del home como `~/Documents`, o por encima del repositorio), `force-push-main` (`git push --force` a `main` o `master`; `--force-with-lease` pasa), `discard-changes` (`git reset --hard` o `git clean -fd` que perderían trabajo sin commitear) y `agent-author` (`--author="Claude <noreply@anthropic.com>"`, `git config user.name Claude` y similares, para que tus commits sigan contando como tuyos).
250
+
251
+ Desactivar: `BULKHEAD_DISABLE=basics`, o una sola regla por su nombre. Detalles: [docs/guards/basics.md](docs/guards/basics.md).
252
+ </details>
253
+
254
+ ## Cómo se relaciona bulkhead con otros paquetes de hooks
255
+
256
+ Los paquetes de seguridad generales protegen una sesión de comandos peligrosos. Por ejemplo, [claude-forge](https://github.com/sangrokjung/claude-forge) incluye hooks que filtran secretos filtrados en la salida, bloquean scripts remotos encadenados por pipe y detienen SQL destructivo, y [dcg](https://github.com/Dicklesworthstone/destructive_command_guard) y [cc-safety-net](https://github.com/kenryu42/claude-code-safety-net) cubren de forma amplia los comandos destructivos de shell y de git. Vale la pena usarlos.
257
+
258
+ bulkhead cubre otro problema: sesiones de una misma máquina que se estorban entre sí por la propiedad de los procesos, los puertos, la RAM compartida y un árbol de git compartido. Solo sus reglas de `basics` se solapan con esos paquetes, y puedes desactivarlas con `BULKHEAD_DISABLE=basics` si otro paquete ya las cubre. bulkhead convive con otros hooks: Claude Code ejecuta todos los hooks que coinciden con una llamada a una herramienta, y la llamada se detiene si alguno la bloquea.
259
+
260
+ ## Configuración
261
+
262
+ Los valores por defecto no requieren configuración. Para cambiarlos, usa un archivo de configuración: `~/.claude/bulkhead/config.json` para la máquina y `<repo>/.claude/bulkhead.json` para un proyecto (se busca subiendo hasta la carpeta con `.git`). La configuración del proyecto tiene prioridad sobre el archivo global.
263
+
264
+ Un archivo de proyecto puede quitar nombres de la lista de bloqueo de kill-guard, ignorar puertos o desactivar un guard en ese repositorio. Revisa `.claude/bulkhead.json` en un repositorio que clones antes de trabajar en él, como harías con el resto de su configuración; `bulkhead config` muestra cada ajuste y el archivo del que viene. Los hosts remotos y las opciones de ssh solo se leen del archivo global.
265
+
266
+ Por ejemplo, un proyecto que ejecuta `ffmpeg` a propósito y tiene una suite de integración lenta:
267
+
268
+ ```json
269
+ {
270
+ "killGuard": { "allowNames": ["ffmpeg"] },
271
+ "waitGuard": { "limitSeconds": 300 },
272
+ "portGuard": { "ignorePorts": [9229] },
273
+ "basics": { "protectedBranches": ["main", "release"] }
274
+ }
275
+ ```
276
+
277
+ Cada guard se puede desactivar con `"<guard>": { "enabled": false }`. `bulkhead config` imprime cada ajuste, su valor y de dónde viene. Un archivo roto se ignora, los guards conservan sus valores por defecto y la sesión muestra un aviso al arrancar. Todas las claves están en [docs/configuration.md](docs/configuration.md), y [config.example.json](config.example.json) define cada una de ellas.
278
+
279
+ Las variables de entorno siguen funcionando y tienen prioridad sobre ambos archivos. El lugar más sencillo para ponerlas es el bloque `env` de `~/.claude/settings.json`.
280
+
281
+ <details>
282
+ <summary>Todas las variables de entorno</summary>
283
+
284
+ | Variable | Valor por defecto | Equivale a |
285
+ |---|---|---|
286
+ | `BULKHEAD_DISABLE` | vacío | Guards que se desactivan, separados por comas: `kill-guard`, `wait-guard`, `memory-guard`, `port-guard`, `checkout-guard`, `disk-guard`, `orphan-reaper`, `basics`, o `all`. También se pueden desactivar reglas sueltas: `rm-root`, `force-push-main`, `discard-changes`, `agent-author`, `stage-all`, `remove-session-dir`. Un nombre aquí queda desactivado digan lo que digan los archivos |
287
+ | `BULKHEAD_WAIT_MAX_SEC` | 180 | `waitGuard.limitSeconds` |
288
+ | `BULKHEAD_MIN_FREE_GB` | 3, o el 15 % de la RAM si es menos | `memory.minFreeGb` |
289
+ | `BULKHEAD_SLOT_FLOOR_GB` | 5, o el 25 % de la RAM si es menos | `memory.slotFloorGb` |
290
+ | `BULKHEAD_MAX_COMMIT_PCT` | 75 | `memory.maxCommitPct` (solo Windows) |
291
+ | `BULKHEAD_NO_LOG` | vacío | `log.enabled: false` cuando vale `1` |
292
+ | `BULKHEAD_STATE_DIR` | `~/.claude/bulkhead` | Dónde viven los slots, el registro de eventos, `guards.log` y el archivo de configuración global |
293
+ | `BULKHEAD_SSH` | `ssh` en el `PATH` | El cliente ssh que ejecuta `bulkhead remote` |
294
+
295
+ </details>
296
+
297
+ ## Ver qué se está ejecutando
298
+
299
+ `bulkhead` está en el `PATH` de la herramienta Bash junto a `bulkhead-slot`. Dentro de Claude Code, `/bulkhead:scan [30d]`, `/bulkhead:status`, `/bulkhead:log [24h|7d]`, `/bulkhead:doctor` y `/bulkhead:reap` ejecutan el comando correspondiente y resumen su salida. En tu propia terminal, ejecuta `npx claude-bulkhead top`, o instálalo una vez con `npm install -g claude-bulkhead` y ejecuta `bulkhead top`. El paquete de npm es el mismo código que el plugin. Todos los comandos que imprimen una tabla aceptan `--json`. La referencia completa está en [docs/commands.md](docs/commands.md).
300
+
301
+ ### bulkhead status
302
+
303
+ Cada sesión de Claude Code de la máquina, la memoria que usa su árbol de procesos, lo que tiene escuchando en un puerto, los trabajos retenidos en bulkhead-slot y los que esperan, y la RAM libre:
304
+
305
+ ```
306
+ $ 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
313
+
314
+ SLOT GB PID AGE COMMAND
315
+ slot-1 4 30112 6 min npx playwright test
316
+
317
+ WAITING GB PID FOR COMMAND
318
+ #1 3 30200 2 min npm run build
319
+
320
+ 9.9 GB free of 31.8 GB, commit 68%
321
+ ```
322
+
323
+ `bulkhead slot ...` es lo mismo que `bulkhead-slot ...`.
324
+
325
+ ### bulkhead top
326
+
327
+ La misma vista, en vivo y a pantalla completa. Se actualiza cada 2 segundos en Linux y macOS y cada 4 segundos en Windows, donde un escaneo de procesos tarda de 1 a 2 segundos. El escaneo corre en un worker thread, así que las teclas nunca lo esperan. `q`, `Esc` o `Ctrl-C` salen, `r` actualiza.
328
+
329
+ ```
330
+ bulkhead top 14:30:05 scan 1.4s every 4s q quit r refresh
331
+ RAM ████████████████░░░░░░░░░░░░░░ 9.9 GB free of 31.8 GB commit 68%
332
+
333
+ SESSIONS 3
334
+ PID STARTED PROJECT RSS PROCS PORTS
335
+ 18672 Oct 12 17:49 ~/src/acme-web 1.4 GB ██████████ 12 :3000 :24678
336
+ 21888 Oct 12 17:52 ~/src/acme-web-auth 353 MB ███░░░░░░░ 3 -
337
+ 26448 03:43 ~/src/acme-web-checkout 625 MB ████░░░░░░ 5 :3001
338
+
339
+ HEAVY JOBS 1 running, 1 waiting
340
+ slot-1 4 GB 30112 6 min npx playwright test
341
+ wait #1 3 GB 30200 2 min npm run build (this machine has 16 GB; one heavy job at a time)
342
+
343
+ RECENT BLOCKS
344
+ 14:29 kill-guard taskkill-im ~/src/acme-web-auth taskkill /F /IM node.exe
345
+ 14:12 wait-guard poll-loop ~/src/acme-web-checkout until [ -f out/DONE ]; do sleep 30; done
346
+ ```
347
+
348
+ En una terminal estrecha elimina columnas en lugar de partir las líneas. Cuando la salida no es una terminal, o con `--once`, imprime una instantánea y termina.
349
+
350
+ ### bulkhead log
351
+
352
+ Cada bloqueo, y cada proceso que detiene orphan-reaper, es una línea JSON en `<state dir>/events.jsonl` con la hora, el guard, la regla, la sesión, el proyecto y el comando recortado a 200 caracteres. El archivo se queda en tu máquina, rota a 1 MB y conserva un archivo antiguo. `BULKHEAD_NO_LOG=1` lo desactiva.
353
+
354
+ ```
355
+ $ bulkhead log --summary --since 7d
356
+ 10 blocks in the last 7 days, 3 projects, 4 sessions
357
+
358
+ GUARD RULE COUNT LAST
359
+ wait-guard poll-loop 3 06:40 ████████████████████████
360
+ wait-guard long-sleep 2 06:40 ████████████████
361
+ basics force-push-main 1 06:40 ████████
362
+ basics rm-root 1 06:40 ████████
363
+ kill-guard pkill 1 06:40 ████████
364
+ kill-guard taskkill-im 1 06:40 ████████
365
+ memory-guard slot-files 1 06:40 ████████
366
+
367
+ PROJECT COUNT
368
+ ~/src/acme-web 4
369
+ ~/src/acme-web-auth 3
370
+ ~/src/acme-web-checkout 3
371
+ ```
372
+
373
+ `bulkhead log -n 20` lista los propios eventos, `--since 30m|24h|7d|2w|<date>` limita el período y `--guard kill-guard` limita el guard.
374
+
375
+ ### bulkhead doctor
376
+
377
+ Comprueba Node, los archivos del plugin, el directorio de estado, los archivos de configuración, cada guard (activo o desactivado, y por qué), una ejecución real de un hook, el lector de procesos con sus tiempos, los archivos de sesión, los límites de RAM calculados para esta máquina, los slots retenidos, el registro de eventos y git. El código de salida es 1 si falla alguna comprobación.
378
+
379
+ ```
380
+ $ 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
402
+ ```
403
+
404
+ ### bulkhead port
405
+
406
+ Imprime un puerto en el que no escucha nadie, comprobado en IPv4 e IPv6, para que un segundo worktree pueda arrancar su servidor sin adivinar:
407
+
408
+ ```
409
+ npm run dev -- --port $(bulkhead port --near 3000)
410
+ ```
411
+
412
+ ### bulkhead reap
413
+
414
+ Ejecuta orphan-reaper ahora. `--dry-run` lista lo que detendría, la regla que coincidió y por qué se considera que la sesión terminó, sin detener nada:
415
+
416
+ ```
417
+ $ bulkhead reap --dry-run
418
+ would stop 30112 test-runner node ~/src/acme-web/node_modules/vitest/dist/workers/forks.js
419
+ Vitest and its worker pool (tinypool); its session has exited and removed snapshot-bash-1791860359256-ezwkie.sh; 6 processes from 30080
420
+ 1 tree would be stopped. Run `bulkhead reap` to stop it.
421
+ ```
422
+
423
+ ### Línea de estado
424
+
425
+ `bulkhead-statusline` imprime una línea para la línea de estado de Claude Code:
426
+
427
+ ```
428
+ 3 sessions 2 heavy 9.1 GB free
429
+ ```
430
+
431
+ Las sesiones son las entradas activas en `~/.claude/sessions`, heavy es el número de trabajos que retienen un bulkhead-slot, y free es la misma medida que usa memory-guard. No escanea procesos, tarda menos de 100 ms y guarda la línea en caché durante 5 segundos en el directorio de estado.
432
+
433
+ Un plugin no puede definir la línea de estado principal (los ajustes de plugin solo admiten `agent` y `subagentStatusLine`), así que añádela tú mismo a `~/.claude/settings.json`:
434
+
435
+ ```json
436
+ {
437
+ "statusLine": {
438
+ "type": "command",
439
+ "command": "bulkhead-statusline",
440
+ "refreshInterval": 10
441
+ }
442
+ }
443
+ ```
444
+
445
+ Esto requiere `npm install -g claude-bulkhead`, que pone `bulkhead-statusline` en el `PATH`. Si ya tienes un script de línea de estado, llama a `bulkhead-statusline` desde él y añade su salida.
446
+
447
+ ## Preguntas frecuentes
448
+
449
+ **¿Ralentiza Claude Code?**
450
+ Un poco. Cada guard es un proceso corto de Node. En un equipo de escritorio con Windows 11 y Node 24, `node scripts/bench-hooks.js 15` midió entre 40 y 49 ms por guard en un comando permitido (mediana de 15 ejecuciones), y 33 ms solo por arrancar Node. Escribir un bloqueo en el registro de eventos no añade tiempo medible. Los guards solo hacen trabajo lento, como leer la lista de procesos (uno o dos segundos en Windows), cuando el comando coincide: arrancar un dev server en un puerto que ya responde, un kill, un comando pesado. La línea de estado tarda menos de 100 ms y se guarda en caché durante 5 segundos.
451
+
452
+ **Ha bloqueado algo que no debía. ¿Qué hago?**
453
+ Ejecuta `bulkhead log` para ver el comando exacto y el motivo. Déjalo pasar en la configuración del proyecto, `<repo>/.claude/bulkhead.json`: `killGuard.allowNames` para un nombre de programa, `portGuard.ignorePorts` para un puerto compartido, `waitGuard.limitSeconds` para una espera más larga, o `"enabled": false` para desactivar todo el guard en ese proyecto. Consulta [docs/configuration.md](docs/configuration.md). Después, abre por favor un [issue de falso positivo](https://github.com/dooly6276/claude-bulkhead/issues/new?template=false-positive.yml) con la línea de `bulkhead log`, para que el patrón se corrija para todos.
454
+
455
+ **¿Sirve con una sola sesión?**
456
+ Sí. kill-guard, wait-guard, memory-guard y basics protegen igual de bien a una sola sesión y a sus subagentes. port-guard y checkout-guard solo actúan cuando hay otra sesión activa, y orphan-reaper limpia lo que dejan las sesiones que ya terminaron.
457
+
458
+ **¿Qué sistemas soporta?**
459
+ Windows, Linux y macOS, con Node 18 o superior. orphan-reaper en macOS está probado con fixtures de la salida de `ps` pero todavía no en un Mac real, y en Linux requiere una versión de Claude Code que defina `CLAUDE_PID` para los shells de herramientas. En Windows, `bulkhead-slot` ejecuta los comandos a través de Git Bash si está instalado y, si no, a través de `cmd.exe`.
460
+
461
+ **¿Envía algo a algún sitio?**
462
+ No. No hay telemetría ni llamadas de red. El único socket que abre es el intento de conexión de port-guard a `localhost` para ver si un puerto responde. Los registros se quedan en el directorio de estado. La única excepción es `bulkhead remote`, que se conecta por SSH a una máquina que tú has configurado, y solo cuando lo ejecutas.
463
+
464
+ Hay más preguntas, incluidas cómo se pueden eludir los guards y cómo se miden las cifras de RAM, en [docs/faq.md](docs/faq.md).
465
+
466
+ ## Limitaciones
467
+
468
+ - Los guards leen el texto de los comandos. Lo dividen en comandos y abren envoltorios como `bash -c`, `cmd /c`, `powershell -EncodedCommand` y `sudo` hasta tres niveles de profundidad, pero un kill o un sleep escondido en un archivo de script, una función de shell o un alias no se ve. Detectan las formas habituales, no un rodeo deliberado.
469
+ - memory-guard y bulkhead-slot solo ven la RAM. No limitan la CPU, el disco ni la GPU.
470
+ - bulkhead-slot solo se usa cuando se le llama. Nada obliga a todas las sesiones a hacer cola a través de él.
471
+ - Cada página de guard lista sus propios límites.
472
+
473
+ ## Desinstalación
474
+
475
+ ```
476
+ /plugin uninstall bulkhead@bulkhead
477
+ /plugin marketplace remove bulkhead
478
+ ```
479
+
480
+ Después, borra el directorio de estado (`~/.claude/bulkhead`, o `BULKHEAD_STATE_DIR` si lo definiste) y elimina la entrada `statusLine` de `~/.claude/settings.json` si la añadiste.
481
+
482
+ ## ¿Usas bulkhead? Muéstralo
483
+
484
+ Añade esta insignia al README de tu proyecto:
485
+
486
+ ```markdown
487
+ [![Guarded by bulkhead](https://img.shields.io/badge/guarded_by-bulkhead-34d6b4?style=flat-square)](https://github.com/dooly6276/claude-bulkhead)
488
+ ```
489
+
490
+ Se muestra así: [![Guarded by bulkhead](https://img.shields.io/badge/guarded_by-bulkhead-34d6b4?style=flat-square)](https://github.com/dooly6276/claude-bulkhead)
491
+
492
+ ## Contribuir
493
+
494
+ Consulta [CONTRIBUTING.md](CONTRIBUTING.md). Reportes de seguridad: [SECURITY.md](SECURITY.md). El changelog está en [CHANGELOG.md](CHANGELOG.md), y lo que bulkhead guarda y envía está en [PRIVACY.md](PRIVACY.md).
495
+
496
+ ## Licencia
497
+
498
+ [MIT](LICENSE)