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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 - 2026-11-12
|
|
4
|
+
|
|
5
|
+
### New
|
|
6
|
+
|
|
7
|
+
- **One hook process for every Bash guard.** `src/bash-guards.js` runs the guards in a row, text-only checks first and the ones that read git, memory, processes or ports last, and stops at the first block. A Bash call used to start seven Node processes. With 10 sessions making a tool call at the same moment, each now waits about 89 ms instead of 318 ms (611 ms to 109 ms with 20). `node scripts/bench-hooks.js 9 --sessions 10` measures it on your machine.
|
|
8
|
+
- **`bulkhead explain -- <command>`** shows what every guard would say about a command, with the evidence (which session owns the process or port, how much RAM is free) and how to allow it, without running anything.
|
|
9
|
+
- **Allow once.** Every block message ends with a code: the user runs `bulkhead allow <code>` in their own terminal and the same command passes once within 10 minutes. The new basics rule `self-allow` blocks the agent from running `bulkhead allow` or writing the allow files itself, in 25 spellings.
|
|
10
|
+
- **Presets.** `bulkhead config --preset quiet|normal|strict [--project]`. `quiet` keeps only what protects one session from another and the rules that cannot be undone; `strict` tightens the limits, scaled to the machine's RAM, and turns secrets-guard on.
|
|
11
|
+
- **`bulkhead worktree add|list|prune`.** `add` makes `../<repo>-<name>` on a new branch, copies your `.env` files (or what `.worktreeinclude` lists), installs dependencies with the lockfile's package manager and writes a stable `PORT` to `.env.local`. `list` shows branch, age, changes, ahead and behind, live session and port. `prune` removes worktrees that are merged (squash and rebase merges included), clean and idle, never one a live session works in, and is a dry run until `--yes`.
|
|
12
|
+
- **`bulkhead port --stable`** gives a worktree the same port every time, and port-guard suggests it first.
|
|
13
|
+
- **Auto-queue.** With `{"memoryGuard":{"autoQueue":true}}`, a heavy command is not refused: the hook rewrites it to run through `bulkhead-slot` and it starts when there is room. Waiting jobs are served first in, first out, poll once a second, and print their place in line every 30 seconds.
|
|
14
|
+
- **subagent-guard** (opt-in, `memoryGuard.subagents`) stops new subagents while memory pressure is critical.
|
|
15
|
+
- **edit-guard** tells the agent, before it edits a file, that another live session edited the same file in the last 30 minutes, in this tree or another worktree of the repository. Advisory by default; `editGuard.mode` can be `ask` or `block`.
|
|
16
|
+
- **secrets-guard** (off by default, on in `strict`) blocks showing `.env` files, private keys, cloud and registry credentials, and the whole environment to the model, through the Read and Grep tools or a shell command. `.env.example`, `ls ~/.ssh`, `.pub` files and appending to `.env` pass.
|
|
17
|
+
- **Codex, Gemini CLI, Copilot CLI, Cursor, Windsurf, Droid, Devin, Cline, opencode and Amp.** `bulkhead setup <agent> --write` registers the same guards in that agent's hook config, with a backup of the original. Their CLI sessions count as sessions for port-guard, checkout-guard and `bulkhead status`.
|
|
18
|
+
- **`bulkhead status` and `top`** show a `STATE` column (working, waiting for you, waiting for a permission) and a `BRANCH` column, the session and project of each queued job, and duplicate MCP servers that several sessions start. A `notify.command` runs when a session starts waiting for you.
|
|
19
|
+
- **`bulkhead doctor`** has an Enforcement section: it runs a harmless command through each guard and shows the block and how long it took, and finds settings that switch the hooks off, duplicate installs and a `node` missing from the hooks' `PATH`.
|
|
20
|
+
- **`bulkhead scan --share`** prints a short summary with counts only, for a post or a chat. `--explain N` shows one hit in full with the part that matched.
|
|
21
|
+
- orphan-reaper keeps processes started with `BULKHEAD_KEEP=1`, SSH tunnels, `cloudflared` and databases, and anything matching `orphanReaper.keepPatterns`. The next session start tells you what it stopped.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- On macOS, free RAM comes from `kern.memorystatus_level` and the memory pressure level instead of a `vm_stat` estimate, which counted far too little as free on a Mac with a lot of file cache. memory-guard blocks heavy commands at pressure level 2 or higher. When neither can be read, heavy commands are let through instead of blocked.
|
|
26
|
+
- More heavy commands are recognised: `xcodebuild`, `swift build` and `swift test`, `fastlane`, `bundle exec`, `go build` and `go test` with `-race` or `./...`, and `nx run|build|test|e2e`.
|
|
27
|
+
- Block messages name the other session by project and branch, and end with the exact config line that would allow the rule.
|
|
28
|
+
- `bulkhead --version`, `bulkhead help <command>` and `<command> --help`; unknown commands and options that need a number are rejected with a clear message.
|
|
29
|
+
- Inside a hook, reading the process table gives up after 4 seconds (8 on Windows) and lets the call through, instead of waiting up to 15 (60).
|
|
30
|
+
- `guards.log` is rotated at 1 MB like `events.jsonl`, and two hooks rotating at the same moment no longer lose the older log.
|
|
31
|
+
|
|
32
|
+
- port-guard knows many more servers, each on its default port: `serve`, `live-server`, `json-server`, `puma`, `gunicorn`, `hypercorn`, `fastapi dev`, Django `runserver`, Streamlit, Jupyter, `trunk`, Metro and React Native, VuePress, VitePress, Phoenix, Parcel, Ember, MkDocs, Hugo, Hexo, Zola, mdBook, Netlify and Vercel dev, Rspack, Rsbuild, Spring Boot and more. It reads the port from `php -S`, `dotnet run --urls`, `--server.port`, `docker run -p` and the `ports:` of a compose file, through `pnpm`, `yarn`, `npm exec`, `bunx`, `uv run`, workspaces and wrappers such as `timeout`, `caffeinate`, `cross-env` and `(cd web && npm run dev &)`. The free-port suggestion uses each tool's own flag.
|
|
33
|
+
- port-guard catches more ways to kill by port: `lsof ... | awk ... | xargs kill` without `-t`, `PID=$(lsof -ti :3000); kill $PID`, loops over `lsof` output, `fkill :3000`, and `netstat`, `ss` and `fuser -n tcp -k` pipelines.
|
|
34
|
+
|
|
35
|
+
- checkout-guard sees more ways to change a shared tree: `git --no-pager add -A` and other global options in front of the subcommand, `git ls-files -m | xargs git add`, `git add $(git ls-files -m)`, `git add "$PWD"` and `*`, `checkout -f`, `stash -a`, `stash drop` and `clear`, `rm -r` of a folder, `restore` or `checkout --` of a folder with uncommitted changes, `cherry-pick`, `revert`, `am`, `apply`, `reset --merge` and `--keep`, and a mixed `reset` over staged files. `rm -rf ./*`, `rm -rf .git` and `find . -delete` count as removing a folder another session works in. Each `cd` in the command is followed, so `cd /tmp/x && rm -rf ./*` passes.
|
|
36
|
+
- New basics rule **`protected-delete`** blocks deleting a protected branch: `git push origin :main`, `git push --delete origin main`, `git branch -D main`. `git branch -d` passes, because git itself refuses to lose unmerged work.
|
|
37
|
+
- checkout-guard compares a session file's start time with the process's, so a reused PID no longer counts as a live session.
|
|
38
|
+
|
|
39
|
+
- kill-guard sees through more indirection: `echo pkill node | sh`, `source <(...)`, `bash <(...)`, `eval "$(...)"`, `xargs pkill`, `busybox`, shell functions and variables (`cmd=pkill; $cmd node`), `tmux`, `screen`, `script`, `parallel`, shell commands that python, node, perl, ruby or php run from a string, and `ssh localhost`. Dev-server and tool names (`next-server`, `uvicorn`, `gunicorn`, `rails`, `expo`, `metro`, `tsc`, `playwright`, Google Chrome and its helpers) are on the shared list, versions included (`node22`, `python3.11`), and so are other coding agents (`codex`, `gemini`, `copilot`, `cursor-agent`).
|
|
40
|
+
- While another Claude session is alive, kill-guard also blocks: `kill <pid>`, `taskkill /PID` and `Stop-Process -Id` of a process in another session's tree; `pkill -f <path>` that matches another session's command line; `pkill -u`, `kill -1` and `kill 0`; `docker ... $(docker ps -q)`, `docker system prune`, `pm2 kill` and `docker compose down` in another session's project; `adb kill-server`, `adb emu kill` without a serial and `simctl shutdown all`; quitting shared apps (Slack, Finder, Dock) and stopping shared services (`brew services stop`, `launchctl bootout`, `systemctl stop`). Each rule has its own switch: `killGuard.massKill`, `dockerMass`, `deviceKill`, `appQuit`, `serviceStop` and `ownerCheck`. The process table is read only for these commands.
|
|
41
|
+
- kill-guard messages are two lines: who owns what you were about to stop, and the command that stops only yours.
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- checkout-guard lets these through: `git add -A src` and other stage-all forms with a path, `git add -n`, `git stash push -- <paths>`, `--help` of any git command, and single-file `restore`. In a sample of 20,000 real commands in a shared, dirty tree, it blocked 1,432 instead of 1,962; the 39 newly blocked ones were all tree-changing commands.
|
|
46
|
+
- basics advice for `git clean` no longer suggests `git stash push -u`, which checkout-guard blocks in a shared tree.
|
|
47
|
+
- port-guard no longer reads quoted text as a command: `grep -E "next dev|vite"` and `ps | grep -E 'next start|playwright'` pass, as do `vite --version`, `vite build` and any tool run with `--help`. Heredoc bodies fed to python, node or cat are data, not commands. In 160,288 real commands from transcripts, it blocked 12 instead of 28 under the same conditions, and every one of the 12 was a real conflict.
|
|
48
|
+
- A heredoc is shell code only when a shell reads it (`bash <<EOF`, `cat <<EOF | sh`, `ssh localhost bash`). Bodies fed to `while read`, `git`, `psql` or a script are data; bodies fed to python or node are read in that language. In 161,188 real commands, kill-guard blocked 4 instead of 14 when no other session ran, and wait-guard blocked 1,009 instead of 1,123 at a 10-minute timeout, with no new blocks.
|
|
49
|
+
- wait-guard reads python `time.sleep` and node `sleep`/`setTimeout` waits inside heredocs in their own units, ignores them inside strings and comments, and no longer multiplies a script's waits by an earlier shell loop.
|
|
50
|
+
- `pkill -f "ssh -N -L 9333"` and other specific `-f` patterns pass; `pkill -f server` and `pkill -f "next dev"` still block.
|
|
51
|
+
- Claude Code sessions started by the macOS desktop app were not seen as sessions.
|
|
52
|
+
- `bulkhead doctor` reported the plugin as installed when run through `npx` from an unrelated copy.
|
|
53
|
+
|
|
3
54
|
## 0.2.2 - 2026-11-11
|
|
4
55
|
|
|
5
56
|
### Fixed
|
package/README.es.md
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
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
5
|
</p>
|
|
6
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
|
|
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.</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">Windows, macOS y Linux. Sin tmux, sin sudo, sin daemon en segundo plano, sin llamadas de red, sin dependencias. También protege a Codex, Gemini CLI, Copilot CLI, Cursor y otros 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="tests"></a>
|
|
@@ -34,7 +36,14 @@ Después, mira qué habría detenido en tu último mes, sin cambiar nada:
|
|
|
34
36
|
/bulkhead:scan 30d
|
|
35
37
|
```
|
|
36
38
|
|
|
37
|
-
Node 18 o superior debe estar en el `PATH` (el instalador nativo de Claude Code no lo instala; compruébalo con `node --version`).
|
|
39
|
+
Node 18 o superior debe estar en el `PATH` (el instalador nativo de Claude Code no lo instala; compruébalo con `node --version`).
|
|
40
|
+
|
|
41
|
+
| Instalación | Qué obtienes |
|
|
42
|
+
|---|---|
|
|
43
|
+
| El plugin (arriba) | Los guards, que se ejecutan en cada llamada a Bash, PowerShell, Read y Edit; los slash commands `/bulkhead:scan`, `status`, `log`, `doctor`, `reap`, `remote`; la skill que enseña a Claude los hábitos seguros. Esta es la parte que te protege. |
|
|
44
|
+
| `npm install -g claude-bulkhead` (opcional) | El comando `bulkhead` en tu propia terminal (`status`, `top`, `explain`, `allow`, `worktree`, `scan`, `doctor`), la línea de estado, `bulkhead-slot` y `bulkhead setup <agent>` para Codex, Gemini y los demás. `npx claude-bulkhead status` funciona sin instalar. |
|
|
45
|
+
|
|
46
|
+
¿No sabes si funciona? `bulkhead doctor` ejecuta un comando inofensivo a través de cada guard y muestra que fue bloqueado, y cuánto tardó.
|
|
38
47
|
|
|
39
48
|
## Qué detiene
|
|
40
49
|
|
|
@@ -42,7 +51,7 @@ Node 18 o superior debe estar en el `PATH` (el instalador nativo de Claude Code
|
|
|
42
51
|
|---|---|
|
|
43
52
|
| 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
53
|
| 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.
|
|
54
|
+
| 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. |
|
|
46
55
|
| 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
56
|
|
|
48
57
|
<details>
|
|
@@ -87,7 +96,7 @@ No hace falta adivinar. Claude Code guarda la transcripción de cada sesión en
|
|
|
87
96
|
/bulkhead:scan 30d
|
|
88
97
|
```
|
|
89
98
|
|
|
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).
|
|
99
|
+
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. `bulkhead scan --share` imprime un resumen de 5 a 8 líneas con solo recuentos (sin rutas ni comandos) que puedes pegar en una publicación o en un chat, y `--explain 1` muestra un ejemplo completo con la parte que coincidió. Detalles: [docs/commands.md](docs/commands.md#bulkhead-scan).
|
|
91
100
|
|
|
92
101
|
## Por qué existe
|
|
93
102
|
|
|
@@ -115,10 +124,13 @@ claude-bulkhead es un conjunto de pequeños hooks que bloquean o limpian cada un
|
|
|
115
124
|
|---|---|
|
|
116
125
|
| **[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
126
|
| **[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)
|
|
127
|
+
| **[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. Para conservar uno a propósito, usa `BULKHEAD_KEEP=1`; los túneles y las bases de datos ya se conservan. |
|
|
128
|
+
| **[disk-guard](docs/guards/disk-guard.md)**<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)**<br>Repite tus transcripciones pasadas de Claude Code contra los guards: qué habrían detenido y cuántas sesiones corrieron a la vez. |
|
|
120
129
|
| **[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
|
-
| **[
|
|
130
|
+
| **[edit-guard](docs/guards/edit-guard.md)** <sup>new</sup><br>Avisa al agente cuando otra sesión activa editó el mismo archivo en los últimos 30 minutos, en este árbol o en otro worktree del repositorio. Solo informa por defecto, sin servidor. | **[secrets-guard](docs/guards/secrets-guard.md)** <sup>new, off by default</sup><br>Bloquea leer o imprimir `.env`, claves privadas, credenciales de la nube y todo el entorno, con la herramienta Read o con un comando de shell, mientras que `.env.example`, `ls ~/.ssh` y los archivos `.pub` pasan. |
|
|
131
|
+
| **[`bulkhead explain` y `bulkhead allow`](#cuando-bloquea-algo-que-querías)** <sup>new</sup><br>Ve qué diría cada guard sobre un comando antes de ejecutarlo, y deja pasar una vez un comando bloqueado con el código del mensaje de bloqueo. Claude no puede aprobar sus propios bloqueos. | **[`bulkhead worktree`](#worktrees-en-un-solo-paso)** <sup>new</sup><br>Un worktree nuevo en un solo paso, con tus archivos `.env` copiados, las dependencias instaladas y su propio puerto estable; `prune` elimina los ya fusionados, incluidos los squash merges, y nunca uno en el que trabaja una sesión. |
|
|
132
|
+
| **[Auto-queue](docs/commands.md#auto-queue)** <sup>new</sup><br>Con `memoryGuard.autoQueue`, los comandos pesados no se rechazan, sino que se ponen en fila: el hook los envuelve en `bulkhead-slot` y empiezan cuando hay espacio. | **[Codex, Gemini y otros agentes](#codex-gemini-y-otros-agentes)** <sup>new</sup><br>Los mismos guards para Codex, Gemini CLI, Copilot CLI, Cursor, Windsurf, Droid, Devin, Cline, opencode y Amp, configurados con `bulkhead setup <agent>`. |
|
|
133
|
+
| **[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 unos 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
134
|
|
|
123
135
|
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
136
|
|
|
@@ -132,14 +144,29 @@ Una ejecución guionizada de `bulkhead status`, port-guard, kill-guard y wait-gu
|
|
|
132
144
|
|
|
133
145
|
1. Instala el plugin como se indica arriba y abre una sesión nueva de Claude Code.
|
|
134
146
|
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.
|
|
147
|
+
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. La sección Enforcement del final demuestra que los hooks bloquean: ejecuta el hook instalado con un comando canario y comprueba el código de salida, el mensaje y la latencia, y avisa de `disableAllHooks`, de un plugin desactivado o de que falta `node`.
|
|
136
148
|
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
149
|
|
|
138
150
|
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
151
|
|
|
152
|
+
## Worktrees en un solo paso
|
|
153
|
+
|
|
154
|
+
Cuando otra sesión trabaja en tu árbol, checkout-guard envía al agente a un worktree. Un worktree normal no tiene `.env`, ni `node_modules`, y usa el mismo puerto de dev server que el checkout principal. `bulkhead worktree add` resuelve esas tres cosas:
|
|
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
|
+
Copia los archivos indicados en `.worktreeinclude` (el archivo que Claude Code también lee) o un conjunto seguro por defecto de archivos `.env`, nunca `node_modules`, la salida de builds ni nada que pese más de 5 MB; instala con el lockfile del proyecto; y le da al worktree un puerto que es el mismo cada vez. `bulkhead worktree list` muestra cada worktree con su rama, estado, sesión activa y puerto. `bulkhead worktree prune` lista los que están fusionados, limpios y sin uso, y los elimina con `--yes` mediante `git worktree remove` y `git branch -d`, nunca con `--force`, y nunca la carpeta de una sesión activa. Detalles en [docs/commands.md](docs/commands.md#bulkhead-worktree).
|
|
166
|
+
|
|
140
167
|
## Ejecutar trabajos pesados en otra máquina (opcional)
|
|
141
168
|
|
|
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.
|
|
169
|
+
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 (automáticamente, con `memoryGuard.autoQueue`). Si tienes una segunda máquina que está casi siempre libre, `bulkhead remote` ejecuta allí el comando pesado.
|
|
143
170
|
|
|
144
171
|
<p align="center">
|
|
145
172
|
<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%">
|
|
@@ -209,12 +236,14 @@ Desactivar: `BULKHEAD_DISABLE=port-guard`. Detalles: [docs/guards/port-guard.md]
|
|
|
209
236
|
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
237
|
|
|
211
238
|
Desactivar: `BULKHEAD_DISABLE=memory-guard`. Detalles: [docs/guards/memory-guard.md](docs/guards/memory-guard.md).
|
|
239
|
+
|
|
240
|
+
Con `"memoryGuard": { "autoQueue": true }`, nadie tiene que acordarse del slot: memory-guard reescribe cada comando pesado (pruebas, builds, ejecuciones de navegador, builds de contenedores) para que se ejecute a través de `bulkhead-slot`, de modo que todas las sesiones esperan en una única cola justa en lugar de ser bloqueadas. Un trabajo en espera imprime su posición cada 30 segundos, y `bulkhead status` muestra a qué sesión y proyecto pertenece cada trabajo en cola. Con `"memoryGuard": { "subagents": true }`, no se inicia un subagente nuevo mientras la presión de memoria sea crítica. Consulta [docs/commands.md](docs/commands.md#auto-queue).
|
|
212
241
|
</details>
|
|
213
242
|
|
|
214
243
|
<details>
|
|
215
244
|
<summary><strong>checkout-guard</strong>: dos sesiones en un mismo árbol de git</summary>
|
|
216
245
|
|
|
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.
|
|
246
|
+
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`; `git add -A src/` y `git add -n` pasan), 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
247
|
|
|
219
248
|
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
249
|
</details>
|
|
@@ -238,19 +267,30 @@ Desactivar: `BULKHEAD_DISABLE=wait-guard`, o sube el límite con `BULKHEAD_WAIT_
|
|
|
238
267
|
<details>
|
|
239
268
|
<summary><strong>orphan-reaper</strong>: procesos que dejan las sesiones que terminaron</summary>
|
|
240
269
|
|
|
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
|
|
270
|
+
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é. Lo que lanzaste a propósito para que siga activo se conserva con `BULKHEAD_KEEP=1 <command>` (los túneles ssh, cloudflared, ngrok, Jupyter, Redis, Postgres, MySQL, MongoDB y Docker se conservan sin ello), y la siguiente sesión te dice en una línea qué se detuvo. Windows, Linux y macOS (macOS probado en un Mac real).
|
|
242
271
|
|
|
243
272
|
Desactivar: `BULKHEAD_DISABLE=orphan-reaper`. Detalles: [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 errores que no se pueden deshacer</summary>
|
|
248
277
|
|
|
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).
|
|
278
|
+
`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), `protected-delete` (`git push origin :main`, `git push --delete origin main`, `git branch -D main`), `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
279
|
|
|
251
280
|
Desactivar: `BULKHEAD_DISABLE=basics`, o una sola regla por su nombre. Detalles: [docs/guards/basics.md](docs/guards/basics.md).
|
|
252
281
|
</details>
|
|
253
282
|
|
|
283
|
+
## Codex, Gemini y otros agentes
|
|
284
|
+
|
|
285
|
+
Si usas Codex CLI, Gemini CLI, Copilot CLI, Cursor, opencode, Amp, Cline, Factory Droid, Windsurf o Devin en la misma máquina que Claude Code, bulkhead protege sus comandos de shell con los mismos guards y cuenta sus sesiones: el dev server de un agente queda protegido frente a los demás, y `bulkhead status` gana una columna `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
|
+
`bulkhead setup <agent>` funciona con `codex`, `gemini`, `copilot`, `cursor`, `windsurf`, `droid`, `devin`, `cline`, `opencode` y `amp`. Cada agente llama a `bulkhead hook --agent <name>` antes de un comando de shell y recibe de vuelta el bloqueo en su propio formato. Los agentes, los archivos de configuración, lo que se protege y la documentación con la que se comprobó cada fila están en [docs/other-agents.md](docs/other-agents.md).
|
|
293
|
+
|
|
254
294
|
## Cómo se relaciona bulkhead con otros paquetes de hooks
|
|
255
295
|
|
|
256
296
|
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.
|
|
@@ -283,7 +323,8 @@ Las variables de entorno siguen funcionando y tienen prioridad sobre ambos archi
|
|
|
283
323
|
|
|
284
324
|
| Variable | Valor por defecto | Equivale a |
|
|
285
325
|
|---|---|---|
|
|
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 |
|
|
326
|
+
| `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`, `protected-delete`, `discard-changes`, `agent-author`, `stage-all`, `remove-session-dir`. Un nombre aquí queda desactivado digan lo que digan los archivos |
|
|
327
|
+
| `BULKHEAD_PRESET` | `normal` | El preset: `quiet`, `normal` o `strict` |
|
|
287
328
|
| `BULKHEAD_WAIT_MAX_SEC` | 180 | `waitGuard.limitSeconds` |
|
|
288
329
|
| `BULKHEAD_MIN_FREE_GB` | 3, o el 15 % de la RAM si es menos | `memory.minFreeGb` |
|
|
289
330
|
| `BULKHEAD_SLOT_FLOOR_GB` | 5, o el 25 % de la RAM si es menos | `memory.slotFloorGb` |
|
|
@@ -294,32 +335,68 @@ Las variables de entorno siguen funcionando y tienen prioridad sobre ambos archi
|
|
|
294
335
|
|
|
295
336
|
</details>
|
|
296
337
|
|
|
338
|
+
## Cuando bloquea algo que querías
|
|
339
|
+
|
|
340
|
+
Un bloqueo es una pregunta, no un veredicto. Hay tres salidas, de la más pequeña a la más amplia:
|
|
341
|
+
|
|
342
|
+
1. Permitirlo una vez. Cada mensaje de bloqueo termina con un código corto. En tu propia terminal, ejecuta `bulkhead allow 7F3K`. La siguiente llamada idéntica del agente (mismo comando, misma carpeta) pasa, una sola vez, dentro de 10 minutos. El agente no puede hacerlo por ti: bulkhead bloquea cualquier intento de ejecutar `bulkhead allow` o de escribir sus archivos de estado.
|
|
343
|
+
2. Ver primero el motivo. `bulkhead explain -- <command>` pasa el comando por cada guard contra las sesiones, los puertos y el árbol de git en vivo, sin ejecutarlo, e imprime quién es el dueño de lo que estorba, el mensaje exacto que ve el agente y cómo permitirlo.
|
|
344
|
+
3. Permitirlo para siempre, o cambiar cuánto bloquea. Pon la regla en `.claude/bulkhead.json` (la tabla de abajo), o elige un preset: `bulkhead config --preset quiet` conserva solo los guards entre sesiones y las dos reglas que no se pueden deshacer, `strict` activa todo con límites más estrictos, y `normal` es el valor por defecto. Tus propias claves y variables de entorno tienen prioridad sobre un preset.
|
|
345
|
+
|
|
346
|
+
### ¿Bloqueó algo que querías? Guía rápida
|
|
347
|
+
|
|
348
|
+
La vía de una sola vez es siempre `bulkhead allow <code>`, ejecutada por ti. La vía permanente, para la regla que se activó:
|
|
349
|
+
|
|
350
|
+
| Guard | Regla | Permanente, en `.claude/bulkhead.json` |
|
|
351
|
+
|---|---|---|
|
|
352
|
+
| kill-guard | `pkill`, `taskkill-im`, `stop-process-name` y las demás formas de matar por nombre | `{"killGuard":{"allowNames":["ffmpeg"]}}` |
|
|
353
|
+
| kill-guard | `other-session-pid`: un PID del árbol de otra sesión | `{"killGuard":{"ownerCheck":false}}` |
|
|
354
|
+
| kill-guard | `mass-kill`, `docker-mass`, `device-kill`, `app-quit`, `service-stop`: las demás reglas (solo mientras corre otra sesión) | `{"killGuard":{"massKill":false}}`, y así con las demás (`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` y los demás cambios de árbol | `{"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` | no se puede permitir una vez; solo tú puedes aprobarlo |
|
|
368
|
+
|
|
369
|
+
El mismo interruptor como variable de entorno es `BULKHEAD_DISABLE=<nombre del guard o de la regla>`. Todo está en [docs/configuration.md](docs/configuration.md) y [docs/commands.md](docs/commands.md).
|
|
370
|
+
|
|
297
371
|
## Ver qué se está ejecutando
|
|
298
372
|
|
|
299
373
|
`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
374
|
|
|
301
375
|
### bulkhead status
|
|
302
376
|
|
|
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,
|
|
377
|
+
Cada sesión de Claude Code de la máquina: qué está haciendo (trabajando, esperándote, necesita permiso), su rama de git y si es un worktree, 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, la RAM libre y los servidores MCP que corren como varias copias entre sesiones:
|
|
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
|
+
`bulkhead top` pone primero las sesiones que te necesitan. `bulkhead port --stable` imprime un puerto que pertenece al worktree de git actual y es el mismo cada vez. Para recibir una notificación de escritorio cuando una sesión empieza a esperar, define `notify.command` ([commands.md](docs/commands.md#session-state-and-notifications)).
|
|
399
|
+
|
|
323
400
|
`bulkhead slot ...` es lo mismo que `bulkhead-slot ...`.
|
|
324
401
|
|
|
325
402
|
### bulkhead top
|
|
@@ -374,31 +451,44 @@ PROJECT COUNT
|
|
|
374
451
|
|
|
375
452
|
### bulkhead doctor
|
|
376
453
|
|
|
377
|
-
Comprueba Node, los archivos del plugin, el directorio de estado, los archivos de configuración, cada guard (activo o desactivado, y por qué),
|
|
454
|
+
Comprueba Node, los archivos del plugin, el directorio de estado, los archivos de configuración, cada guard (activo o desactivado, y por qué), 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. Después, una sección Enforcement demuestra que los hooks instalados bloquean: la instalación y `enabledPlugins`, las instalaciones duplicadas, los ajustes que desactivan los hooks, `node` en el `PATH` del hook, y una ejecución real del comando de hook de cada guard contra un canario, con su latencia. El código de salida es 1 si falla alguna comprobación.
|
|
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 @@ would stop 30112 test-runner node ~/src/acme-web/node_modules/vitest/dist/work
|
|
|
428
518
|
3 sessions 2 heavy 9.1 GB free
|
|
429
519
|
```
|
|
430
520
|
|
|
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
|
|
521
|
+
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. Cuando hay sesiones esperándote, la línea añade `2 waiting` después del número de sesiones. No lista todos los procesos (un solo `ps` solo para los pids de sesión), tarda unos 100 ms en frío en un Mac con 650 procesos y guarda la línea en caché durante 5 segundos en el directorio de estado, escrita a través de un archivo temporal para que las sesiones concurrentes nunca lean la mitad.
|
|
432
522
|
|
|
433
523
|
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
524
|
|
|
@@ -447,7 +537,7 @@ Esto requiere `npm install -g claude-bulkhead`, que pone `bulkhead-statusline` e
|
|
|
447
537
|
## Preguntas frecuentes
|
|
448
538
|
|
|
449
539
|
**¿Ralentiza Claude Code?**
|
|
450
|
-
Un poco.
|
|
540
|
+
Un poco. Todos los guards de Bash se ejecutan en un único proceso corto de Node sin dependencias, unos 76 ms por llamada a una herramienta en un MacBook Pro (Node 24), de los cuales 32 ms son el arranque de Node. Cuando 10 sesiones llaman a una herramienta en el mismo instante, cada una espera unos 89 ms (318 ms cuando cada guard era un proceso propio, como en la 0.2). 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 unos 100 ms en frío y se guarda en caché durante 5 segundos.
|
|
451
541
|
|
|
452
542
|
**Ha bloqueado algo que no debía. ¿Qué hago?**
|
|
453
543
|
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.
|
|
@@ -456,7 +546,7 @@ Ejecuta `bulkhead log` para ver el comando exacto y el motivo. Déjalo pasar en
|
|
|
456
546
|
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
547
|
|
|
458
548
|
**¿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`
|
|
549
|
+
Windows, Linux y macOS, con Node 18 o superior. orphan-reaper en macOS está probado con fixtures de la salida de `ps` y en un Mac real (se terminó una sesión de relleno y solo se detuvieron sus restos), 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
550
|
|
|
461
551
|
**¿Envía algo a algún sitio?**
|
|
462
552
|
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.
|
|
@@ -477,6 +567,8 @@ Hay más preguntas, incluidas cómo se pueden eludir los guards y cómo se miden
|
|
|
477
567
|
/plugin marketplace remove bulkhead
|
|
478
568
|
```
|
|
479
569
|
|
|
570
|
+
Si en su lugar instalaste el paquete de npm, ejecuta `npm uninstall -g claude-bulkhead`. Un proceso de espera de SessionEnd que ya esté en marcha termina por sí solo en menos de 3 minutos, así que no queda nada ejecutándose después de desinstalar.
|
|
571
|
+
|
|
480
572
|
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
573
|
|
|
482
574
|
## ¿Usas bulkhead? Muéstralo
|