@plumpslabs/fennec-cli 1.14.2 → 1.14.4

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/README.md CHANGED
@@ -57,6 +57,7 @@ pnpm build
57
57
  ```
58
58
 
59
59
  Browser engines (optional for source install):
60
+
60
61
  ```bash
61
62
  pnpm add playwright
62
63
  npx playwright install chromium
@@ -126,7 +127,7 @@ Connect remote MCP clients with `{ "type": "remote", "url": "http://127.0.0.1:33
126
127
 
127
128
  ### 4. Ask your AI to diagnose issues
128
129
 
129
- > *"Why is my app broken?"* — AI uses Fennec to check browser console, network, and server logs simultaneously.
130
+ > _"Why is my app broken?"_ — AI uses Fennec to check browser console, network, and server logs simultaneously.
130
131
 
131
132
  ## CLI Commands
132
133
 
@@ -134,35 +135,38 @@ Fennec is both an MCP server **and** a CLI you can use directly in your terminal
134
135
 
135
136
  ### Server
136
137
 
137
- | Command | Description |
138
- |---------|-------------|
139
- | `fennec start` | Start the MCP server (stdio transport). Default when no app command is given. |
140
- | `fennec start --sse` | Start the MCP server over HTTP+SSE (experimental). |
141
- | `fennec start --transport sse` | Alias of `--sse`. |
138
+ | Command | Description |
139
+ | ------------------------------ | ----------------------------------------------------------------------------- |
140
+ | `fennec start` | Start the MCP server (stdio transport). Default when no app command is given. |
141
+ | `fennec start --sse` | Start the MCP server over HTTP+SSE (experimental). |
142
+ | `fennec start --transport sse` | Alias of `--sse`. |
142
143
 
143
144
  ### Apps & Processes
144
145
 
145
- | Command | Description |
146
- |---------|-------------|
147
- | `fennec start <command> --name <name> [options]` | Launch an app as a supervised background daemon. Alias: `run`. |
148
- | `fennec ps [options]` | List Fennec-tracked apps with live status. |
149
- | `fennec status [name]` | System overview + top processes (tracked and system). |
150
- | `fennec log <name\|pid> [options]` | Show (and follow) logs for a tracked app. |
151
- | `fennec spawn [name] [--all]` | Re-spawn a stopped tracked app from its saved config. |
152
- | `fennec stop <name\|--all>` | Stop (pause) a tracked app but keep it in the registry. Add `-y/--yes` to skip the confirmation prompt. |
153
- | `fennec restart <name\|pid>` | Stop and re-spawn a tracked app from its saved config. |
154
- | `fennec kill <pid\|name\|all>` | Kill a process and remove it from the registry. Add `-y/--yes` to skip the confirmation prompt. |
155
- | `fennec adopt <pid> [--name <name>] [--port <port>]` | Adopt an externally-started process into Fennec tracking. |
156
- | `fennec supervisor <start\|stop\|restart\|status>` | Manage the background supervisor that keeps `--restart` apps alive. |
157
- | `fennec persist <enable\|disable\|status>` | Survive reboots auto-start tracked apps after login (systemd/launchd/Windows). |
158
- | `fennec dev <up\|down\|status\|restart <app>>` | Orchestrate a whole dev stack from `fennec.config.yaml`. |
159
- | `fennec inspect <name\|pid>` | Compact, AI-safe snapshot (status + recent logs + error scan). |
160
- | `fennec info <name>` | Detailed info for a tracked app. |
161
- | `fennec rename <old> <new>` | Rename a tracked app. |
162
-
163
- **`start` / `run` options:** `--name <name>` (recommended), `--port <port>` (Fennec waits until it accepts connections), `--cwd <dir>`, `--restart` (auto-restart on crash / port-down, survives terminal close), `--jsonl` (structured JSON-lines logs).
164
-
165
- **`ps` options:** `-w/--watch` (live refresh), `--system/-a/--all` (include non-Fennec system processes), `--json`, `--name <filter>`, `--sort <cpu|mem|pid|name>`.
146
+ | Command | Description |
147
+ | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
148
+ | `fennec start <command> --name <name> [options]` | Launch an app as a supervised background daemon. Alias: `run`. |
149
+ | `fennec ps [options]` | List Fennec-tracked apps with live status. |
150
+ | `fennec status [name]` | System overview + top processes (tracked and system). |
151
+ | `fennec log <name\|pid> [options]` | Show (and follow) logs for a tracked app. |
152
+ | `fennec spawn [name] [name...] [--all]` | Re-spawn a stopped tracked app from its saved config. Accepts MULTIPLE names at once. |
153
+ | `fennec stop <name\|--all> [name...]` | Stop (pause) a tracked app but keep it in the registry. Accepts MULTIPLE names. Add `-y/--yes` to skip the confirmation prompt. |
154
+ | `fennec restart <name\|pid> [name...]` | Stop and re-spawn a tracked app from its saved config. Accepts MULTIPLE names at once. |
155
+ | `fennec kill <pid\|name\|all> [name...]` | Kill a process and remove it from the registry. Accepts MULTIPLE names at once. Add `-y/--yes` to skip the confirmation prompt. |
156
+ | `fennec group [name] [group]` | Assign a logical group to tracked apps (or list them). Bulk: `fennec group <group> <name...>`. `--unset` to clear. Group is preserved across `spawn`/`restart`. |
157
+ | `fennec adopt <pid> [--name <name>] [--port <port>]` | Adopt an externally-started process into Fennec tracking. |
158
+ | `fennec supervisor <start\|stop\|restart\|status>` | Manage the background supervisor that keeps `--restart` apps alive. |
159
+ | `fennec persist <enable\|disable\|status>` | Survive reboots auto-start tracked apps after login (systemd/launchd/Windows). |
160
+ | `fennec dev <up\|down\|status\|restart <app>>` | Orchestrate a whole dev stack from `fennec.config.yaml`. |
161
+ | `fennec inspect <name\|pid>` | Compact, AI-safe snapshot (status + recent logs + error scan). |
162
+ | `fennec info <name>` | Detailed info for a tracked app. |
163
+ | `fennec rename <old> <new>` | Rename a tracked app. |
164
+
165
+ **`start` / `run` options:** `--name <name>` (recommended), `--port <port>` (Fennec waits until it accepts connections), `--cwd <dir>`, `--restart` (auto-restart on crash / port-down, survives terminal close), `--group <group>` (tag for scoped bulk ops), `--jsonl` (structured JSON-lines logs).
166
+
167
+ **`ps` options:** `-w/--watch` (live refresh), `--system/-a/--all` (include non-Fennec system processes), `--json`, `--name <filter>`, `--group <g>` (show only apps in group `<g>`), `--sort <cpu|mem|pid|name>`. The `MEM` column shows each running app's resident memory (RSS) cross-platform, so you can spot leaks from long-lived apps.
168
+
169
+ **Logical groups + bulk (multiple names):** tag apps with `fennec start <cmd> --name <n> --group <g>`, or retroactively with `fennec group <name> <g>` (existing entries too — `fennec group <name> --unset` clears). You can ALSO assign a group to MANY apps at once (bulk): `fennec group <group> <name1> <name2> ...` — e.g. `fennec group crm be-crm fe-crm` tags all three as `crm` in one shot (alternatively `fennec group --group crm be-crm fe-crm`). Then scope bulk ops to just that group: `fennec kill --group <g>`, `fennec stop --group <g>`, `fennec spawn --group <g>`, `fennec restart --group <g>`, `fennec ps --group <g>`. A bare group name as the positional (e.g. `fennec kill <g>`) is also accepted as shorthand. You can ALSO pass MULTIPLE names at once for one-shot bulk ops: `fennec stop be-crm fe-crm`, `fennec kill be-crm fe-crm -y`, `fennec restart be-crm fe-crm -y`, `fennec spawn be-crm fe-crm`. The group is PRESERVED across `spawn`/`restart` (stop→resume keeps the tag). Already-running entries in scope are reported as "already running" (never double-spawned); `--all` still targets **every** tracked app across all groups.
166
170
 
167
171
  **`log` options:** `-f/--follow`, `--lines N`, `--since 10m|1h|2d`, `--level error|warn|info|debug`, `--json` (bounded, redacted, machine-readable for AI), `--no-redact`, `--clear`.
168
172
 
@@ -170,32 +174,47 @@ Fennec is both an MCP server **and** a CLI you can use directly in your terminal
170
174
 
171
175
  ### Observation
172
176
 
173
- | Command | Description |
174
- |---------|-------------|
175
- | `fennec attach <port>` | Observe a running process by the port it listens on. |
176
- | `fennec attach-pid <pid>` | Attach to and observe a process by its PID. |
177
- | `fennec attach-port <port>` | Attach to and observe a process by its port. |
178
- | `fennec pipe --name <name>` | Pipe stdin into a Fennec log watcher. |
179
- | `fennec watch --file <path>` | Watch an existing log file. |
177
+ | Command | Description |
178
+ | ---------------------------- | ---------------------------------------------------- |
179
+ | `fennec attach <port>` | Observe a running process by the port it listens on. |
180
+ | `fennec attach-pid <pid>` | Attach to and observe a process by its PID. |
181
+ | `fennec attach-port <port>` | Attach to and observe a process by its port. |
182
+ | `fennec pipe --name <name>` | Pipe stdin into a Fennec log watcher. |
183
+ | `fennec watch --file <path>` | Watch an existing log file. |
180
184
 
181
185
  ### Data
182
186
 
183
- | Command | Description |
184
- |---------|-------------|
185
- | `fennec export --file <path>` | Export tracked apps to a file. |
186
- | `fennec import <file>` | Import tracked apps from a file. |
187
- | `fennec cleanup` | Remove dead/stale entries from the tracked registry. |
187
+ | Command | Description |
188
+ | ----------------------------- | ---------------------------------------------------- |
189
+ | `fennec export --file <path>` | Export tracked apps to a file. |
190
+ | `fennec import <file>` | Import tracked apps from a file. |
191
+ | `fennec cleanup` | Remove dead/stale entries from the tracked registry. |
192
+
193
+ ### Store & Doctor
194
+
195
+ Fennec persists everything — auth sessions, tracked processes, exports, plugin/workflow state — under **one global store**, by default `~/.fennec` (honors `FENNEC_HOME` / `FENNEC_DATA_DIR`), manageable from **any directory**. `--local` targets the per-project `.fennec` instead.
196
+
197
+ | Command | Description |
198
+ | ---------------------------------- | ------------------------------------------------------------------------------------------------------------ |
199
+ | `fennec store` | Overview of everything in the global store (counts, size, age). |
200
+ | `fennec store --local` | Same, for the project `.fennec`. |
201
+ | `fennec store session` | List saved auth sessions. |
202
+ | `fennec store session info <name>` | Show a session — cookie/localStorage **values are masked**; add `--show-secrets` to reveal. |
203
+ | `fennec store session rm <name>` | Delete a session (confirm prompt). |
204
+ | `fennec doctor` | Health + secret-surface checks: store permissions, synced-home leakage, embedded secrets in launch commands. |
188
205
 
189
206
  ### Configuration & Misc
190
207
 
191
- | Command | Description |
192
- |---------|-------------|
193
- | `fennec init` | Generate a `fennec.config.yaml` in the current directory. |
194
- | `fennec setup` | Interactively configure your MCP client for Fennec. |
195
- | `fennec install-browsers` | Install Playwright browser engines. |
196
- | `fennec sessions` | List saved browser auth sessions. |
197
- | `fennec health` | Health check of the Fennec environment. |
198
- | `fennec help [command]` | Show help, or detailed help for a command. |
208
+ | Command | Description |
209
+ | ------------------------- | -------------------------------------------------------------------------- |
210
+ | `fennec init` | Generate a `fennec.config.yaml` in the current directory. |
211
+ | `fennec setup` | Interactively configure your MCP client for Fennec. |
212
+ | `fennec install-browsers` | Install Playwright browser engines. |
213
+ | `fennec sessions` | List saved browser auth sessions (alias of `fennec store session`). |
214
+ | `fennec store` | Unified view of everything Fennec persists (sessions, processes, exports). |
215
+ | `fennec doctor` | Health + secret-surface checks for the store. |
216
+ | `fennec health` | Health check of the Fennec environment. |
217
+ | `fennec help [command]` | Show help, or detailed help for a command. |
199
218
 
200
219
  ## Usage Examples
201
220
 
@@ -217,7 +236,7 @@ fennec log web -f
217
236
 
218
237
  `fennec dev up` reads `fennec.config.yaml` and brings the whole stack up. It is
219
238
  **idempotent**: already-running apps with unchanged config are skipped, apps whose
220
- config changed are restarted, and an app whose port is already taken by *another*
239
+ config changed are restarted, and an app whose port is already taken by _another_
221
240
  process is **adopted** instead of spawning a conflicting duplicate.
222
241
 
223
242
  ```bash
@@ -227,6 +246,28 @@ fennec dev restart web # restart just one app
227
246
  fennec dev down # stop everything (keeps it in the registry)
228
247
  ```
229
248
 
249
+ ### Bulk operations & groups
250
+
251
+ ```bash
252
+ # Tag apps into groups when starting (or retroactively with `fennec group`)
253
+ fennec start "npm run dev-be" --name be-crm --group crm
254
+ fennec start "npm run dev-fe" --name fe-crm --group crm
255
+
256
+ # One-shot bulk: pass MULTIPLE names at once
257
+ fennec stop be-crm fe-crm # pause both, keep them in the registry
258
+ fennec spawn be-crm fe-crm # re-spawn both paused apps
259
+ fennec kill be-crm fe-crm -y # kill + forget both
260
+ fennec restart be-crm fe-crm -y # restart both from saved config
261
+
262
+ # Group-scoped bulk: only that group is touched (other groups safe)
263
+ fennec kill --group crm -y
264
+ fennec stop --group crm
265
+ fennec ps --group crm # MEM column shows each app's live RSS
266
+
267
+ # Global: --all still hits EVERY tracked app across all groups
268
+ fennec stop --all
269
+ ```
270
+
230
271
  ### Adopt a process an AI agent started via raw bash
231
272
 
232
273
  An AI agent (or you) sometimes launches a server with plain bash. Fennec can take
@@ -272,8 +313,8 @@ Key configuration options (see [full reference](../../docs/configuration.md)):
272
313
 
273
314
  ```yaml
274
315
  browser:
275
- adapter: auto # auto, cdp, or playwright
276
- type: chromium # chromium, firefox, or webkit
316
+ adapter: auto # auto, cdp, or playwright
317
+ type: chromium # chromium, firefox, or webkit
277
318
  headless: true
278
319
  viewport:
279
320
  width: 1280
@@ -281,7 +322,7 @@ browser:
281
322
 
282
323
  process:
283
324
  maxProcesses: 10
284
- spawnAllowlist: # only these commands may be spawned
325
+ spawnAllowlist: # only these commands may be spawned
285
326
  - npm
286
327
  - node
287
328
  - pnpm
@@ -293,13 +334,13 @@ process:
293
334
  security:
294
335
  sandbox: true
295
336
  allowProcessSpawn: true
296
- allowProcessKill: false # off by default — opt in explicitly
337
+ allowProcessKill: false # off by default — opt in explicitly
297
338
  allowJSEvaluation: true
298
339
 
299
340
  lazyContext:
300
- level1: true # Auto-attach summary on errors
301
- level2: false # Attach detail on expand
302
- level3: false # Attach raw data on request
341
+ level1: true # Auto-attach summary on errors
342
+ level2: false # Attach detail on expand
343
+ level3: false # Attach raw data on request
303
344
 
304
345
  correlation:
305
346
  windowMs: 500
@@ -312,20 +353,20 @@ correlation:
312
353
  Fennec ships with **sandbox mode enabled by default** and conservative process
313
354
  permissions. Environment variables override the config file:
314
355
 
315
- | Variable | Effect |
316
- |----------|--------|
317
- | `FENNEC_DATA_DIR` | Override where Fennec stores tracked state & logs (default `~/.fennec`). |
318
- | `FENNEC_SANDBOX` | `false` disables the sandbox (permits more operations). |
319
- | `FENNEC_SECURITY_ALLOW_PROCESS_SPAWN` | `true` allows the AI to spawn new processes. |
320
- | `FENNEC_SECURITY_ALLOW_PROCESS_KILL` | `true` allows the AI to kill processes. |
321
- | `FENNEC_SECURITY_ALLOW_JS_EVALUATION` | `true` allows in-page JS evaluation. |
322
- | `FENNEC_TRANSPORT_TYPE` | `stdio` (default) or `sse`. |
323
- | `FENNEC_PORT` | Port for SSE transport (default `3333`). |
324
- | `FENNEC_BROWSER_TYPE` | `chromium` \| `firefox` \| `webkit`. |
325
- | `FENNEC_HEADLESS` | `false` to run headed. |
326
- | `FENNEC_DEFAULT_TIMEOUT` | Browser default timeout (ms). |
327
- | `FENNEC_VIEWPORT_WIDTH` / `FENNEC_VIEWPORT_HEIGHT` | Viewport size. |
328
- | `FENNEC_LOG_LEVEL` | `debug` \| `info` \| `warn` \| `error`. |
356
+ | Variable | Effect |
357
+ | -------------------------------------------------- | ------------------------------------------------------------------------ |
358
+ | `FENNEC_DATA_DIR` | Override where Fennec stores tracked state & logs (default `~/.fennec`). |
359
+ | `FENNEC_SANDBOX` | `false` disables the sandbox (permits more operations). |
360
+ | `FENNEC_SECURITY_ALLOW_PROCESS_SPAWN` | `true` allows the AI to spawn new processes. |
361
+ | `FENNEC_SECURITY_ALLOW_PROCESS_KILL` | `true` allows the AI to kill processes. |
362
+ | `FENNEC_SECURITY_ALLOW_JS_EVALUATION` | `true` allows in-page JS evaluation. |
363
+ | `FENNEC_TRANSPORT_TYPE` | `stdio` (default) or `sse`. |
364
+ | `FENNEC_PORT` | Port for SSE transport (default `3333`). |
365
+ | `FENNEC_BROWSER_TYPE` | `chromium` \| `firefox` \| `webkit`. |
366
+ | `FENNEC_HEADLESS` | `false` to run headed. |
367
+ | `FENNEC_DEFAULT_TIMEOUT` | Browser default timeout (ms). |
368
+ | `FENNEC_VIEWPORT_WIDTH` / `FENNEC_VIEWPORT_HEIGHT` | Viewport size. |
369
+ | `FENNEC_LOG_LEVEL` | `debug` \| `info` \| `warn` \| `error`. |
329
370
 
330
371
  Security features:
331
372
 
@@ -364,6 +405,18 @@ FENNEC_BROWSER_TYPE=webkit fennec start
364
405
  - [Security Model](https://github.com/plumpslabs/fennec/blob/main/docs/security-model.md)
365
406
  - [GitHub Repository](https://github.com/plumpslabs/fennec)
366
407
 
408
+ ## Memory & Garbage Safety
409
+
410
+ Fennec is built to **not** leak memory or orphan processes on your machine:
411
+
412
+ - 🌳 **Process-tree kills** — `stop`/`kill`/`spawn`/`restart` tear down the _entire_ process tree (npm → vite → esbuild on POSIX; `taskkill /T /F` on Windows), so no orphaned children are left "nyampah".
413
+ - 🧹 **Browser contexts are fully torn down** on session destroy (page **and** its `BrowserContext` — cookies, cache, service workers), not just the page.
414
+ - ⏳ **Idle-session GC** runs on a timer (not only when the session cap is hit): idle sessions and over-TTL sessions are destroyed automatically.
415
+ - 📑 **Tab caps** — opening many tabs (`tab_new` / `context_new`) auto-closes the oldest non-active page so contexts can't accumulate.
416
+ - ♻️ **Context rotation** — long-lived contexts are periodically recycled (`config.session.rotationIntervalSecs`, default 0 = off). The old `BrowserContext` is closed and a fresh one built with your cookies/localStorage preserved (via storageState) and the current URL reloaded, so a session that's open for hours can't grow unbounded in DOM/listeners/workers. Trigger on demand with the `context_rotate` tool too.
417
+ - 🪵 **Bounded logs** — app logs are rotated (10 MB × 3 files) so disk never fills.
418
+ - 🔌 **Graceful shutdown** — `SIGTERM`/`SIGINT` closes the browser and all tracked daemons; `ps` even shows a live **MEM** (RSS) column so you can spot leaks.
419
+
367
420
  ## License
368
421
 
369
422
  MIT — see [LICENSE](https://github.com/plumpslabs/fennec/blob/main/LICENSE) for details.