@peekdev/cli 0.1.0-alpha.26 → 0.1.0-alpha.27

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
@@ -8,6 +8,9 @@
8
8
  [![downloads](https://img.shields.io/npm/dw/@peekdev/cli.svg)](https://www.npmjs.com/package/@peekdev/cli)
9
9
  [![license](https://img.shields.io/npm/l/@peekdev/cli.svg)](https://github.com/Cubenest/rrweb-stack/blob/main/LICENSE)
10
10
  [![CI](https://github.com/Cubenest/rrweb-stack/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Cubenest/rrweb-stack/actions/workflows/ci.yml)
11
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Cubenest/rrweb-stack/badge)](https://scorecard.dev/viewer/?uri=github.com/Cubenest/rrweb-stack)
12
+ [![node](https://img.shields.io/node/v/@peekdev/cli.svg)](https://www.npmjs.com/package/@peekdev/cli)
13
+ ![status: alpha](https://img.shields.io/badge/status-alpha-orange.svg)
11
14
 
12
15
  ![peek sessions list and drill-down — three real sessions, console + network errors, markdown-formatted output for AI paste](https://raw.githubusercontent.com/Cubenest/rrweb-stack/main/assets/peek-hero.gif)
13
16
 
@@ -29,7 +32,7 @@ peek init
29
32
  2. Detects your AI coding-agent client (Claude Code, Cursor, Cline, Windsurf, VS Code) and adds the `peek-mcp` server to its MCP configuration.
30
33
  3. Prints a one-line "install the extension" link.
31
34
 
32
- Then you install the [Peek Chrome extension](https://chromewebstore.google.com/) (CWS submission pending), open the side panel on the site you want to capture, and click **Enable on this site**. Your AI agent can now query the recording.
35
+ Then you install the **Peek Chrome extension** (CWS listing pending — Phase 5; for now it loads unpacked, see [`@peekdev/extension`](https://github.com/Cubenest/rrweb-stack/tree/main/packages/peek-extension)), open the side panel on the site you want to capture, and click **Enable on this site**. Your AI agent can now query the recording.
33
36
 
34
37
  ## What this is NOT
35
38
 
@@ -61,7 +64,7 @@ After `peek init`, the `peek-mcp` server is available to your AI client as an MC
61
64
  - "find network requests with status >= 400 from the last 5 minutes of recording on `example.com`"
62
65
  - "generate a Playwright reproduction script from session `abc123`"
63
66
 
64
- The MCP server exposes 10 tools — listing, session summaries, console/network drill-down, user-action history, DOM reconstruction and history, Playwright-repro generation, and (with explicit per-action authorization) actions like clicks/inputs/navigation. See [`@peekdev/mcp`](https://github.com/Cubenest/rrweb-stack/tree/main/packages/peek-mcp) for the tool reference.
67
+ The MCP server exposes 14 tools — listing, session summaries, console/network drill-down, user-action history, DOM reconstruction and history, Playwright-repro generation, non-destructive element highlighting, and (with explicit per-origin permission) actions like clicks/inputs/navigation plus a pause-and-hand-back-to-the-user input handoff. See [`@peekdev/mcp`](https://github.com/Cubenest/rrweb-stack/tree/main/packages/peek-mcp) for the tool reference.
65
68
 
66
69
  ## Privacy
67
70
 
@@ -119,9 +122,9 @@ The skill is idempotent on re-run (no-op when the on-disk content matches the bu
119
122
  }
120
123
  ```
121
124
 
122
- Commit it or add it to `.gitignore` — Cursor reads either. Cursor's docs document the global file as "tools available everywhere" and the project file as "project-specific tools" (see [docs.cursor.com/context/mcp](https://cursor.com/docs/context/mcp) for current merge semantics).
125
+ Commit it or add it to `.gitignore` — Cursor reads either. Cursor's docs document the global file as "tools available everywhere" and the project file as "project-specific tools" (see [cursor.com/docs/context/mcp](https://cursor.com/docs/context/mcp) for current merge semantics).
123
126
 
124
- This is the same block `peek init` writes to the global file, so the two configs are interchangeable. You still need the [Peek Chrome extension](https://chromewebstore.google.com/) installed and the native messaging host registered — run `peek init --skip-clients` if you want the host installed without touching any MCP config.
127
+ This is the same block `peek init` writes to the global file, so the two configs are interchangeable. You still need the **Peek Chrome extension** installed (CWS listing pending — Phase 5; loads unpacked for now, see [`@peekdev/extension`](https://github.com/Cubenest/rrweb-stack/tree/main/packages/peek-extension)) and the native messaging host registered — run `peek init --skip-clients` if you want the host installed without touching any MCP config.
125
128
 
126
129
  ## Versioning & compatibility
127
130
 
@@ -129,8 +132,10 @@ Semantic Versioning. Currently `0.1.0-alpha.x` — pre-release; the CLI surface
129
132
 
130
133
  `@peekdev/cli` depends on `@peekdev/mcp` as a workspace peer. Both are versioned and published together via Changesets + OIDC Trusted Publishing.
131
134
 
135
+ Full release history: [CHANGELOG.md](https://github.com/Cubenest/rrweb-stack/blob/main/packages/peek-cli/CHANGELOG.md).
136
+
132
137
  ## License
133
138
 
134
- Apache 2.0. The bundled rrweb engine remains MIT-licensed; see `NOTICE`.
139
+ Apache 2.0. The bundled rrweb engine remains MIT-licensed; see [`NOTICE`](https://github.com/Cubenest/rrweb-stack/blob/main/packages/peek-cli/NOTICE).
135
140
 
136
141
  Contributions are accepted under the [Developer Certificate of Origin (DCO)](https://developercertificate.org/) — sign your commits with `git commit -s`. See [CONTRIBUTING.md](https://github.com/Cubenest/rrweb-stack/blob/main/CONTRIBUTING.md) + [SECURITY.md](https://github.com/Cubenest/rrweb-stack/blob/main/SECURITY.md).
@@ -1,3 +1,14 @@
1
+ /** Injectable seams (defaults are the real fs + a sync sleep). For tests. */
2
+ export interface AtomicWriteDeps {
3
+ /** Rename implementation (default `fs.renameSync`). */
4
+ readonly rename?: (from: string, to: string) => void;
5
+ /** Synchronous backoff between retries (default {@link syncSleep}). */
6
+ readonly sleep?: (ms: number) => void;
7
+ /** Platform (default `process.platform`); retries happen ONLY on `win32`. */
8
+ readonly platform?: NodeJS.Platform;
9
+ /** Max rename attempts before giving up on a transient Windows lock (default 4). */
10
+ readonly maxRetries?: number;
11
+ }
1
12
  /**
2
13
  * Write `content` to `path` atomically: write a temp file in the SAME directory
3
14
  * then `renameSync` over the target (rename is atomic on a single filesystem).
@@ -5,6 +16,11 @@
5
16
  * crash / full disk / OOM could leave as an empty or partial file — and
6
17
  * `~/.claude.json` is read on every Claude Code startup. Parent dirs are
7
18
  * created; on failure the temp file is best-effort removed.
19
+ *
20
+ * On Windows the final rename can transiently fail with EBUSY/EPERM/EACCES when
21
+ * the target or temp is briefly locked (editor open, antivirus scan); those are
22
+ * retried with a short backoff before giving up. On POSIX a single failed
23
+ * rename throws immediately (no spurious lock errors there).
8
24
  */
9
- export declare function atomicWriteFileSync(path: string, content: string): void;
25
+ export declare function atomicWriteFileSync(path: string, content: string, deps?: AtomicWriteDeps): void;
10
26
  //# sourceMappingURL=fs-atomic.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fs-atomic.d.ts","sourceRoot":"","sources":["../../src/lib/fs-atomic.ts"],"names":[],"mappings":"AAQA;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAcvE"}
1
+ {"version":3,"file":"fs-atomic.d.ts","sourceRoot":"","sources":["../../src/lib/fs-atomic.ts"],"names":[],"mappings":"AAuBA,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,uEAAuE;IACvE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IACpC,oFAAoF;IACpF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,eAAoB,GACzB,IAAI,CAmBN"}
@@ -4,6 +4,19 @@
4
4
  import { randomBytes } from 'node:crypto';
5
5
  import { mkdirSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
6
6
  import { dirname } from 'node:path';
7
+ /**
8
+ * Error codes that, on Windows, mean the rename target (or the freshly-written
9
+ * temp) is TRANSIENTLY locked — an editor with the config open, or antivirus
10
+ * scanning the new temp file — so `MoveFileEx` fails but a retry moments later
11
+ * usually succeeds. POSIX `rename(2)` replaces atomically even while the target
12
+ * is open and never hits these, so we only retry on win32. ENOSPC/ENOENT and
13
+ * friends are NOT in here — those aren't locks and must fail fast.
14
+ */
15
+ const WINDOWS_TRANSIENT_RENAME_CODES = new Set(['EBUSY', 'EPERM', 'EACCES']);
16
+ /** Synchronous sleep (atomicWriteFileSync is sync, so we can't await). */
17
+ function syncSleep(ms) {
18
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
19
+ }
7
20
  /**
8
21
  * Write `content` to `path` atomically: write a temp file in the SAME directory
9
22
  * then `renameSync` over the target (rename is atomic on a single filesystem).
@@ -11,13 +24,22 @@ import { dirname } from 'node:path';
11
24
  * crash / full disk / OOM could leave as an empty or partial file — and
12
25
  * `~/.claude.json` is read on every Claude Code startup. Parent dirs are
13
26
  * created; on failure the temp file is best-effort removed.
27
+ *
28
+ * On Windows the final rename can transiently fail with EBUSY/EPERM/EACCES when
29
+ * the target or temp is briefly locked (editor open, antivirus scan); those are
30
+ * retried with a short backoff before giving up. On POSIX a single failed
31
+ * rename throws immediately (no spurious lock errors there).
14
32
  */
15
- export function atomicWriteFileSync(path, content) {
33
+ export function atomicWriteFileSync(path, content, deps = {}) {
34
+ const rename = deps.rename ?? renameSync;
35
+ const sleep = deps.sleep ?? syncSleep;
36
+ const platform = deps.platform ?? process.platform;
37
+ const maxRetries = deps.maxRetries ?? 4;
16
38
  mkdirSync(dirname(path), { recursive: true });
17
39
  const tmp = `${path}.peek-tmp-${randomBytes(4).toString('hex')}`;
18
40
  try {
19
41
  writeFileSync(tmp, content, 'utf8');
20
- renameSync(tmp, path);
42
+ renameWithWindowsRetry(rename, tmp, path, platform, maxRetries, sleep);
21
43
  }
22
44
  catch (err) {
23
45
  try {
@@ -29,4 +51,25 @@ export function atomicWriteFileSync(path, content) {
29
51
  throw err;
30
52
  }
31
53
  }
54
+ /** Rename, retrying transient Windows lock errors with backoff. POSIX: one shot. */
55
+ function renameWithWindowsRetry(rename, from, to, platform, maxRetries, sleep) {
56
+ for (let attempt = 1;; attempt += 1) {
57
+ try {
58
+ rename(from, to);
59
+ return;
60
+ }
61
+ catch (err) {
62
+ const code = err?.code;
63
+ const retryable = platform === 'win32' &&
64
+ attempt < maxRetries &&
65
+ code !== undefined &&
66
+ WINDOWS_TRANSIENT_RENAME_CODES.has(code);
67
+ if (!retryable)
68
+ throw err;
69
+ // Brief, growing backoff (25ms → 50ms → 100ms…) so the lock holder (AV,
70
+ // editor) has a moment to release before the next MoveFileEx attempt.
71
+ sleep(25 * 2 ** (attempt - 1));
72
+ }
73
+ }
74
+ }
32
75
  //# sourceMappingURL=fs-atomic.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fs-atomic.js","sourceRoot":"","sources":["../../src/lib/fs-atomic.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yEAAyE;AACzE,8CAA8C;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,OAAe;IAC/D,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,GAAG,IAAI,aAAa,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;IACjE,IAAI,CAAC;QACH,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACpC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,UAAU,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;QACvE,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"fs-atomic.js","sourceRoot":"","sources":["../../src/lib/fs-atomic.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yEAAyE;AACzE,8CAA8C;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;;;GAOG;AACH,MAAM,8BAA8B,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE7E,0EAA0E;AAC1E,SAAS,SAAS,CAAC,EAAU;IAC3B,OAAO,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AACnE,CAAC;AAcD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAY,EACZ,OAAe,EACf,OAAwB,EAAE;IAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,UAAU,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;IACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;IAExC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,GAAG,IAAI,aAAa,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;IACjE,IAAI,CAAC;QACH,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACpC,sBAAsB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,UAAU,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;QACvE,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,oFAAoF;AACpF,SAAS,sBAAsB,CAC7B,MAA0C,EAC1C,IAAY,EACZ,EAAU,EACV,QAAyB,EACzB,UAAkB,EAClB,KAA2B;IAE3B,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAAyC,EAAE,IAAI,CAAC;YAC9D,MAAM,SAAS,GACb,QAAQ,KAAK,OAAO;gBACpB,OAAO,GAAG,UAAU;gBACpB,IAAI,KAAK,SAAS;gBAClB,8BAA8B,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,CAAC,SAAS;gBAAE,MAAM,GAAG,CAAC;YAC1B,wEAAwE;YACxE,sEAAsE;YACtE,KAAK,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: peek
3
- description: Use when the user mentions a recent browser session, an error they just reproduced, "what was the user doing before X", DOM state at some past moment, or wants to turn a manual repro into a Playwright test. Peek exposes 10 MCP tools backed by a local SQLite store of rrweb-captured browser sessions.
3
+ description: Use when the user mentions a recent browser session, an error they just reproduced, "what was the user doing before X", DOM state at some past moment, or wants to turn a manual repro into a Playwright test. Peek exposes 14 MCP tools backed by a local SQLite store of rrweb-captured browser sessions.
4
4
  ---
5
5
 
6
6
  # peek — local browser-session inspection
7
7
 
8
8
  Peek is an OSS browser companion for AI coding agents. A Chrome MV3
9
9
  extension records masked rrweb sessions to a local SQLite store
10
- (`~/.peek/sessions.db`); a stdio MCP server exposes 10 tools that let you
10
+ (`~/.peek/sessions.db`); a stdio MCP server exposes 14 tools that let you
11
11
  inspect those sessions and (with consent) drive the live browser.
12
12
 
13
13
  Peek runs entirely on the user's machine. No telemetry, no cloud, no
@@ -38,9 +38,9 @@ Don't reach for peek when:
38
38
  not a live debugger
39
39
  - The question is about static code, not runtime behavior
40
40
 
41
- ## The 10 tools
41
+ ## The 14 tools
42
42
 
43
- **Read tools (8) — work at permission Level 2+ for the origin:**
43
+ **Read tools (8) — usable at permission Level 1 (Read-only) and above:**
44
44
 
45
45
  | Tool | When |
46
46
  |---|---|
@@ -53,12 +53,26 @@ Don't reach for peek when:
53
53
  | `query_dom_history` | Given a CSS selector + sessionId, returns every snapshot where that element changed. Good for "when did this element appear/disappear/change text". |
54
54
  | `generate_playwright_repro` | Turns a session (or a slice of one) into a runnable Playwright test stub. Selectors are best-effort from rrweb metadata; surface to the user for review before assuming they'll work. |
55
55
 
56
- **Write tools (2) — escalating consent required:**
56
+ **Act tools (2) — Level 3+; every call is audit-logged to `~/.peek/audit.log`:**
57
57
 
58
58
  | Tool | When |
59
59
  |---|---|
60
- | `request_authorization` | Ask the user to authorize a specific action against a specific origin. Always call this BEFORE `execute_action` if the action is destructive (form submission, navigation away from the current page, anything that mutates state). |
61
- | `execute_action` | Performs a click / type / navigate in the user's live browser. Gated by the per-origin permission level Level 3 covers safe reads, Level 4 covers actions with destructive-action consent, Level 5 is full automation. |
60
+ | `request_authorization` | Ask the user to authorize a specific action against a specific origin via the side-panel banner. On Allow it returns a one-shot `confirmToken` to pass to `execute_action`. Call this BEFORE `execute_action` at Level 3, or to pre-authorize. |
61
+ | `execute_action` | Performs a click / type / navigate in the user's live browser. Gated by the per-origin level: **Level 3** prompts a confirm banner per action (unless a `confirmToken` is passed); **Level 4** auto-allows non-destructive actions; below Level 3 it's denied. The destructive-action blocklist (delete/send/pay/…) always prompts, even at Level 4. |
62
+
63
+ **Suggest tools (2) — Level 2+; non-mutating:**
64
+
65
+ | Tool | When |
66
+ |---|---|
67
+ | `suggest_element` | Draw a non-destructive highlight overlay on a CSS selector (optional label) to point something out. Never clicks, types, or navigates. |
68
+ | `clear_highlight` | Remove the highlight overlay drawn by `suggest_element`. |
69
+
70
+ **Control tools (2) — Level 4 with the control shield up:**
71
+
72
+ | Tool | When |
73
+ |---|---|
74
+ | `set_intent` | Set the agent's status-banner text on the control shield (e.g. "Applying to Senior Frontend · step 2/4") so the user can follow what you're doing. |
75
+ | `request_user_input` | Pause the agent and hand the keyboard back to the user for one editable field (or a free-text prompt) — a CAPTCHA, an OTP, a final review — then resume. |
62
76
 
63
77
  ## Workflow
64
78
 
@@ -144,19 +158,23 @@ User: "Click the Save button on the page I have open."
144
158
 
145
159
  ## Permission model
146
160
 
147
- Peek uses a five-level per-origin model. The state lives in
148
- `~/.peek/permissions.json`; the user manages it via the extension's
149
- side panel and `peek audit` (CLI).
161
+ Peek uses a five-level per-origin model (ADR-0010). The level lives in the
162
+ extension (`chrome.storage.sync`, key `peek:permissionLevels`); the user
163
+ manages it via the side panel's trust dial. A freshly-enabled origin defaults
164
+ to **Level 1 (Read-only)**.
165
+
166
+ - **Level 0 — Off** — tool surface disabled for the origin (recording suppressed)
167
+ - **Level 1 — Read-only** (default) — all 8 read tools; no action execution
168
+ - **Level 2 — Suggest-only** — read + non-mutating highlight overlay
169
+ (`suggest_element` / `clear_highlight`); no DOM mutation
170
+ - **Level 3 — Act-with-confirm** — read + `execute_action` (click/type/navigate),
171
+ each prompting Allow once / Always for this site / Deny
172
+ - **Level 4 — YOLO this session** — read + non-destructive actions auto-allowed
173
+ with no prompt; auto-expires on tab close or after 60 min; also unlocks
174
+ `set_intent` / `request_user_input` while the control shield is up
150
175
 
151
- - **Level 0** no access (default for new origins)
152
- - **Level 1** — list-only (sessionId + origin + timestamps; no event content)
153
- - **Level 2** — read full session content (all 8 read tools usable)
154
- - **Level 3** — read + safe actions (clicks, typing in inputs; no
155
- navigation away, no form submission)
156
- - **Level 4** — read + actions including destructive (with per-action
157
- `request_authorization` consent)
158
- - **Level 5** — automation (Level 4 actions without per-action consent;
159
- rare, opt-in only)
176
+ There is no Level 5. The destructive-action blocklist (delete/send/pay/…) is a
177
+ cross-level override that **always** prompts including at Level 4 not a level.
160
178
 
161
179
  If a tool returns `{ error: 'permission_denied', origin, currentLevel,
162
180
  requiredLevel }`, tell the user how to escalate (via the side panel)
@@ -166,7 +184,7 @@ and stop. Don't retry, don't suggest workarounds.
166
184
 
167
185
  - Never invent sessions. If `list_recent_sessions` returns empty, say so
168
186
  and suggest the user record a session via the extension.
169
- - Never invent tool names. The 10 above are the entire surface.
187
+ - Never invent tool names. The 14 above are the entire surface.
170
188
  - Selector results from `generate_playwright_repro` are derived from
171
189
  rrweb event metadata. Surface them for review; don't claim a generated
172
190
  test is production-ready without the user confirming.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peekdev/cli",
3
- "version": "0.1.0-alpha.26",
3
+ "version": "0.1.0-alpha.27",
4
4
  "description": "peek command-line tool. A thin read-mostly client of the native host's ~/.peek/sessions.db: status, sessions list/show/export/delete, the `peek init` MCP-client wizard, and `peek audit log`.",
5
5
  "keywords": [
6
6
  "peek",
@@ -36,7 +36,7 @@
36
36
  ],
37
37
  "dependencies": {
38
38
  "better-sqlite3": "^12.10.0",
39
- "@peekdev/mcp": "0.1.0-alpha.20"
39
+ "@peekdev/mcp": "0.1.0-alpha.21"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/better-sqlite3": "^7.6.13",