@emmaneugene/pi-cursor-sdk 0.4.3 → 0.5.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +19 -39
  3. package/dist/bundled-context-windows.js +6 -13
  4. package/dist/context.js +0 -3
  5. package/dist/cursor-config.js +0 -3
  6. package/dist/cursor-provider-turn-prepare.js +0 -1
  7. package/dist/cursor-state.js +3 -16
  8. package/dist/index.js +0 -2
  9. package/dist/model-discovery.js +11 -47
  10. package/docs/cursor-dogfood-checklist.md +1 -1
  11. package/docs/cursor-live-smoke-checklist.md +1 -2
  12. package/docs/cursor-model-ux-spec.md +80 -151
  13. package/docs/cursor-native-tool-replay.md +2 -3
  14. package/docs/cursor-native-tool-visual-audit.md +1 -1
  15. package/docs/cursor-testing-lessons.md +1 -1
  16. package/docs/cursor-tool-surfaces.md +3 -6
  17. package/docs/platform-smoke-implementation.md +1 -1
  18. package/docs/platform-smoke.md +1 -1
  19. package/package.json +1 -1
  20. package/scripts/isolated-cursor-smoke.sh +1 -1
  21. package/scripts/lib/local-resume-smoke-harness.mjs +2 -1
  22. package/scripts/local-resume-smoke.mjs +1 -1
  23. package/scripts/platform-smoke/card-detect.mjs +1 -1
  24. package/scripts/refresh-cursor-model-snapshots.mjs +3 -3
  25. package/shared/cursor-model-selection-identities.d.mts +1 -4
  26. package/shared/cursor-model-selection-identities.mjs +21 -74
  27. package/src/bundled-context-windows.ts +6 -13
  28. package/src/context.ts +1 -5
  29. package/src/cursor-config.ts +9 -13
  30. package/src/cursor-provider-turn-prepare.ts +0 -1
  31. package/src/cursor-state.ts +3 -22
  32. package/src/index.ts +0 -3
  33. package/src/model-discovery.ts +16 -62
  34. package/dist/cursor-question-tool.js +0 -194
  35. package/node_modules/cross-spawn/node_modules/which/CHANGELOG.md +0 -166
  36. package/src/cursor-question-tool.ts +0 -267
@@ -8,9 +8,10 @@ Implemented design target. This file describes the intended Cursor model UX and
8
8
 
9
9
  Current implementation notes:
10
10
 
11
- - Cursor context variants use `base@context` pi model IDs.
11
+ - Each Cursor catalog item registers one pi model under its canonical `model.id`.
12
+ - The Cursor default variant supplies context and fast parameters; aliases and alternate variants do not create more pi model rows.
12
13
  - Cursor `reasoning`, `effort`, and boolean `thinking` parameters are driven by pi native thinking when the Cursor SDK exposes those controls.
13
- - Cursor `fast` is extension state by default; models that expose `fast` also get selection-only `:fast` / `:slow` virtual aliases for per-agent overrides.
14
+ - Cursor `fast` is extension state controlled through `/cursor-fast`, saved defaults, or process flags.
14
15
  - Cursor SDK `mode` (`agent` or `plan`) is extension session state, not model identity, pi thinking, Cursor `fast`, or pi's separate plan-mode extension.
15
16
  - Cursor status uses one coordinated `ctx.ui.setStatus("cursor", ...)` value for fast, non-default plan mode, and the local-only `http1` transport marker; the default pi footer remains intact.
16
17
  - Installed `@cursor/sdk` user messages accept images, and Cursor models are treated as image-capable; registered input metadata is `text` plus `image`.
@@ -25,7 +26,7 @@ Current implementation notes:
25
26
  - Local Cursor agents get two tool surfaces. First, Cursor keeps the Cursor SDK local-agent tool surface plus configured Cursor settings, plugins, and Cursor MCP servers. Second, pi-cursor-sdk exposes active pi tools through a default-on, tokenized loopback MCP bridge when bridgeable tools exist.
26
27
  - `buildCursorPiToolBridgeSnapshot()` is the runtime capability source for pi bridge tools. It snapshots `pi.getActiveTools()` and `pi.getAllTools()`, carries pi 0.77+ per-tool `promptGuidelines` into bridge MCP descriptions, filters internal replay names, hides overlapping built-in pi tools (`read`, `bash`, `write`, `edit`, `grep`, `find`, `ls`) unless `PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1`, and creates collision-safe MCP names such as `pi__sem_reindex`. Cursor discovers the current run's exposed bridge tools through MCP `listTools`. Bootstrap prompts include a compact callable-surface manifest from `buildCursorToolManifestText()` by default (`PI_CURSOR_TOOL_MANIFEST=1`); disable with `PI_CURSOR_TOOL_MANIFEST=0`. There is no per-turn visible tool list, status manifest, or footer manifest. User-facing summary: [Cursor tool surfaces in pi](./cursor-tool-surfaces.md).
27
28
  - Prompt text is the primary provider/bridge contract. Bootstrap prompts carry a short boundary block plus the callable-surface manifest by default (`PI_CURSOR_TOOL_MANIFEST=1`). MCP `listTools` descriptions use a one-line pointer to the bootstrap prompt instead of repeating the full contract (`buildCursorPiBridgeMcpToolDescription()`). Cursor must call the exposed `pi__*` MCP name, not the real pi tool name shown in pi history or transcripts. When exposed, `pi__mcp` takes preference over Cursor-configured MCP for MCP work and `pi__subagent` takes preference over Cursor-native subagents for delegation; the Cursor-native surfaces remain fallbacks when the matching pi bridge tool is absent or unavailable. Pi emits and executes the real pi tool name. Maintainer debug: `/cursor-tools` prints bridge/manifest enablement, effective `PI_CURSOR_SETTING_SOURCES`, and the current callable-surface snapshot.
28
- - The provider also registers `cursor_ask_question` for Cursor models when the bridge and default-on `PI_CURSOR_ASK_QUESTION` control are enabled. While the tool awaits pi UI input it emits package event `pi-cursor-sdk:ask-question:blocked` with `{ active: true }` and clears `{ active: false }` in `finally`; the tool runs with `executionMode: "sequential"` so parallel sibling calls cannot overlap dialogs. Cursor sees it as `pi__cursor_ask_question`, and pi executes it through the normal tool path so interactive users can choose options from pi UI. `PI_CURSOR_ASK_QUESTION=0` removes only this tool while preserving the rest of the bridge. In non-UI modes it reports that UI is unavailable so Cursor can state a default assumption instead. When pi has visible Agent Skills loaded, the provider rewrites the skill catalog for Cursor and registers `cursor_activate_skill` as `pi__cursor_activate_skill`; pi executes it through the normal tool path so Cursor can load the full `SKILL.md` and skill resource list for the current pi-loaded skill source of truth. `PI_CURSOR_PI_TOOL_BRIDGE=0` disables the local bridge, including question and skill activation bridging.
29
+ - When pi has visible Agent Skills loaded, the provider rewrites the skill catalog for Cursor and registers `cursor_activate_skill` as `pi__cursor_activate_skill`; pi executes it through the normal tool path so Cursor can load the full `SKILL.md` and skill resource list for the current pi-loaded skill source of truth. `PI_CURSOR_PI_TOOL_BRIDGE=0` disables the local bridge, including skill activation bridging.
29
30
  - The bridge queues MCP calls, emits provider `toolcall_*` events, waits for matching pi `toolResult` messages by `toolCallId`, resolves the result back into the same live Cursor SDK run without creating a new `Agent`, and never calls tool `execute()` handlers directly. The same-run resume invariant holds unless the run was disposed, aborted, or cancelled.
30
31
  - Cursor SDK MCP tool calls use a guarded timeout override because installed `@cursor/sdk` 1.0.30 still has a 60-second MCP request default with no public per-server timeout option. The extension extends the verified Cursor SDK MCP `callTool` timeout path to 3600 seconds by default and shortens the verified first-send MCP initialize/listTools timeout paths to 10 seconds by default so unavailable configured MCP servers do not block the first reply for a full minute; unknown MCP protocol timeout stacks keep the SDK default. Users can override tool-call timeouts with `PI_CURSOR_MCP_TOOL_TIMEOUT_MS` or `PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS`, and initialize/listTools timeouts with `PI_CURSOR_MCP_CONNECT_TIMEOUT_MS` or `PI_CURSOR_MCP_CONNECT_TIMEOUT_SECONDS`. Bridged `CallTool` waits also have a local fail-closed deadline that defaults to and cannot exceed the effective MCP tool timeout; `PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS` can lower it, expiry or MCP cancellation aborts active pi execution when available, and expired bridge events are dropped before pi tool emission.
31
32
  - Cursor SDK local safety controls are off by default. `--cursor-auto-review` / `PI_CURSOR_AUTO_REVIEW` and `--cursor-sandbox` / `PI_CURSOR_SANDBOX` pass only explicit enabled values into `Agent.create({ local })`; user or trusted project config can set `local.autoReview` and `local.sandboxOptions.enabled`; project config is active only when Pi's project-trust flow reached the extension and approved the project or the run used explicit `--approve`, and project saves require the same immutable trust provenance rather than creating Pi trust resources automatically. Pi 0.84.0 loads `pi install -l` project-local extensions after the trust event, so those installs require `--approve` on every run that reads or writes `.pi/cursor-sdk.json`. Fast-default and HTTP transport saves preserve unrecognized config fields, reject malformed or non-object JSON without rewriting it, and use one lock-protected read-modify-write path; fast saves mutate only the selected model key. Because Pi can mutate its in-memory session branch before a journal append throws, a completed global save is authoritative and the command reports the partial journal failure instead of attempting an ambiguous rollback; the new global value stays authoritative over stale branch entries until a later successful save or session restart.
@@ -40,7 +41,7 @@ Current implementation notes:
40
41
  - Current fork release evidence for Cursor provider/runtime changes is the full unit/typecheck suite, package dry run, a live print-mode Cursor run, and visual smoke. The Crabbox-backed platform matrix is deferred under [issue #2](https://github.com/emmaneugene/pi-cursor-sdk/issues/2). Use [Cursor Live Smoke Checklist](./cursor-live-smoke-checklist.md) for live verification with real `pi -ne --approve -e . --cursor-no-fast --model cursor/grok-4.6` invocations, temporary session dirs, diagnostics scans, and persisted JSONL inspection. See [Cursor testing lessons](./cursor-testing-lessons.md) for auth.json seeding, isolated smoke harnesses, and replay JSONL scans.
41
42
  - For models without a catalog `context` parameter, context windows are not hardcoded. The extension ships a bundled SDK-derived default/non-Max cache generated from `createAgentPlatform().checkpointStore.loadLatest(agentId).tokenDetails.maxTokens`. Successful runs can update a local override cache, but model discovery does not probe models at startup.
42
43
  - Max Mode context windows are distinct from default/non-Max context windows. `@cursor/sdk` 1.0.30 documentation says the SDK may enable Max Mode automatically when a selected model requires it, but the public local-agent `ModelSelection` path still does not expose a manual Max Mode selector. Do not advertise Max Mode context windows unless the SDK catalog exposes an exact parameter/variant or the SDK public API adds a Max Mode selector that the extension actually sends.
43
- - The installed `@cursor/sdk` exposes latest-style `ModelListItem.aliases`. The extension registers only unambiguous aliases as pi model IDs (with the same context suffixes when applicable) and sends the alias back in `ModelSelection.id`. Cursor-only fast preferences are keyed by the selected SDK model ID/alias, with read fallback for older preferences keyed by the underlying catalog `id`. Aliases shared by multiple base models, such as generic family aliases, are skipped because the pi row metadata would otherwise imply one base model while Cursor may resolve the alias to another.
44
+ - The installed `@cursor/sdk` exposes `ModelListItem.aliases`, alternate contexts, and fast parameters. The extension does not register those as extra pi models. It sends the canonical catalog ID with the default variant's parameters and applies supported thinking and fast controls at send time.
44
45
  - Local restart resume treats user entries already present at `session_start` or selected by tree navigation as crash-ambiguous: an older SDK handle cannot span them because the prior process may already have submitted that prompt. A user entry appended after startup in the current process may span the last completed handle for the normal next send.
45
46
  - Persisted pi sessions use a session-scoped Cursor SDK SQLite store at `<getDefaultSdkStateRoot(cwd)>/pi-sessions/<session-hash>/`; create/resume, transcript reads, checkpoint lookup, and exact-ID cleanup all receive that same store. Fileless acquisitions use unique OS-temporary stores that are removed on graceful disposal; invalidation starts a fresh agent instead of reopening a disposed temporary store. Resume entries version the store identity. Legacy entries still resume against the SDK default workspace store, then move to the per-session store after fallback or agent replacement. Removing a persisted pi session does not automatically remove its store directory; only a verified session-derived `pi-sessions/<session-hash>` root may be removed after no pi process uses it. The shared SDK default workspace root recorded by legacy entries must never be removed as session cleanup.
46
47
  - Session-scoped Cursor SDK agent pooling reuses one live `@cursor/sdk` agent across compatible follow-up turns within the same pi session scope. Independently, each distinct local agent whose `Agent.send()` is initiated is best-effort recorded once per native pi session as a non-resumable `cursor-sdk-agent-lineage` custom entry (including failed/cancelled sends and when local resume is disabled). Cloned/forked sessions record lineage under their own pi session ID; donor entries do not suppress the new session. `planCursorSessionSend()` in `src/cursor-session-send-policy.ts` decides whether the next turn sends a full bootstrap prompt or an incremental follow-up, whether the SDK agent must be recreated, and why. `computeCursorContextFingerprint()` and `shouldBootstrapCursorContext()` remain the context-only bootstrap signal. The pool recreates the agent when context diverges, when branch or compaction summaries appear after `/tree` navigation or compaction, after 20 completed incremental sends, when the API key identity changes, after send errors, after five minutes without a successful send (`CURSOR_LOCAL_AGENT_IDLE_MS`; `Agent.create`, not `Agent.resume`), on `session_shutdown`, and when `session_before_tree` / `session_tree` invalidate the active branch. Incremental sends omit the full Cursor SDK tool boundary block because the session agent retains prior bootstrap context, but every send ends with a short tool tail guard placed after the latest user request (including an explicit shell `cd` hint). True incremental sends also omit invariant Pi system instructions; system-prompt changes are part of the context fingerprint and force a full context-divergence bootstrap that includes the updated system section.
@@ -54,12 +55,12 @@ Main outcomes:
54
55
 
55
56
  - `pi --list-models` shows pi-native Cursor models with accurate `contextWindow`, pi-controllable thinking metadata, and conservative defaults where the Cursor SDK does not expose limits or capabilities.
56
57
  - `shift+tab` is pi's native thinking control and drives Cursor `reasoning` or `effort`.
57
- - Cursor context options are represented as pi-visible model variants when they change native model metadata.
58
+ - Each Cursor catalog item appears once under its canonical ID. The default Cursor context supplies pi's `contextWindow` metadata.
58
59
  - Cursor-only state (`fast` and Cursor SDK `mode`) is controlled by extension flags/commands and shown through native status text only when non-default.
59
60
  - The default pi footer remains intact.
60
61
  - Model capabilities are discovered from the Cursor SDK, not hardcoded per model.
61
62
 
62
- Native tradeoff: context-capable Cursor models intentionally use context-qualified pi model IDs. This gives up one completely clean row per Cursor base model, but it lets pi's native `contextWindow`, footer context usage, context overflow checks, compaction behavior, session restore, model selection, and `--list-models` metadata stay accurate.
63
+ Native tradeoff: pi exposes no generic provider-parameter picker. The extension therefore uses Cursor's default context instead of adding one pi model row per context value. Cached checkpoint evidence keeps pi's `contextWindow`, footer usage, overflow checks, and compaction metadata aligned with that default where evidence exists.
63
64
 
64
65
  ## Non-goals
65
66
 
@@ -70,7 +71,6 @@ Not building now:
70
71
  - generic pi model-parameter system for all providers
71
72
  - full custom footer replacement
72
73
  - independent Claude `thinking` toggle separate from pi thinking
73
- - multi-parameter CLI suffixes such as `--model cursor/gpt-5.5:medium:272k:fast`
74
74
 
75
75
  ## Source of Truth
76
76
 
@@ -91,13 +91,13 @@ Startup never parses `process.argv`; Pi remains the sole owner of CLI model/prov
91
91
 
92
92
  For each model, use:
93
93
 
94
- - `model.id`
95
- - `model.aliases`
94
+ - `model.id` as the only registered pi model ID
96
95
  - `model.displayName`
97
96
  - `model.parameters`
98
- - `model.variants`
99
97
  - default variant: `variant.isDefault === true`, else first variant
100
98
 
99
+ Ignore `model.aliases` and non-default variants for registration.
100
+
101
101
  This means new Cursor models and changed Cursor parameters are picked up after `/cursor-refresh-models`, reload, or restart.
102
102
 
103
103
  Pi model metadata is also a source of truth for pi-native behavior:
@@ -133,7 +133,7 @@ CURSOR_API_KEY="your-key" npm run refresh:cursor-snapshots -- --write \
133
133
  --context-windows ~/.pi/agent/cursor-sdk-context-windows.json
134
134
  ```
135
135
 
136
- Both modes call `Cursor.models.list({ apiKey })` and use the same sanitizer and stable sort. `--check` byte-compares `src/cursor-fallback-models.generated.ts` without writing; `--write` refreshes it and updates `src/bundled-context-windows.ts` only when `--context-windows` is provided. Context-window inputs are limited to current selectable model IDs; redundant default `:fast`/`:slow` aliases collapse to one key, conflicting equivalent selections fail generation, and stale or ambiguous aliases are omitted. Generated provenance and command output record the installed `@cursor/sdk` version and model count. The script prints model IDs/counts only and scrubs known auth material from SDK errors; it must not print or store API keys. Review generated diffs before committing because Cursor can change aliases, defaults, and parameter meanings.
136
+ Both modes call `Cursor.models.list({ apiKey })` and use the same sanitizer and stable sort. `--check` byte-compares `src/cursor-fallback-models.generated.ts` without writing; `--write` refreshes it and updates `src/bundled-context-windows.ts` only when `--context-windows` is provided. Context-window evidence is normalized to canonical catalog IDs only when it matches the model's default context; aliases, forced-speed variants, non-default contexts, and stale IDs are omitted. Conflicting evidence fails generation. Generated provenance and command output record the installed `@cursor/sdk` version and model count. The script prints model IDs/counts only and scrubs known auth material from SDK errors; it must not print or store API keys. Review generated diffs before committing because Cursor can change defaults and parameter meanings.
137
137
 
138
138
  Dated evidence for Cursor's assistant-visible, model-specific system text and reconstructed tool guidance lives in [Cursor System Prompts and Tool Guidance — 2026-08-02](https://github.com/emmaneugene/pi-cursor-sdk/blob/main/docs/evidence/cursor-system-prompts-2026-08-02/README.md). Keep that evidence separate from pi-cursor-sdk's own bootstrap prompt: Cursor persists its base system message in the local SDK checkpoint, while this extension sends Pi context and bridge instructions as user content.
139
139
 
@@ -144,11 +144,11 @@ Use native pi abstractions wherever possible:
144
144
  | Concern | Representation |
145
145
  |---|---|
146
146
  | Cursor base model | pi provider model |
147
- | Cursor `context` | pi-visible model variant because it changes `contextWindow` |
147
+ | Cursor `context` | default variant plus canonical model `contextWindow` metadata |
148
148
  | Cursor `reasoning` | pi native thinking via `thinkingLevelMap` |
149
149
  | Cursor `effort` | pi native thinking via `thinkingLevelMap` |
150
150
  | Cursor `thinking=false` | pi native `off` |
151
- | Cursor `fast` | extension state plus `:fast` / `:slow` virtual aliases for per-agent overrides |
151
+ | Cursor `fast` | extension state through saved defaults, commands, and process flags |
152
152
  | Cursor SDK `mode` | extension session state; `agent` by default, `plan` via SDK-native mode |
153
153
  | Footer | default pi footer plus optional extension status |
154
154
 
@@ -165,65 +165,42 @@ Register a `cursor` provider with `pi.registerProvider()`.
165
165
 
166
166
  Rules:
167
167
 
168
- - Register one pi model for each Cursor base model and each unambiguous SDK alias when there is no Cursor `context` parameter.
169
- - Register one pi model per Cursor `context` value for each Cursor base model and each unambiguous SDK alias when the model exposes a `context` parameter.
170
- - Skip SDK aliases that collide with another base model ID or are shared by multiple base models; those aliases can resolve differently from the pi row metadata.
171
- - Do not encode `reasoning`, `effort`, `thinking`, or Cursor SDK `mode` into pi model IDs. For models with a Cursor `fast` parameter, also register selection-only `:fast` and `:slow` virtual model aliases that do not change pi-native metadata.
172
- - Prefer stable, readable `@<context>` suffixes that do not conflict with pi's final `:<thinking>` suffix parser.
173
- - Sort Cursor models by base ID, then context value in Cursor SDK order before calling `pi.registerProvider()`. Registration order matters for `/model` display and model cycling; `--list-models` sorts output separately.
168
+ - Register exactly one pi model for each Cursor catalog item.
169
+ - Use canonical `model.id`; do not register `model.aliases`.
170
+ - Use the default variant's context and fast parameters; do not register alternate contexts or forced-speed rows.
171
+ - Do not encode `reasoning`, `effort`, `thinking`, `context`, `fast`, or Cursor SDK `mode` into pi model IDs.
172
+ - Sort Cursor models by canonical ID before calling `pi.registerProvider()`. Registration order matters for `/model` display and model cycling; `--list-models` sorts output separately.
174
173
 
175
- Recommended context-variant ID format:
174
+ Example IDs:
176
175
 
177
176
  ```text
178
- cursor/gpt-5.5@1m
179
- cursor/gpt-5.5@272k
180
- cursor/claude-opus-4-8@1m
181
- cursor/claude-opus-4-8@300k
182
- cursor/composer-2-5
183
- cursor/composer-2-5:fast
184
- cursor/composer-2-5:slow
177
+ cursor/gpt-5.5
178
+ cursor/claude-opus-4-8
179
+ cursor/composer-2.5
185
180
  cursor/grok-4.6
186
- cursor/grok-4.6:fast
187
- cursor/grok-4.6:slow
188
- cursor/gpt-5.5@1m:fast
189
181
  ```
190
182
 
191
- Avoid colon-based context IDs in the first implementation unless this spec is intentionally changed:
183
+ Pi's final `:<thinking>` shorthand remains available because thinking is a native pi control:
192
184
 
193
185
  ```text
194
- cursor/gpt-5.5:1m
195
- cursor/gpt-5.5:1m:medium
186
+ cursor/gpt-5.5:medium
187
+ cursor/claude-opus-4-8:max
196
188
  ```
197
189
 
198
- Those can work technically because pi parses only the final `:<thinking>` suffix, but they overload pi's documented thinking shorthand.
199
-
200
- Avoid this old parameter encoding:
201
-
202
- ```text
203
- cursor/gpt-5.5:context=1m;fast=false;reasoning=medium
204
- cursor/claude-opus-4-8:context=1m;effort=xhigh;thinking=true
205
- ```
206
-
207
- Reason:
208
-
209
- - `@1m` keeps context visually separate from pi's native `:medium` thinking suffix.
210
- - Context variants make `contextWindow` accurate in `--list-models`, the native footer, context overflow checks, and compaction logic.
211
- - `:fast` / `:slow` are virtual aliases, not separate Cursor SDK base models: they keep the same context/thinking metadata and only force the outgoing Cursor `fast` param. They exist so subagents and workflow-spawned agents can choose fast/slow without mutating shared `/cursor-fast` defaults.
212
-
213
190
  ### Metadata Per Registered Model
214
191
 
215
192
  Each registered model must set:
216
193
 
217
- - `id`: context-qualified pi model ID when needed. For SDK aliases, this uses the alias as the pi-visible ID and the alias is sent back to Cursor as `ModelSelection.id`.
218
- - `name`: human-readable Cursor display name plus context when useful.
194
+ - `id`: canonical Cursor catalog `model.id`.
195
+ - `name`: Cursor's human-readable display name.
219
196
  - `reasoning`: `true` only if a Cursor `reasoning`, `effort`, or `thinking` parameter can map to pi thinking. This controls pi's thinking UI and `pi --list-models` `thinking` column; it must not be used to claim whether the Cursor model can think internally. Cursor SDK models are thinking-capable even when this is `false`.
220
197
  - `thinkingLevelMap`: model-specific pi-to-Cursor mapping for pi UI, clamping, persistence, and footer display.
221
- - `contextWindow`: parsed from context variant, else conservative fallback.
198
+ - `contextWindow`: cached checkpoint evidence for the canonical ID or default context, then the parsed default context or conservative fallback.
222
199
  - `maxTokens`: conservative explicit value until Cursor SDK exposes output limits.
223
200
  - `input`: supported input types. The installed Cursor SDK accepts `SDKUserMessage.images`, and Cursor models are expected to support image input, so advertise `["text", "image"]`.
224
201
  - `cost`: zeroed unless reliable Cursor costs are available.
225
202
 
226
- The extension stores runtime metadata in an internal map keyed by registered pi model ID. That map records the Cursor base catalog model ID, the Cursor selection model ID (base ID or alias), selected context param, default params, and discovered capabilities. `ProviderModelConfig` has no dedicated metadata field, so do not rely on hidden custom fields for this state.
203
+ The extension stores runtime metadata in an internal map keyed by canonical pi model ID. That map records default params and discovered capabilities. `ProviderModelConfig` has no dedicated metadata field, so do not rely on hidden custom fields for this state.
227
204
 
228
205
  ## Dynamic Capabilities
229
206
 
@@ -233,7 +210,7 @@ Infer behavior from discovered params:
233
210
 
234
211
  | Cursor param | Extension behavior |
235
212
  |---|---|
236
- | `context` with values | register pi-visible context variants |
213
+ | `context` with values | use the default variant's value and context-window metadata |
237
214
  | `reasoning` | populate `thinkingLevelMap` |
238
215
  | `effort` | populate `thinkingLevelMap` |
239
216
  | `thinking` with `true/false` | map `false` to pi `off`; map `true` to the enabled pi level chosen for boolean-only thinking |
@@ -254,7 +231,7 @@ Native pi keybindings:
254
231
  | Action | Keybinding | Owner |
255
232
  |---|---:|---|
256
233
  | Cycle thinking / reasoning / effort | `shift+tab` | pi native `app.thinking.cycle` |
257
- | Select model / context variant | `/model`, `ctrl+l`, scoped model cycling | pi native model selection |
234
+ | Select model | `/model`, `ctrl+l`, scoped model cycling | pi native model selection |
258
235
 
259
236
  Cursor extension controls:
260
237
 
@@ -347,29 +324,19 @@ Reason:
347
324
 
348
325
  ## Context Behavior
349
326
 
350
- If a Cursor model supports `context`, register one pi model variant per context value.
351
-
352
- Examples:
353
-
354
- ```text
355
- cursor/gpt-5.5@272k
356
- cursor/gpt-5.5@1m
357
-
358
- cursor/claude-opus-4-8@300k
359
- cursor/claude-opus-4-8@1m
360
- ```
327
+ If a Cursor model supports `context`, use the context value from its default variant. Do not register alternate context rows.
361
328
 
362
- Each variant must:
329
+ The canonical model must:
363
330
 
364
- - have an entry in the extension metadata map that points back to the same Cursor base model ID,
365
- - include the selected Cursor `context` param when calling `Agent.create()`,
366
- - set pi `contextWindow` from that context value,
367
- - share the same `thinkingLevelMap` as the base model unless Cursor reports otherwise.
331
+ - retain the default Cursor `context` param when calling `Agent.create()`,
332
+ - set pi `contextWindow` from canonical checkpoint evidence, matching default-context evidence, the parsed default context label, or the conservative fallback in that order,
333
+ - keep one `thinkingLevelMap` for the model.
368
334
 
369
335
  Reason:
370
336
 
371
- - pi context display and overflow logic must match the actual Cursor context.
372
- - pi has no generic provider-parameter system that can change `contextWindow` while keeping the same model ID.
337
+ - pi has no generic provider-parameter picker.
338
+ - one canonical model row matches Cursor's model-picker mental model.
339
+ - checkpoint evidence keeps pi context display and overflow logic aligned with the default Cursor selection where the catalog label differs from the effective window.
373
340
 
374
341
  ## Fast Behavior
375
342
 
@@ -381,10 +348,8 @@ fast=false <-> fast=true
381
348
 
382
349
  Rules:
383
350
 
384
- - Unsuffixed models use extension state from `/cursor-fast`, per-session entries, and global defaults.
385
- - `:fast` / `:slow` virtual model aliases force fast on/off for that selected agent and override saved defaults without writing state.
386
- - Toggle unsuffixed models with `/cursor-fast`; do not persist a new default while a virtual fast alias is selected.
387
- - Store per-session and global per-base-model preferences for unsuffixed models.
351
+ - Models use extension state from `/cursor-fast`, per-session entries, and global defaults.
352
+ - Store preferences per canonical model ID.
388
353
  - When calling `Agent.create()` or `agent.send()`, include the selected `fast` value in Cursor model params.
389
354
  - Show fast-capable models as `cursor · fast:on` or `cursor · fast:off` through `ctx.ui.setStatus()` while a Cursor model is active.
390
355
  - Keep `--cursor-fast` and `--cursor-no-fast` as explicit process-level force flags.
@@ -392,7 +357,7 @@ Rules:
392
357
  Reason:
393
358
 
394
359
  - `fast` does not affect pi `contextWindow`, thinking levels, or input support.
395
- - The virtual aliases trade small `--list-models` noise for per-agent selection that works with subagents and dynamic workflows, where mutating a shared global fast default is the wrong abstraction.
360
+ - Fast state is not a distinct model and should not add picker rows.
396
361
 
397
362
  Status examples:
398
363
 
@@ -457,7 +422,7 @@ Expected native footer behavior:
457
422
  `ctx.ui.setStatus()` adds an extension status line in the default footer. It does not patch the built-in model segment. The native shape is closer to:
458
423
 
459
424
  ```text
460
- ... (cursor) gpt-5.5@1m • medium
425
+ ... (cursor) gpt-5.5 • medium
461
426
  cursor · fast:off · plan
462
427
  ```
463
428
 
@@ -475,7 +440,7 @@ Match pi's native mental model:
475
440
 
476
441
  Let pi persist:
477
442
 
478
- - selected model, including context variant,
443
+ - selected canonical model,
479
444
  - selected thinking level,
480
445
  - session model restore,
481
446
  - global default thinking behavior.
@@ -485,7 +450,7 @@ Let pi persist:
485
450
  The extension persists only Cursor-only state:
486
451
 
487
452
  - `fast` per session,
488
- - `fast` global default per selected Cursor SDK model ID or alias,
453
+ - `fast` global default per canonical Cursor model ID,
489
454
  - Cursor SDK `mode` per session,
490
455
  - local HTTP transport per session and user default,
491
456
  - any future Cursor-only parameter that does not map to pi model metadata.
@@ -501,8 +466,8 @@ Use:
501
466
  Use Cursor default variants:
502
467
 
503
468
  ```text
504
- gpt-5.5 -> cursor/gpt-5.5@1m, thinking medium, fast=false
505
- composer-2.5 -> cursor/composer-2-5, fast=true
469
+ gpt-5.5 -> cursor/gpt-5.5, default context=1m, thinking medium, fast=false
470
+ composer-2.5 -> cursor/composer-2.5, fast=true
506
471
  grok-4.6 -> cursor/grok-4.6, fast=true
507
472
  ```
508
473
 
@@ -510,7 +475,7 @@ grok-4.6 -> cursor/grok-4.6, fast=true
510
475
 
511
476
  Restore:
512
477
 
513
- - pi model, including context variant,
478
+ - pi model,
514
479
  - pi thinking level,
515
480
  - session Cursor-only state such as `fast`, Cursor SDK `mode`, and local HTTP transport.
516
481
 
@@ -520,7 +485,7 @@ Use:
520
485
 
521
486
  1. pi's selected/default model and thinking level,
522
487
  2. branch HTTP transport state, then explicit environment, then the user-level HTTP default,
523
- 3. global fast defaults for the selected SDK model ID or alias, falling back to older base-model keys,
488
+ 3. global fast defaults for the canonical model ID,
524
489
  4. else Cursor default variant params.
525
490
 
526
491
  ## CLI / Print Mode
@@ -528,58 +493,42 @@ Use:
528
493
  Guaranteed first-pass support:
529
494
 
530
495
  ```bash
531
- pi --model cursor/gpt-5.5@1m --thinking medium
532
- pi --model cursor/gpt-5.5@1m --cursor-mode plan
533
- pi --model cursor/gpt-5.5@1m:medium
534
- pi --model cursor/gpt-5.5@272k:xhigh
496
+ pi --model cursor/gpt-5.5 --thinking medium
497
+ pi --model cursor/gpt-5.5 --cursor-mode plan
498
+ pi --model cursor/gpt-5.5:medium
535
499
  ```
536
500
 
537
501
  These use pi's native thinking parser. `--thinking` wins over a `:<thinking>` suffix when both are present.
538
502
 
539
- Not first-pass support:
540
-
541
- ```bash
542
- pi --model cursor/gpt-5.5:medium:272k:fast
543
- ```
544
-
545
- Reason:
546
-
547
- - pi supports one final `:<thinking>` suffix.
548
- - Cursor-only parameters are not generic pi CLI parameters.
549
- - Context is already represented by the registered pi model ID.
550
- - `fast` is controlled by saved extension defaults, `:fast` / `:slow` virtual model aliases, or the `--cursor-fast` / `--cursor-no-fast` extension flags.
551
- - Cursor SDK `mode` is controlled by `/cursor-mode` session state or the first-pass `--cursor-mode` extension flag; it is never encoded in `--model`.
503
+ Cursor context, fast, and SDK mode are not encoded in `--model`. The default catalog variant supplies context; `/cursor-fast` and its process flags control fast; `/cursor-mode` and `--cursor-mode` control SDK mode.
552
504
 
553
505
  For print mode:
554
506
 
555
507
  - no keybindings,
556
- - use selected context model variant,
508
+ - use the model's default Cursor context,
557
509
  - use `--thinking` or `:medium` for reasoning/effort,
558
- - use saved global `fast` defaults unless a virtual `:fast` / `:slow` model alias or force flag is present,
510
+ - use saved global `fast` defaults unless a force flag is present,
559
511
  - use Cursor SDK `agent` mode unless `/cursor-mode` session state or `--cursor-mode` overrides it.
560
512
 
561
513
  Fast flag example:
562
514
 
563
515
  ```bash
564
- pi --model cursor/gpt-5.5@1m --cursor-fast -p "Say ok only"
516
+ pi --model cursor/gpt-5.5 --cursor-fast -p "Say ok only"
565
517
  ```
566
518
 
567
519
  ## Discovered Model Capability Examples
568
520
 
569
- These examples document the capability shapes the extension handles, not an exhaustive live catalog. The exact Cursor catalog changes over time; use `pi -ne --approve -e . --list-models cursor` or `Cursor.models.list()` for the current model surface. When the SDK reports aliases, only unambiguous aliases are registered; shared generic aliases are skipped.
521
+ These examples document the capability shapes the extension handles, not an exhaustive live catalog. The exact Cursor catalog changes over time; use `pi -ne --approve -e . --list-models cursor` or `Cursor.models.list()` for the current model surface. Each catalog item registers once under its canonical ID.
570
522
 
571
523
  | Example model shape | Cursor controls | Pi representation |
572
524
  |---|---|---|
573
525
  | plain model, such as `default` or models with no exposed controls | none | plain model |
574
526
  | Composer-style model such as `composer-2.5` or `composer-2` | fast | plain model + fast extension state |
575
- | GPT-style reasoning model with context variants | context, reasoning, fast when exposed | context variants + native thinking + optional fast state |
576
- | Claude-style thinking model with context variants | thinking, context, effort when exposed | context variants + native thinking + optional fast state |
577
- | Claude-style thinking model without context variants | thinking and/or effort | plain model + native thinking |
578
- | context-only model | context | context variants |
579
- | unique latest alias for any shape | aliases | same pi rows as the base model shape, using the alias as `ModelSelection.id` |
580
- | shared generic alias across multiple base models | aliases | skipped to avoid misleading pi rows |
527
+ | GPT-style reasoning model | context, reasoning, fast when exposed | canonical model + default context + native thinking + optional fast state |
528
+ | Claude-style thinking model | thinking, context, effort when exposed | canonical model + default context + native thinking |
529
+ | context-only model | context | canonical model + default context |
581
530
 
582
- If Cursor later adds `fast`, `context`, `reasoning`, `effort`, or aliases to a model, the extension picks up unambiguous capability changes dynamically.
531
+ If Cursor later changes `fast`, `context`, `reasoning`, or `effort`, the extension picks up the default capability changes dynamically.
583
532
 
584
533
  ## Detailed Examples
585
534
 
@@ -588,7 +537,7 @@ If Cursor later adds `fast`, `context`, `reasoning`, `effort`, or aliases to a m
588
537
  Initial Cursor default for Composer 2.5:
589
538
 
590
539
  ```text
591
- pi model: cursor/composer-2-5
540
+ pi model: cursor/composer-2.5
592
541
  Cursor params: fast=true
593
542
  pi thinking: off
594
543
  Cursor status: cursor · fast:on
@@ -608,24 +557,16 @@ Cursor status: cursor · fast:off
608
557
  Initial Cursor default:
609
558
 
610
559
  ```text
611
- pi model: cursor/gpt-5.5@1m
560
+ pi model: cursor/gpt-5.5
612
561
  Cursor params: context=1m; reasoning=medium; fast=false
613
562
  pi thinking: medium
614
563
  Cursor status: cursor · fast:off
615
564
  ```
616
565
 
617
- After selecting the 272k variant:
618
-
619
- ```text
620
- pi model: cursor/gpt-5.5@272k
621
- Cursor params: context=272k; reasoning=medium; fast=false
622
- pi contextWindow: 272000
623
- ```
624
-
625
566
  After fast toggle:
626
567
 
627
568
  ```text
628
- Cursor params: context=272k; reasoning=medium; fast=true
569
+ Cursor params: context=1m; reasoning=medium; fast=true
629
570
  Cursor status: cursor · fast:on
630
571
  ```
631
572
 
@@ -633,7 +574,7 @@ After `shift+tab` to xhigh:
633
574
 
634
575
  ```text
635
576
  pi thinking: xhigh
636
- Cursor params: context=272k; reasoning=extra-high; fast=true
577
+ Cursor params: context=1m; reasoning=extra-high; fast=true
637
578
  ```
638
579
 
639
580
  ### `gpt-5.3-codex`
@@ -654,43 +595,35 @@ pi thinking: low
654
595
  Cursor params: reasoning=low; fast=true
655
596
  ```
656
597
 
657
- No context variant.
598
+ No context parameter.
658
599
 
659
600
  ### `claude-opus-4-8`
660
601
 
661
602
  Initial Cursor default:
662
603
 
663
604
  ```text
664
- pi model: cursor/claude-opus-4-8@1m
605
+ pi model: cursor/claude-opus-4-8
665
606
  Cursor params: thinking=true; context=1m; effort=xhigh
666
607
  pi thinking: xhigh
667
608
  ```
668
609
 
669
- After selecting the 300k variant:
670
-
671
- ```text
672
- pi model: cursor/claude-opus-4-8@300k
673
- Cursor params: thinking=true; context=300k; effort=xhigh
674
- pi contextWindow: 300000
675
- ```
676
-
677
610
  After `shift+tab` to high:
678
611
 
679
612
  ```text
680
613
  pi thinking: high
681
- Cursor params: thinking=true; context=300k; effort=high
614
+ Cursor params: thinking=true; context=1m; effort=high
682
615
  ```
683
616
 
684
617
  After `shift+tab` to off:
685
618
 
686
619
  ```text
687
620
  pi thinking: off
688
- Cursor params: thinking=false; context=300k
621
+ Cursor params: thinking=false; context=1m
689
622
  ```
690
623
 
691
624
  ### `grok-4.5`
692
625
 
693
- Supports `effort=low|medium|high` and `fast=false|true`; it does not advertise context variants.
626
+ Supports `effort=low|medium|high` and `fast=false|true`; it does not advertise a context parameter.
694
627
 
695
628
  ```text
696
629
  cursor/grok-4.5
@@ -702,15 +635,13 @@ Fast toggle maps to the Cursor `fast` parameter.
702
635
 
703
636
  ### `grok-4.6`
704
637
 
705
- Supports `effort=low|medium|high|xhigh` and `fast=false|true`; it does not advertise context variants. The Cursor default variant is `effort=high` and `fast=true`.
638
+ Supports `effort=low|medium|high|xhigh` and `fast=false|true`; it does not advertise a context parameter. The Cursor default variant is `effort=high` and `fast=true`.
706
639
 
707
640
  ```text
708
641
  cursor/grok-4.6
709
- cursor/grok-4.6:fast
710
- cursor/grok-4.6:slow
711
642
  ```
712
643
 
713
- Fast toggle maps to the Cursor `fast` parameter. `--cursor-no-fast` and `:slow` send `fast=false`.
644
+ Fast toggle maps to the Cursor `fast` parameter. `--cursor-no-fast` sends `fast=false`.
714
645
 
715
646
  `shift+tab` maps the available low, medium, high, and xhigh levels to Cursor `effort`; levels without a catalog value do not invent one.
716
647
 
@@ -719,9 +650,9 @@ Fast toggle maps to the Cursor `fast` parameter. `--cursor-no-fast` and `:slow`
719
650
  Before calling done:
720
651
 
721
652
  1. Unit tests:
722
- - context-variant model IDs
653
+ - one canonical model ID per catalog item
723
654
  - dynamic capability discovery
724
- - context variant registration and decoding
655
+ - default-context parameter and metadata selection
725
656
  - fast extension state and status behavior
726
657
  - Cursor SDK mode session/CLI state and status behavior
727
658
  - `reasoning` mapping
@@ -735,7 +666,7 @@ Before calling done:
735
666
 
736
667
  2. Runtime checks:
737
668
  - `pi --list-models cursor`
738
- - confirm context variants show expected `context` column
669
+ - confirm each catalog item appears once with its default context window
739
670
  - launch interactive with Cursor
740
671
  - verify default pi footer remains unchanged
741
672
  - verify Cursor status appears only for Cursor models
@@ -744,16 +675,14 @@ Before calling done:
744
675
  - verify Cursor `plan` status appears only in non-default mode and combines with status as `cursor · fast:n/a · plan`, `cursor · fast:on · plan`, or `cursor · fast:off · plan`
745
676
  - verify non-cursor footer/status unchanged
746
677
  - verify `shift+tab` uses pi native thinking
747
- - verify context changes through native model selection
748
678
  - verify resume restores model, thinking, and Cursor-only state
749
679
 
750
680
  3. Print mode:
751
- - `pi --model cursor/gpt-5.5@1m:medium -p "Say ok only"`
752
- - `pi --model cursor/gpt-5.5@272k --thinking xhigh -p "Say ok only"`
753
- - `pi --model cursor/claude-opus-4-7@1m --thinking max -p "Say ok only"`
754
- - `pi --model cursor/gpt-5.5@1m --cursor-fast -p "Say ok only"`
755
- - `pi --model cursor/gpt-5.5@1m --cursor-mode plan -p "Say ok only"`
756
- - confirm requests use selected context, pi thinking, fast flag state, and SDK-native mode
681
+ - `pi --model cursor/gpt-5.5:medium -p "Say ok only"`
682
+ - `pi --model cursor/claude-opus-4-7 --thinking max -p "Say ok only"`
683
+ - `pi --model cursor/gpt-5.5 --cursor-fast -p "Say ok only"`
684
+ - `pi --model cursor/gpt-5.5 --cursor-mode plan -p "Say ok only"`
685
+ - confirm requests use the default context, pi thinking, fast flag state, and SDK-native mode
757
686
 
758
687
  4. Tool bridge and replay:
759
688
  - `npm test -- test/cursor-pi-tool-bridge.test.ts test/cursor-pi-tool-bridge-call-timeout.test.ts test/cursor-provider-bridge-mcp.test.ts test/cursor-live-run-coordinator.test.ts test/cursor-mcp-timeout-override.test.ts`
@@ -23,12 +23,11 @@ Cursor SDK `plan` mode (`--cursor-mode plan` or `/cursor-mode plan`) can make Cu
23
23
 
24
24
  ## Local pi bridge summary
25
25
 
26
- The bridge is enabled by default when bridgeable active pi tools exist. Cursor sees bridge-owned MCP names such as `pi__sem_reindex`, while pi history and tool cards use the real pi tool name such as `sem_reindex`. The bridge hides overlapping built-in pi tools by default because Cursor already has native equivalents; extension/custom tools and non-overlapping active tools present in pi's active tool registry normally remain exposed. pi-cursor-sdk also registers `cursor_ask_question` for Cursor models when the bridge is enabled and default-on `PI_CURSOR_ASK_QUESTION` is left on, exposed to Cursor as `pi__cursor_ask_question`, so Cursor can ask the user to choose instead of silently defaulting when the pi UI is available. When pi has visible Agent Skills loaded, pi-cursor-sdk registers `cursor_activate_skill`, exposed as `pi__cursor_activate_skill`, so Cursor can load the full pi `SKILL.md` that corresponds to the current pi skill catalog. The bridge does not call pi tool `execute()` handlers directly; it queues the request, emits a real pi `toolCall`, waits for the matching pi `toolResult`, and resolves the Cursor MCP call back into the same live Cursor SDK run without creating a new `Agent`, unless the run was disposed, aborted, or cancelled.
26
+ The bridge is enabled by default when bridgeable active pi tools exist. Cursor sees bridge-owned MCP names such as `pi__sem_reindex`, while pi history and tool cards use the real pi tool name such as `sem_reindex`. The bridge hides overlapping built-in pi tools by default because Cursor already has native equivalents; extension/custom tools and non-overlapping active tools present in pi's active tool registry normally remain exposed. When pi has visible Agent Skills loaded, pi-cursor-sdk registers `cursor_activate_skill`, exposed as `pi__cursor_activate_skill`, so Cursor can load the full pi `SKILL.md` that corresponds to the current pi skill catalog. The bridge does not call pi tool `execute()` handlers directly; it queues the request, emits a real pi `toolCall`, waits for the matching pi `toolResult`, and resolves the Cursor MCP call back into the same live Cursor SDK run without creating a new `Agent`, unless the run was disposed, aborted, or cancelled.
27
27
 
28
28
  Rollback, timeout, and diagnostics controls:
29
29
 
30
30
  ```bash
31
- PI_CURSOR_ASK_QUESTION=0 pi --model cursor/grok-4.6
32
31
  PI_CURSOR_PI_TOOL_BRIDGE=0 pi --model cursor/grok-4.6
33
32
  PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1 pi --model cursor/grok-4.6
34
33
  PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS=7200 pi --model cursor/grok-4.6
@@ -39,7 +38,7 @@ PI_CURSOR_MCP_CONNECT_TIMEOUT_MS=5000 pi --model cursor/grok-4.6
39
38
  PI_CURSOR_PI_TOOL_BRIDGE_DEBUG=1 pi --model cursor/grok-4.6
40
39
  ```
41
40
 
42
- `PI_CURSOR_ASK_QUESTION=0` disables only `cursor_ask_question` / `pi__cursor_ask_question`, leaving the rest of the pi bridge available; it is enabled by default. `PI_CURSOR_PI_TOOL_BRIDGE=0` disables the bridge, including `pi__cursor_ask_question`. `PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1` opts in to exposing overlapping pi tool names that Cursor already has native equivalents for (`read`, `bash`, `write`, `edit`, `grep`, `find`, and `ls`). By default those names are hidden even when pi's Cursor replay wrapper has registered them as extension tools; non-overlapping active built-ins remain bridgeable by default. The installed Cursor SDK uses a 60-second MCP protocol default; pi-cursor-sdk overrides that seam by default with 3600 seconds for MCP `callTool` requests and 10 seconds for verified initialize/listTools requests on first send. Bridged calls also have a local fail-closed deadline capped by the effective MCP tool timeout; lower it with `PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS` to reject stale pending state and abort active pi execution sooner. Unknown MCP protocol timeout stacks keep the SDK default. `PI_CURSOR_PI_TOOL_BRIDGE_DEBUG=1` emits typed, allowlisted, scrubbed single-line JSONL bridge diagnostics to `process.stderr` with prefix `[pi-cursor-sdk:bridge]`; it is off by default, uses run-safe IDs that are not reused in endpoint paths, and does not print endpoint URLs/path components/tokens, raw args/results, file contents, or secrets. Cursor-native tools, Cursor settings, plugins, and configured Cursor MCP servers still come from the Cursor SDK local agent path.
41
+ `PI_CURSOR_PI_TOOL_BRIDGE=0` disables the bridge, including `pi__cursor_activate_skill`. `PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1` opts in to exposing overlapping pi tool names that Cursor already has native equivalents for (`read`, `bash`, `write`, `edit`, `grep`, `find`, and `ls`). By default those names are hidden even when pi's Cursor replay wrapper has registered them as extension tools; non-overlapping active built-ins remain bridgeable by default. The installed Cursor SDK uses a 60-second MCP protocol default; pi-cursor-sdk overrides that seam by default with 3600 seconds for MCP `callTool` requests and 10 seconds for verified initialize/listTools requests on first send. Bridged calls also have a local fail-closed deadline capped by the effective MCP tool timeout; lower it with `PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS` to reject stale pending state and abort active pi execution sooner. Unknown MCP protocol timeout stacks keep the SDK default. `PI_CURSOR_PI_TOOL_BRIDGE_DEBUG=1` emits typed, allowlisted, scrubbed single-line JSONL bridge diagnostics to `process.stderr` with prefix `[pi-cursor-sdk:bridge]`; it is off by default, uses run-safe IDs that are not reused in endpoint paths, and does not print endpoint URLs/path components/tokens, raw args/results, file contents, or secrets. Cursor-native tools, Cursor settings, plugins, and configured Cursor MCP servers still come from the Cursor SDK local agent path.
43
42
 
44
43
  ## What gets replayed
45
44
 
@@ -16,7 +16,7 @@ Record the required cutover validation here or in the final release handoff. The
16
16
  | --- | --- |
17
17
  | Command/session used | `npm run smoke:visual -- --ext "$PWD" --cwd "$PWD" --mode plan --out-dir <fresh /tmp dir> --label release-check --prompt <bounded prompt>` with default native-replay isolation |
18
18
  | Baseline versions | `pi --version` = 0.84.0; `npm ls` = `@cursor/sdk@1.0.30` and local `@earendil-works/*@0.84.0` |
19
- | Card categories checked | Claim only categories proven by both PNG and JSONL. Required cutover categories are read, grep/search, find/glob, shell success, write, edit/diff, and true read failure. Direct `ls`/list is tracked as optional because composer-2-5 does not route it through native `ls` reliably; source-enumeration coverage is gated through find/glob. Neutral Cursor plan/todo/task/mode activity is optional/opportunistic and only counts when JSONL contains a completed Cursor workflow event. |
19
+ | Card categories checked | Claim only categories proven by both PNG and JSONL. Required cutover categories are read, grep/search, find/glob, shell success, write, edit/diff, and true read failure. Direct `ls`/list is tracked as optional because composer-2.5 does not route it through native `ls` reliably; source-enumeration coverage is gated through find/glob. Neutral Cursor plan/todo/task/mode activity is optional/opportunistic and only counts when JSONL contains a completed Cursor workflow event. |
20
20
  | Observed status/card colors | Confirm native-looking cards use native pi styling; neutral Cursor activity is not red; true errors are distinct; diff previews show red/green; plan status is readable |
21
21
  | Screenshot/ANSI evidence location | External path only, for example `/tmp/pi-cursor-sdk-1016-visual.*/read-package.{ansi,txt,html,png,jsonl.path}` |
22
22
  | Debug artifact location | External `.debug/cursor-sdk-events/...` or temp artifact directory path only; do not commit raw artifacts |
@@ -238,7 +238,7 @@ npm pack --dry-run
238
238
  # -ne keeps a host `pi install` of this package from colliding with -e .
239
239
  SMOKE_DIR="$(mktemp -d /tmp/pi-cursor-sdk-release.XXXXXX)"
240
240
  PI_CURSOR_SETTING_SOURCES=none \
241
- pi -ne --approve -e . --cursor-no-fast --model cursor/grok-4.6:slow \
241
+ pi -ne --approve -e . --cursor-no-fast --model cursor/grok-4.6 \
242
242
  --session-dir "$SMOKE_DIR/session" --no-tools \
243
243
  -p 'Reply exactly: LIVE_PRINT_OK'
244
244