pi-cursor-sdk 0.2.0 → 0.3.7

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 (177) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +55 -51
  3. package/dist/bundled-context-windows.js +39 -0
  4. package/dist/context-window-cache.js +92 -0
  5. package/dist/context.js +353 -0
  6. package/dist/cursor-active-tools.js +3 -0
  7. package/dist/cursor-agent-message-web-tools.js +165 -0
  8. package/dist/cursor-agents-context-registration.js +17 -0
  9. package/dist/cursor-agents-context.js +127 -0
  10. package/dist/cursor-api-key.js +34 -0
  11. package/dist/cursor-bridge-contract.js +27 -0
  12. package/dist/cursor-cloud-lifecycle.js +650 -0
  13. package/dist/cursor-cloud-local-state.js +460 -0
  14. package/dist/cursor-cloud-options.js +145 -0
  15. package/dist/cursor-cloud-reporting.js +222 -0
  16. package/dist/cursor-compact-tool-summary.js +75 -0
  17. package/dist/cursor-config.js +613 -0
  18. package/dist/cursor-context-tools.js +6 -0
  19. package/dist/cursor-display-only-trace.js +11 -0
  20. package/dist/cursor-display-text.js +18 -0
  21. package/dist/cursor-durable-fs.js +53 -0
  22. package/dist/cursor-edit-diff.js +13 -0
  23. package/dist/cursor-env-boolean.js +19 -0
  24. package/dist/cursor-fallback-models.generated.js +7760 -0
  25. package/dist/cursor-fallback-warning.js +15 -0
  26. package/dist/cursor-http1.js +45 -0
  27. package/dist/cursor-incomplete-tool-visibility.js +83 -0
  28. package/dist/cursor-live-run-accounting.js +55 -0
  29. package/dist/cursor-live-run-coordinator.js +409 -0
  30. package/dist/cursor-mcp-timeout-override.js +116 -0
  31. package/dist/cursor-model-lifecycle.js +32 -0
  32. package/dist/cursor-model.js +5 -0
  33. package/dist/cursor-native-replay-routing.js +35 -0
  34. package/dist/cursor-native-replay-trace.js +28 -0
  35. package/dist/cursor-native-tool-display-registration.js +102 -0
  36. package/dist/cursor-native-tool-display-replay.js +428 -0
  37. package/dist/cursor-native-tool-display-state.js +70 -0
  38. package/dist/cursor-native-tool-display-tools.js +123 -0
  39. package/dist/cursor-native-tool-names.js +11 -0
  40. package/dist/cursor-partial-content-emitter.js +130 -0
  41. package/dist/cursor-pi-context.js +30 -0
  42. package/dist/cursor-pi-tool-bridge-abort.js +114 -0
  43. package/dist/cursor-pi-tool-bridge-constants.js +6 -0
  44. package/dist/cursor-pi-tool-bridge-diagnostics.js +125 -0
  45. package/dist/cursor-pi-tool-bridge-env.js +18 -0
  46. package/dist/cursor-pi-tool-bridge-mcp.js +100 -0
  47. package/dist/cursor-pi-tool-bridge-run.js +355 -0
  48. package/dist/cursor-pi-tool-bridge-server.js +163 -0
  49. package/dist/cursor-pi-tool-bridge-snapshot.js +63 -0
  50. package/dist/cursor-pi-tool-bridge-types.js +1 -0
  51. package/dist/cursor-pi-tool-bridge.js +123 -0
  52. package/dist/cursor-provider-errors.js +311 -0
  53. package/dist/cursor-provider-lazy.js +39 -0
  54. package/dist/cursor-provider-live-run-drain.js +420 -0
  55. package/dist/cursor-provider-overflow.js +90 -0
  56. package/dist/cursor-provider-run-finalizer.js +176 -0
  57. package/dist/cursor-provider-run-outcome.js +76 -0
  58. package/dist/cursor-provider-turn-coordinator.js +293 -0
  59. package/dist/cursor-provider-turn-display-router.js +158 -0
  60. package/dist/cursor-provider-turn-emit.js +41 -0
  61. package/dist/cursor-provider-turn-finalize.js +154 -0
  62. package/dist/cursor-provider-turn-lifecycle-emitter.js +126 -0
  63. package/dist/cursor-provider-turn-prepare.js +379 -0
  64. package/dist/cursor-provider-turn-runner.js +146 -0
  65. package/dist/cursor-provider-turn-sdk-normalizer.js +74 -0
  66. package/dist/cursor-provider-turn-send.js +138 -0
  67. package/dist/cursor-provider-turn-shell-output.js +117 -0
  68. package/dist/cursor-provider-turn-tool-ledger.js +99 -0
  69. package/dist/cursor-provider-turn-types.js +1 -0
  70. package/dist/cursor-provider.js +72 -0
  71. package/dist/cursor-question-tool.js +194 -0
  72. package/dist/cursor-record-utils.js +61 -0
  73. package/dist/cursor-replay-activity-builders.js +114 -0
  74. package/dist/cursor-replay-source-names.js +27 -0
  75. package/dist/cursor-replay-summary-args.js +105 -0
  76. package/dist/cursor-replay-tool-details.js +167 -0
  77. package/dist/cursor-ripgrep-path.js +27 -0
  78. package/dist/cursor-run-final-text.js +63 -0
  79. package/dist/cursor-runtime-state.js +380 -0
  80. package/dist/cursor-sdk-billed-usage.js +86 -0
  81. package/dist/cursor-sdk-event-debug-constants.js +33 -0
  82. package/dist/cursor-sdk-event-debug-session.js +107 -0
  83. package/dist/cursor-sdk-event-debug.js +461 -0
  84. package/dist/cursor-sdk-output-filter.js +1 -0
  85. package/dist/cursor-sdk-process-error-guard.js +221 -0
  86. package/dist/cursor-sdk-runtime.js +3 -0
  87. package/dist/cursor-sensitive-text.js +23 -0
  88. package/dist/cursor-session-agent-cleanup.js +311 -0
  89. package/dist/cursor-session-agent-lifecycle.js +32 -0
  90. package/dist/cursor-session-agent-lineage.js +103 -0
  91. package/dist/cursor-session-agent-resume.js +417 -0
  92. package/dist/cursor-session-agent.js +507 -0
  93. package/dist/cursor-session-compaction-prep.js +21 -0
  94. package/dist/cursor-session-scope.js +113 -0
  95. package/dist/cursor-session-send-policy.js +18 -0
  96. package/dist/cursor-session-store.js +105 -0
  97. package/dist/cursor-session-turn-queue.js +50 -0
  98. package/dist/cursor-setting-sources.js +15 -0
  99. package/dist/cursor-skill-tool.js +230 -0
  100. package/dist/cursor-state.js +519 -0
  101. package/dist/cursor-task-presentation.js +59 -0
  102. package/dist/cursor-tool-lifecycle.js +94 -0
  103. package/dist/cursor-tool-manifest.js +34 -0
  104. package/dist/cursor-tool-presentation-registry.js +305 -0
  105. package/dist/cursor-tool-result-display-readers.js +158 -0
  106. package/dist/cursor-tool-transcript.js +32 -0
  107. package/dist/cursor-tool-visibility.js +28 -0
  108. package/dist/cursor-transcript-tool-formatters.js +618 -0
  109. package/dist/cursor-transcript-tool-specs.js +284 -0
  110. package/dist/cursor-transcript-utils.js +170 -0
  111. package/dist/cursor-usage-accounting.js +166 -0
  112. package/dist/cursor-web-tool-activity.js +23 -0
  113. package/dist/cursor-web-tool-args.js +12 -0
  114. package/dist/index.js +82 -0
  115. package/dist/model-discovery.js +305 -0
  116. package/dist/model-list-cache.js +156 -0
  117. package/docs/cursor-dogfood-checklist.md +2 -1
  118. package/docs/cursor-live-smoke-checklist.md +13 -12
  119. package/docs/cursor-model-ux-spec.md +27 -6
  120. package/docs/cursor-native-tool-replay.md +13 -13
  121. package/docs/cursor-native-tool-visual-audit.md +6 -3
  122. package/docs/cursor-testing-lessons.md +14 -8
  123. package/docs/cursor-tool-surfaces.md +5 -5
  124. package/docs/platform-smoke.md +3 -3
  125. package/package.json +19 -7
  126. package/platform-smoke.config.mjs +1 -1
  127. package/scripts/build.mjs +126 -0
  128. package/scripts/cloud-runtime-smoke.mjs +3 -1
  129. package/scripts/debug-provider-events.mjs +3 -1
  130. package/scripts/debug-sdk-events.mjs +1 -1
  131. package/scripts/isolated-cursor-smoke.sh +5 -4
  132. package/scripts/lib/cloud-smoke-cleanup-evidence.mjs +1 -1
  133. package/scripts/lib/cursor-visual-render.mjs +1 -1
  134. package/scripts/lib/ensure-built.mjs +16 -0
  135. package/scripts/lib/local-resume-smoke-harness.mjs +1 -1
  136. package/scripts/local-resume-smoke.mjs +3 -1
  137. package/scripts/platform-smoke/card-detect.mjs +1 -1
  138. package/scripts/platform-smoke/live-suite-runner.mjs +1 -1
  139. package/scripts/platform-smoke/render-ansi.mjs +1 -1
  140. package/scripts/platform-smoke/targets.mjs +2 -2
  141. package/scripts/prepare.mjs +102 -0
  142. package/scripts/steering-rpc-smoke.mjs +4 -2
  143. package/scripts/tmux-live-smoke.sh +11 -11
  144. package/scripts/visual-tui-smoke-self-test.mjs +4 -1
  145. package/scripts/visual-tui-smoke.mjs +51 -7
  146. package/src/bundled-context-windows.ts +4 -1
  147. package/src/context.ts +27 -4
  148. package/src/cursor-agents-context-registration.ts +2 -2
  149. package/src/cursor-agents-context.ts +24 -10
  150. package/src/cursor-api-key.ts +5 -4
  151. package/src/cursor-cloud-reporting.ts +23 -2
  152. package/src/cursor-context-tools.ts +3 -1
  153. package/src/cursor-fallback-models.generated.ts +592 -204
  154. package/src/cursor-live-run-coordinator.ts +11 -6
  155. package/src/cursor-native-tool-display-registration.ts +10 -11
  156. package/src/cursor-partial-content-emitter.ts +13 -0
  157. package/src/cursor-pi-context.ts +44 -0
  158. package/src/cursor-provider-errors.ts +1 -1
  159. package/src/cursor-provider-lazy.ts +5 -4
  160. package/src/cursor-provider-live-run-drain.ts +14 -9
  161. package/src/cursor-provider-run-finalizer.ts +1 -0
  162. package/src/cursor-provider-turn-coordinator.ts +15 -0
  163. package/src/cursor-provider-turn-emit.ts +6 -0
  164. package/src/cursor-provider-turn-finalize.ts +12 -0
  165. package/src/cursor-provider-turn-prepare.ts +10 -5
  166. package/src/cursor-provider-turn-types.ts +2 -0
  167. package/src/cursor-sdk-billed-usage.ts +107 -0
  168. package/src/cursor-sdk-process-error-guard.ts +6 -4
  169. package/src/cursor-session-agent-lifecycle.ts +8 -9
  170. package/src/cursor-session-agent-resume.ts +23 -0
  171. package/src/cursor-session-compaction-prep.ts +4 -0
  172. package/src/cursor-skill-tool.ts +1 -1
  173. package/src/cursor-tool-manifest.ts +1 -1
  174. package/src/cursor-usage-accounting.ts +70 -9
  175. package/src/index.ts +1 -1
  176. package/tsconfig.build.json +8 -0
  177. package/tsconfig.json +16 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,78 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.7 - 2026-09-16
4
+
5
+ ### Fixed
6
+
7
+ - Preserve completed Cursor SDK assistant-message boundaries in streamed and persisted output: separate progress messages from the next message without splitting token chunks, duplicating the SDK final result, or adding whitespace to an exact final answer. Carry boundaries through local native-replay drain as well as direct/cloud turns.
8
+
9
+ - Support transcript-only Pi provider requests via the host's public replay helpers, without requiring those exports on stock Pi 0.84.0 or 0.85.1. Preserve current instructions, section updates, and explicit empty replay-tool snapshots.
10
+ - Fingerprint replayed instructions and tool definitions plus individual system-message content/section/tool deltas, so unchanged transcripts stay incremental and changed context reboots correctly.
11
+ - Preserve current Pi instructions in fresh cloud prompts, and ignore system updates when finding pending replay/bridge tool results and steering input.
12
+ - Handle Pi's XML-wrapped tool/rule/skill sections and project-context serialization without duplicating local rules or skill catalogs. Cloud keeps project instructions and omits the local skill catalog.
13
+
14
+ ## 0.3.6 - 2026-08-18
15
+
16
+ ### Fixed
17
+
18
+ - Isolate `smoke:visual` captures from the host: pi runs with `PI_CODING_AGENT_DIR=<out-dir>/pi-agent` (seeded `auth.json`, `quietStartup`, telemetry off), `PI_OFFLINE=1`, and `PI_SKIP_VERSION_CHECK=1`, so host extensions, skills, MCP config, update banners, and package-update notices no longer pollute visual evidence.
19
+ - Start the visual-smoke tmux session in `--cwd` with a non-login shell, eliminating `shell-init: getcwd` noise from a stale tmux-server working directory.
20
+ - Forward `--session-id` to pi only when explicitly provided, so fresh captures no longer show the new-session warning line; the HTML render labels pi-assigned sessions instead of failing.
21
+
22
+ ## 0.3.5 - 2026-08-18
23
+
24
+ ### Fixed
25
+
26
+ - Keep billed `getUsage()` rows as spend only. Occupancy `totalTokens` uses local turn-ended usage only when it is below the latest compaction `tokensBefore`, so a stale or cumulative Cursor total cannot restick the footer or retrigger auto-compact (#204).
27
+ - Leave local-resume persist suppressed across any `turn_end` that fires during compaction summarization; only `session_compact` clears the guard (#223).
28
+
29
+ ## 0.3.4 - 2026-08-18
30
+
31
+ ### Changed
32
+
33
+ - Pin the runtime to exact `@cursor/sdk@1.0.27` and recapture installed-package ripgrep, stalled-connection, HTTP/1.1, PR-control, closed-writable, and `getUsage` contracts against that pin.
34
+ - Refresh the 37-model Cursor fallback catalog and checkpoint-derived context-window snapshot from the live `@cursor/sdk@1.0.27` runtime, including Grok 4.6.
35
+ - Make `cursor/grok-4.6` the recommended local/smoke default (`:slow` for live evidence). Composer 2.5 remains in the catalog.
36
+
37
+ ### Added
38
+
39
+ - Apply billed `Agent.getUsage()` spend to pi assistant usage for local and cloud turns. Local billed rows are selected by unseen usage UUIDs (never by a client-minted `run-*` id). Cloud reports prefer mapped `AgentUsage` and keep the REST `/v1/agents/:id/usage` fallback.
40
+
41
+ ### Fixed
42
+
43
+ - Keep billed token spend when cumulative `inputTokens + outputTokens` exceeds the model context window, while occupancy `totalTokens` still uses in-window turn-ended occupancy or the post-compaction estimate floor.
44
+ - Ignore assistant occupancy at or before the latest `compactionSummary`, and ignore measurements at or above that summary's `tokensBefore`, so split-turn keep cannot restick the footer at the pre-compaction watermark.
45
+ - Drop compaction-summarizer local-resume handles: `session_before_compact` suppresses persist, and `session_compact` clears any pending handle so the first later `turn_end` cannot flush the one-message summarizer lineage (#223).
46
+ - Write smoke self-test fake `pi` helpers as ESM so Node 24 shebang execution can dump env without `require`.
47
+
48
+ ## 0.3.3 - 2026-08-14
49
+
50
+ ### Changed
51
+
52
+ - Hardened the precompiled import guard for legacy and future Pi package aliases plus `createRequire()` / `require.resolve()` escape hatches, while preserving the intentional Cursor SDK ripgrep resolution path.
53
+
54
+ ## 0.3.2 - 2026-08-14
55
+
56
+ ### Fixed
57
+
58
+ - Keep every Cursor runtime subtree that imports Pi host peers in Pi's static extension graph, preventing precompiled native `import()` from bypassing Pi's peer resolver after install-time dev-dependency pruning. This restores Cursor startup, native tool registration, provider turns, session-agent lifecycle, compaction, AGENTS.md deduplication, and stored Pi credential lookup from a pruned install.
59
+ - Retain safe lazy boundaries for the installed Cursor SDK, SQLite store, MCP bridge implementation, and generated fallback catalog, with an import-graph regression test that rejects future native dynamic imports reaching Pi host peers.
60
+
61
+ ## 0.3.1 - 2026-08-14
62
+
63
+ ### Changed
64
+
65
+ - `scripts/build.mjs` now reaps `dist.staging.<pid>` directories stranded by dead builds (SIGKILL or crash mid-emit) at the start of every build. Only pids already gone at the signal-0 probe are eligible; pid reuse in the tiny probe-to-remove window remains an inherent limitation. Reaping is best-effort: an unreapable strand warns instead of failing the build.
66
+ - `dist/` is now published by retrying this build's own `rename` instead of waiting on another build. A rename failure yields only when `dist/` exists and is non-empty (an existence check, not an errno check, so platforms that report a different code for rename-onto-existing-directory still behave correctly); otherwise the staging tree is retained and the rename retried, so this build can publish its own output rather than wait on a concurrent winner's scheduling. This closes the review-identified windows where a losing build could exit 1 while a concurrent winner was mid-swap or descheduled.
67
+ - `scripts/prepare.mjs` forwards build output on success too, so install-time diagnostics such as the concurrent-swap race-loss warning are no longer swallowed. If both the build and the final dev-dependency prune fail, the prune warning no longer masks the original build error (and may leave the dev toolchain for manual cleanup).
68
+ - New automated coverage for the staging swap: failed TypeScript emits preserve the previous `dist/`; successful builds purge stale files; dead-pid staging dirs are reaped while live ones survive; the real-process smoke narrows from three twelve-wide rounds to one four-way round; empty directories are not accepted as winners; slow winners cannot time out another build; and publish failures exhaust a bounded retry, fail loudly, and may leave `dist/` absent after removing the old output.
69
+
70
+ ## 0.3.0 - 2026-08-13
71
+
72
+ ### Changed
73
+
74
+ - The Pi extension manifest now loads precompiled `dist/index.js` instead of transpiling `src/index.ts` through jiti. This reduces load cost on cold starts and after cache invalidation (fresh installs, `pi update`, cache eviction); warm starts with a hot jiti cache were already near parity. A `prepare` lifecycle script builds `dist/` on install and update (including Pi's `npm install --omit=dev` flow) and prunes the dev toolchain back out afterwards.
75
+
3
76
  ## 0.2.0 - 2026-08-06
4
77
 
5
78
  ### Added
package/README.md CHANGED
@@ -41,7 +41,7 @@ pi install https://github.com/fitchmultz/pi-cursor-sdk
41
41
  2. Start pi with a Cursor model:
42
42
 
43
43
  ```bash
44
- pi --model cursor/composer-2-5
44
+ pi --model cursor/grok-4.6
45
45
  ```
46
46
 
47
47
  3. In pi, run `/login`, choose `Use an API key`, choose `Cursor`, and paste your Cursor SDK API key.
@@ -51,10 +51,10 @@ If pi started without a key, run `/cursor-refresh-models` after `/login` to refr
51
51
  ## Requirements
52
52
 
53
53
  - Node.js 22.19+
54
- - Pi 0.84.0 or later; pi core peer metadata remains optional and uses `"*"` ranges per Pi package guidance
54
+ - Pi 0.84.0 or later; stock Pi 0.84.0 and 0.85.1 are supported without a fork. Pi core peer metadata remains optional and uses `"*"` ranges per Pi package guidance
55
55
  - a Cursor SDK API key saved through `/login`, available as `CURSOR_API_KEY`, or passed with pi's `--api-key`
56
56
 
57
- No global `@cursor/sdk` install is required. This package depends on exact `@cursor/sdk@1.0.23`, so normal package installation brings in the SDK version this extension was built and tested against. Cursor SDK 1.0.23 declares its Node ConnectRPC transport dependency directly, so npm installs place `@connectrpc/connect-node` where the SDK can resolve it. The extension intentionally does not bundle `@cursor/sdk` or its platform packages, because packing from one maintainer OS can otherwise ship the wrong optional SDK binary for another OS. Cursor SDK 1.0.23 keeps the older `sqlite3 -> node-gyp@8` dependency chain out of the runtime tree, so deprecated install warnings for `inflight`, `rimraf`, `glob@7`, `npmlog`, `gauge`, `are-we-there-yet`, and `tar@6` from that chain are not expected. Older Pi and Cursor SDK compatibility paths are not maintained.
57
+ No global `@cursor/sdk` install is required. This package depends on exact `@cursor/sdk@1.0.27`, so normal package installation brings in the SDK version this extension was built and tested against. Cursor SDK 1.0.27 declares its Node ConnectRPC transport dependency directly, so npm installs place `@connectrpc/connect-node` where the SDK can resolve it. The extension intentionally does not bundle `@cursor/sdk` or its platform packages, because packing from one maintainer OS can otherwise ship the wrong optional SDK binary for another OS. Cursor SDK 1.0.27 keeps the older `sqlite3 -> node-gyp@8` dependency chain out of the runtime tree, so deprecated install warnings for `inflight`, `rimraf`, `glob@7`, `npmlog`, `gauge`, `are-we-there-yet`, and `tar@6` from that chain are not expected. Pi hosts that pass transcript-only provider contexts are also supported through their public replay helpers, detected at runtime; no fork-only API or dependency is required. Older Pi (before 0.84.0) and Cursor SDK compatibility paths are not maintained.
58
58
 
59
59
  ## Install
60
60
 
@@ -81,7 +81,7 @@ pi install -l npm:pi-cursor-sdk
81
81
  Pi 0.84.0 loads project-local extensions only after project trust is resolved, so this extension cannot observe that trust event. When a project-local install needs to read or write `.pi/cursor-sdk.json`, start every such run with explicit approval:
82
82
 
83
83
  ```bash
84
- pi --approve --model cursor/composer-2-5
84
+ pi --approve --model cursor/grok-4.6
85
85
  ```
86
86
 
87
87
  Without `--approve`, the project-local extension still runs after Pi trusts the project, but it ignores `.pi/cursor-sdk.json` and rejects `--save-project`; user config remains available.
@@ -91,10 +91,12 @@ Without `--approve`, the project-local extension still runs after Pi trusts the
91
91
  For development from this repository:
92
92
 
93
93
  ```bash
94
- npm install
95
- pi --approve -e . --model cursor/composer-2-5
94
+ npm install # runs prepare, which compiles src/ into dist/ (the manifest entry pi loads)
95
+ pi --approve -e . --model cursor/grok-4.6
96
96
  ```
97
97
 
98
+ After editing `src/`, run `npm run build` before the next `pi -e .` run, or pi loads the previous build.
99
+
98
100
  ## Configure your Cursor SDK API key
99
101
 
100
102
  `pi-cursor-sdk` passes an explicit API key to the Cursor SDK. It does **not** reuse Cursor Agent CLI login, Cursor Desktop login, or Cursor subscription/OAuth state shown by `agent status`.
@@ -104,7 +106,7 @@ Use either a user API key from Cursor Dashboard → API Keys or a service accoun
104
106
  Preferred setup:
105
107
 
106
108
  ```bash
107
- pi --model cursor/composer-2-5
109
+ pi --model cursor/grok-4.6
108
110
  ```
109
111
 
110
112
  Then, inside pi:
@@ -123,13 +125,13 @@ Environment setup:
123
125
 
124
126
  ```bash
125
127
  export CURSOR_API_KEY="your-key"
126
- pi --model cursor/composer-2-5
128
+ pi --model cursor/grok-4.6
127
129
  ```
128
130
 
129
131
  One-shot setup:
130
132
 
131
133
  ```bash
132
- pi --api-key "your-key" --model cursor/composer-2-5 --cursor-no-fast -p "Say ok only."
134
+ pi --api-key "your-key" --model cursor/grok-4.6 --cursor-no-fast -p "Say ok only."
133
135
  ```
134
136
 
135
137
  Startup discovery intentionally does not parse Pi CLI arguments. It uses the stored `cursor` key in `~/.pi/agent/auth.json`, then `CURSOR_API_KEY`; without either, the bundled fallback catalog registers. Provider turns still receive Pi's resolved `--api-key`. `/cursor-refresh-models` and `/cursor-cloud` mutations ask Pi's ModelRegistry for provider `cursor`, so command-time auth follows Pi's provider-scoped resolution and is normalized through `CURSOR_API_KEY` placeholders before reaching the Cursor SDK.
@@ -140,10 +142,10 @@ To avoid a live `Cursor.models.list` network round-trip on every pi startup, the
140
142
 
141
143
  ```bash
142
144
  # Cache lifetime in milliseconds (default 86400000 = 24h).
143
- PI_CURSOR_SDK_MODEL_CACHE_TTL_MS=3600000 pi --model cursor/composer-2-5
145
+ PI_CURSOR_SDK_MODEL_CACHE_TTL_MS=3600000 pi --model cursor/grok-4.6
144
146
 
145
147
  # Disable the cache and always discover live.
146
- PI_CURSOR_SDK_DISABLE_MODEL_CACHE=1 pi --model cursor/composer-2-5
148
+ PI_CURSOR_SDK_DISABLE_MODEL_CACHE=1 pi --model cursor/grok-4.6
147
149
  ```
148
150
 
149
151
  Do not store the API key in `~/.pi/agent/cursor-sdk.json`. That file is only for non-secret extension state such as Cursor fast defaults. `PATH` is only for executable lookup and should not contain the API key.
@@ -165,7 +167,7 @@ Expected behavior:
165
167
  Smoke test:
166
168
 
167
169
  ```bash
168
- pi --model cursor/composer-2-5 --cursor-no-fast --no-session --mode json \
170
+ pi --model cursor/grok-4.6 --cursor-no-fast --no-session --mode json \
169
171
  -p "Reply exactly PI_CURSOR_MODEL_OK and nothing else."
170
172
  ```
171
173
 
@@ -176,7 +178,7 @@ Expected: the final assistant text is `PI_CURSOR_MODEL_OK`. If auth is missing o
176
178
  Choose Cursor models interactively with `/model`, or pass a model on the command line:
177
179
 
178
180
  ```bash
179
- pi --model cursor/composer-2-5
181
+ pi --model cursor/grok-4.6
180
182
  pi --model cursor/gpt-5.5@1m
181
183
  pi --model cursor/gpt-5.5@272k
182
184
  pi --model cursor/claude-opus-4-8@300k
@@ -198,7 +200,7 @@ pi --model cursor/claude-opus-4-7@1m:max
198
200
  pi --model cursor/gpt-5.5@1m --thinking medium
199
201
  ```
200
202
 
201
- Cursor `context` becomes a pi-visible model variant because it changes pi's native `contextWindow`. For models that expose Cursor's boolean `fast` parameter, the extension also registers virtual `:fast` and `:slow` model aliases such as `cursor/composer-2-5:slow` and `cursor/gpt-5.5@1m:fast`. Those aliases are selection-only controls for subagents and workflow-spawned agents: they send the same Cursor SDK model ID plus an explicit `fast=true` or `fast=false` param, and they take precedence over saved `/cursor-fast` session/global defaults. Cursor SDK conversation mode remains extension state, not model identity. Alias model IDs use their selected SDK ID for Cursor-only state such as fast defaults, with read fallback for older defaults keyed by the underlying Cursor base model.
203
+ Cursor `context` becomes a pi-visible model variant because it changes pi's native `contextWindow`. For models that expose Cursor's boolean `fast` parameter, the extension also registers virtual `:fast` and `:slow` model aliases such as `cursor/grok-4.6:slow` and `cursor/gpt-5.5@1m:fast`. Those aliases are selection-only controls for subagents and workflow-spawned agents: they send the same Cursor SDK model ID plus an explicit `fast=true` or `fast=false` param, and they take precedence over saved `/cursor-fast` session/global defaults. Cursor SDK conversation mode remains extension state, not model identity. Alias model IDs use their selected SDK ID for Cursor-only state such as fast defaults, with read fallback for older defaults keyed by the underlying Cursor base model.
202
204
 
203
205
  ## Thinking support
204
206
 
@@ -233,13 +235,13 @@ For one run, force fast on or off without changing saved defaults:
233
235
 
234
236
  ```bash
235
237
  pi --model cursor/gpt-5.5@1m --cursor-fast -p "Say ok only"
236
- pi --model cursor/composer-2-5 --cursor-no-fast -p "Say ok only"
238
+ pi --model cursor/grok-4.6 --cursor-no-fast -p "Say ok only"
237
239
  ```
238
240
 
239
241
  For per-agent control, select the virtual model alias instead of mutating the shared saved default:
240
242
 
241
243
  ```bash
242
- pi --model cursor/composer-2-5:slow -p "Say ok only"
244
+ pi --model cursor/grok-4.6:slow -p "Say ok only"
243
245
  pi --model cursor/gpt-5.5@1m:fast -p "Say ok only"
244
246
  ```
245
247
 
@@ -269,8 +271,8 @@ Cursor SDK conversation mode is Cursor-only extension state. It is not a pi mode
269
271
  Default mode is `agent`. Start a one-shot run in a specific mode:
270
272
 
271
273
  ```bash
272
- pi --model cursor/composer-2-5 --cursor-mode agent
273
- pi --model cursor/composer-2-5 --cursor-mode plan
274
+ pi --model cursor/grok-4.6 --cursor-mode agent
275
+ pi --model cursor/grok-4.6 --cursor-mode plan
274
276
  ```
275
277
 
276
278
  Change the session mode interactively:
@@ -296,15 +298,15 @@ Cursor SDK `plan` mode can produce plan-oriented output and Cursor todo/plan act
296
298
  Cursor SDK local safety controls stay off by default. Enable them explicitly for one run:
297
299
 
298
300
  ```bash
299
- PI_CURSOR_AUTO_REVIEW=1 PI_CURSOR_SANDBOX=1 pi --model cursor/composer-2-5
300
- pi --model cursor/composer-2-5 --cursor-auto-review --cursor-sandbox
301
+ PI_CURSOR_AUTO_REVIEW=1 PI_CURSOR_SANDBOX=1 pi --model cursor/grok-4.6
302
+ pi --model cursor/grok-4.6 --cursor-auto-review --cursor-sandbox
301
303
  ```
302
304
 
303
305
  For manual stuck-run recovery only, explicitly force-expire the active persisted local SDK run before sending:
304
306
 
305
307
  ```bash
306
- PI_CURSOR_LOCAL_FORCE=1 pi --model cursor/composer-2-5
307
- pi --model cursor/composer-2-5 --cursor-local-force
308
+ PI_CURSOR_LOCAL_FORCE=1 pi --model cursor/grok-4.6
309
+ pi --model cursor/grok-4.6 --cursor-local-force
308
310
  ```
309
311
 
310
312
  This maps to the next actual `agent.send(..., { local: { force: true } })` only. SDK load, agent acquire, prompt preparation, or a pre-send abort does not consume it. A consumed CLI flag is not rearmed by session reload/tree lifecycle events; the environment override remains once per process. It is not a retry loop and does not cancel another live process's existing run handle; use it only when you know the persisted local run is wedged.
@@ -312,8 +314,8 @@ This maps to the next actual `agent.send(..., { local: { force: true } })` only.
312
314
  Branch-scoped local resume reattaches to recorded local SDK agents after a pi restart. It is on by default for local runtime and records agent IDs plus their SDK store identity only in pi session custom entries, never user/project config. Independently of resume, each local agent whose send is initiated is also recorded once per native pi session as a best-effort non-resumable `cursor-sdk-agent-lineage` custom entry at the `Agent.send()` boundary for forensic lineage; cloned/forked sessions record their own lineage under their new pi session ID. Disable resume per run with CLI/env, or persist an opt-out in config:
313
315
 
314
316
  ```bash
315
- pi --model cursor/composer-2-5 --cursor-no-local-resume
316
- PI_CURSOR_LOCAL_RESUME=0 pi --model cursor/composer-2-5
317
+ pi --model cursor/grok-4.6 --cursor-no-local-resume
318
+ PI_CURSOR_LOCAL_RESUME=0 pi --model cursor/grok-4.6
317
319
  ```
318
320
 
319
321
  Resume is strict: the current pi session file/id, branch path prefix, cwd/repo root, model/API/tool-surface pool key, SDK store identity, and compaction generation must match. Each persisted pi session gets a SQLite store under `<getDefaultSdkStateRoot(cwd)>/pi-sessions/<session-hash>/`, and that same store is used for create/resume, transcript reads, checkpoint lookup, and exact-ID cleanup so parallel pi sessions do not contend on one workspace `index.db`. Fileless sessions use a unique OS-temporary store per acquisition, remove it on graceful disposal, and start a fresh agent after invalidation instead of reopening a disposed temporary store. Legacy resume entries still try the SDK's default workspace store; if that resume fails or the agent is later replaced, the new agent moves to the per-session store. A trailing user message already present at process startup is crash-ambiguous and invalidates the old handle; only a user message appended in the current process may span a recorded handle, preventing restart from resending an already-submitted prompt. A successful process reattachment bootstraps the current pi transcript once while retaining the resumed Cursor agent's native state; later in-process turns remain incremental. If `Agent.resume()` fails, pi bootstraps a new local Cursor agent from the current transcript and streams one display-only continuity note. Superseded local agents can be cleaned up explicitly with `/cursor-local-resume-cleanup --dry-run` and `/cursor-local-resume-cleanup --yes`; cleanup only deletes exact recorded `agent-*` IDs from their recorded store. Cloud resume remains disabled; `/cursor-cloud list|archive|delete` only manages recorded cloud agents.
@@ -348,7 +350,7 @@ Project config may save a cloud runtime default but not first-use acknowledgemen
348
350
  Cursor Cloud pull-request controls are strictly opt-in. Omit them to preserve the Cursor SDK's default behavior; when omitted, the extension sends neither SDK field.
349
351
 
350
352
  ```bash
351
- pi --model cursor/composer-2-5 --cursor-runtime cloud --cursor-cloud-ack \
353
+ pi --model cursor/grok-4.6 --cursor-runtime cloud --cursor-cloud-ack \
352
354
  --cursor-cloud-repo https://github.com/your-org/your-repo \
353
355
  --cursor-cloud-branch main \
354
356
  --cursor-cloud-auto-create-pr --cursor-cloud-skip-reviewer-request
@@ -358,7 +360,7 @@ PI_CURSOR_CLOUD_REPO=https://github.com/your-org/your-repo \
358
360
  PI_CURSOR_CLOUD_BRANCH=main \
359
361
  PI_CURSOR_CLOUD_AUTO_CREATE_PR=1 \
360
362
  PI_CURSOR_CLOUD_SKIP_REVIEWER_REQUEST=1 \
361
- pi --model cursor/composer-2-5 --cursor-runtime cloud
363
+ pi --model cursor/grok-4.6 --cursor-runtime cloud
362
364
  ```
363
365
 
364
366
  User config uses `cloud.autoCreatePR` and `cloud.skipReviewerRequest`:
@@ -462,35 +464,35 @@ Bridge controls:
462
464
 
463
465
  ```bash
464
466
  # Keep the pi bridge but disable Cursor's interactive question tool.
465
- PI_CURSOR_ASK_QUESTION=0 pi --model cursor/composer-2-5
467
+ PI_CURSOR_ASK_QUESTION=0 pi --model cursor/grok-4.6
466
468
 
467
469
  # Roll back to Cursor SDK tools/settings/MCP only; do not expose active pi tools through the bridge.
468
- PI_CURSOR_PI_TOOL_BRIDGE=0 pi --model cursor/composer-2-5
470
+ PI_CURSOR_PI_TOOL_BRIDGE=0 pi --model cursor/grok-4.6
469
471
 
470
472
  # Opt in to also expose overlapping pi tool names through the bridge.
471
- PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1 pi --model cursor/composer-2-5
473
+ PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1 pi --model cursor/grok-4.6
472
474
 
473
475
  # Override Cursor SDK MCP tool-call timeout, including bridged pi tools and configured Cursor MCP servers.
474
- PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS=7200 pi --model cursor/composer-2-5
475
- PI_CURSOR_MCP_TOOL_TIMEOUT_MS=7200000 pi --model cursor/composer-2-5
476
+ PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS=7200 pi --model cursor/grok-4.6
477
+ PI_CURSOR_MCP_TOOL_TIMEOUT_MS=7200000 pi --model cursor/grok-4.6
476
478
 
477
479
  # Fail a stranded pi bridge CallTool sooner than the effective MCP tool timeout.
478
- PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS=120000 pi --model cursor/composer-2-5
480
+ PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS=120000 pi --model cursor/grok-4.6
479
481
 
480
482
  # Override known MCP initialize/listTools timeouts on first send (default 10s).
481
- PI_CURSOR_MCP_CONNECT_TIMEOUT_SECONDS=5 pi --model cursor/composer-2-5
482
- PI_CURSOR_MCP_CONNECT_TIMEOUT_MS=5000 pi --model cursor/composer-2-5
483
+ PI_CURSOR_MCP_CONNECT_TIMEOUT_SECONDS=5 pi --model cursor/grok-4.6
484
+ PI_CURSOR_MCP_CONNECT_TIMEOUT_MS=5000 pi --model cursor/grok-4.6
483
485
 
484
486
  # Force Cursor SDK local-agent backend streams to HTTP/1.1/SSE instead of HTTP/2.
485
- env 'PI_CURSOR_HTTP_1_1=true' pi --model cursor/composer-2-5
487
+ env 'PI_CURSOR_HTTP_1_1=true' pi --model cursor/grok-4.6
486
488
  # Or toggle it inside an interactive Cursor session.
487
489
  /cursor-http on
488
490
 
489
491
  # Disable bootstrap callable-surface manifest (on by default).
490
- PI_CURSOR_TOOL_MANIFEST=0 pi --model cursor/composer-2-5
492
+ PI_CURSOR_TOOL_MANIFEST=0 pi --model cursor/grok-4.6
491
493
 
492
494
  # Emit scrubbed bridge diagnostics as JSONL to stderr with prefix [pi-cursor-sdk:bridge].
493
- PI_CURSOR_PI_TOOL_BRIDGE_DEBUG=1 pi --model cursor/composer-2-5
495
+ PI_CURSOR_PI_TOOL_BRIDGE_DEBUG=1 pi --model cursor/grok-4.6
494
496
  ```
495
497
 
496
498
  On bootstrap sends, a compact **callable tool surfaces** block is injected into the Cursor prompt by default. It reminds the model that Cursor host/configured MCP tools are controlled by Cursor, while pi tool toggles only affect pi tools/bridge exposure; when bridge tools are exposed, it lists the current `pi__*` names. Disable with `PI_CURSOR_TOOL_MANIFEST=0`.
@@ -505,7 +507,7 @@ On bootstrap sends, a compact **callable tool surfaces** block is injected into
505
507
 
506
508
  For Cursor provider/runtime changes, the canonical local release and pre-commit gate is the local platform smoke gate in [Platform smoke](docs/platform-smoke.md): run `npm run smoke:platform:all`, which runs doctor before the target matrix. Cloud-runtime changes must also run `npm run smoke:cloud`. The platform gate validates macOS, Ubuntu, and Windows native through Crabbox using packed installs, a required HTTP/1.1/SSE provider-turn lane, PTY/ConPTY ANSI capture, host-rendered xterm/PNG evidence, JSONL assertions, bridge diagnostics, usage/cache checks, abort cleanup, artifact manifests, and redaction scans. After each platform run, `.artifacts/platform-smoke/latest.json` points to the latest useful evidence paths. Do not mark a release ready with optional, deferred, mostly-passing, or unobserved platform smoke checks outstanding.
507
509
 
508
- The older live smoke helpers remain useful for inner-loop debugging and focused visual audits, not as the release gate. Use [Cursor live smoke checklist](docs/cursor-live-smoke-checklist.md), `npm run smoke:visual`, `npm run smoke:live`, or direct `pi --approve -e . --cursor-no-fast --model cursor/composer-2-5` runs when iterating on a specific TUI/card/runtime issue before the full platform gate. `npm run smoke:visual` captures an offscreen PTY rendered through browser/xterm and saved as PNG screenshots with Playwright, or with `agent_browser` from the generated HTML when available. Its default matrix is native replay only: native replay registration is forced on, Cursor setting sources are disabled, the pi bridge is off, overlapping built-in pi tools are not exposed, and inherited Cursor SDK event-debug artifact env is cleared; `--event-debug` writes to a deterministic debug directory under the visual output directory. The visible TUI/output, rendered screenshots, scrubbed diagnostics, and persisted JSONL must agree. See [Cursor testing lessons](docs/cursor-testing-lessons.md) for auth.json seeding, isolated `/tmp` harness layout, JSONL replay-error scans, and other regression traps.
510
+ The older live smoke helpers remain useful for inner-loop debugging and focused visual audits, not as the release gate. Use [Cursor live smoke checklist](docs/cursor-live-smoke-checklist.md), `npm run smoke:visual`, `npm run smoke:live`, or direct `pi --approve -e . --cursor-no-fast --model cursor/grok-4.6` runs when iterating on a specific TUI/card/runtime issue before the full platform gate. `npm run smoke:visual` captures an offscreen PTY rendered through browser/xterm and saved as PNG screenshots with Playwright, or with `agent_browser` from the generated HTML when available. Its default matrix is native replay only: native replay registration is forced on, Cursor setting sources are disabled, the pi bridge is off, overlapping built-in pi tools are not exposed, and inherited Cursor SDK event-debug artifact env is cleared; `--event-debug` writes to a deterministic debug directory under the visual output directory. The visible TUI/output, rendered screenshots, scrubbed diagnostics, and persisted JSONL must agree. See [Cursor testing lessons](docs/cursor-testing-lessons.md) for auth.json seeding, isolated `/tmp` harness layout, JSONL replay-error scans, and other regression traps.
509
511
 
510
512
  ### Maintainer Cursor SDK event capture
511
513
 
@@ -519,7 +521,7 @@ See [Cursor testing lessons](docs/cursor-testing-lessons.md#cursor-sdk-event-cap
519
521
 
520
522
  If startup has no stored `/login` key or `CURSOR_API_KEY`, model discovery fails, or discovery returns no models, the extension registers a bundled fallback snapshot of the latest reviewed Cursor SDK model catalog and notifies interactive users when possible. Pi CLI `--api-key` remains available to provider turns but is not parsed independently during startup discovery.
521
523
 
522
- The fallback snapshot includes Composer 2.5 (`composer-2.5` and `composer-2-5`), Composer 2, Cursor's GPT-5.6 Luna/Sol/Terra models, Claude, Gemini, Grok, Kimi, and other model IDs exposed by the reviewed `Cursor.models.list()` output. Pi's separate `openai-codex` catalog is owned by Pi itself; Pi 0.84.0 includes native `gpt-5.6-luna`, `gpt-5.6-sol`, and `gpt-5.6-terra` support. The exact checked-in Cursor snapshot lives in `src/cursor-fallback-models.generated.ts`. A dated maintainer capture documents the assistant-visible [Cursor system prompts and tool guidance](https://github.com/fitchmultz/pi-cursor-sdk/blob/main/docs/evidence/cursor-system-prompts-2026-08-02/README.md) for Grok 4.5, Opus 5, Fable 5, and the GPT-5.6 Sol/Terra/Luna family.
524
+ The fallback snapshot includes Grok 4.6, Composer 2.5 (`composer-2.5` and `composer-2-5`), Composer 2, Cursor's GPT-5.6 Luna/Sol/Terra models, Claude, Gemini, Grok 4.5, Kimi, and other model IDs exposed by the reviewed `Cursor.models.list()` output. Recommended local/smoke runs use `cursor/grok-4.6`. Pi's separate `openai-codex` catalog is owned by Pi itself; Pi 0.84.0 includes native `gpt-5.6-luna`, `gpt-5.6-sol`, and `gpt-5.6-terra` support. The exact checked-in Cursor snapshot lives in `src/cursor-fallback-models.generated.ts`. A dated maintainer capture documents the assistant-visible [Cursor system prompts and tool guidance](https://github.com/fitchmultz/pi-cursor-sdk/blob/main/docs/evidence/cursor-system-prompts-2026-08-02/README.md) for Grok 4.5, Opus 5, Fable 5, and the GPT-5.6 Sol/Terra/Luna family.
523
525
 
524
526
  Actual Cursor runs still need a key from `/login`, `CURSOR_API_KEY`, or `--api-key`. If you add auth after startup, run `/cursor-refresh-models` to refresh the full live Cursor model catalog without restarting pi.
525
527
 
@@ -546,19 +548,19 @@ When a Cursor run fails after auth is configured, pi now surfaces scrubbed provi
546
548
 
547
549
  Aborted runs now include a likely cause when determinable, for example `Cancelled: prompt interrupted.` for user cancel or `Cancelled: Cursor SDK run was cancelled.` for SDK-side cancellation.
548
550
 
549
- Network failures from the Cursor SDK connect layer (for example `ConnectError: read ETIMEDOUT` or `ConnectError: [aborted] read ECONNRESET`) surface as scrubbed `Network error` messages instead of crashing pi, matching pi's native auto-retry classifier. The exact Cursor SDK 1.0.23-provenance `WriteIterableClosedError: WritableIterable is closed` race is contained for the Pi session lifecycle because controlled-exec can reject after the originating provider turn; Connect/network suppression remains active-turn scoped; raw Cursor SDK `AbortError` DOMExceptions are suppressed while any provider turn or session process-error guard is active (stall/inter-turn timers). Unrelated failures remain fatal. The observed raw `write EPIPE` uncaught exception (SDK 1.0.23 local shell executor writes child stdin without a stream error listener, so a child exiting mid-write surfaces a single-frame async pipe-write EPIPE) is contained only for that exact shape and only while a local Cursor provider turn is active; a contained closed pipe marks that turn's pooled/resumable agent transport dead so the next turn recreates it. EPIPE outside an active local turn, and the multi-frame synchronous write-path EPIPE from pi's own piped stdout or a dead terminal, stay fatal. The affected run may still report its underlying transport or tool failure normally. Persistent failures may indicate a transient Cursor service or network issue.
551
+ Network failures from the Cursor SDK connect layer (for example `ConnectError: read ETIMEDOUT` or `ConnectError: [aborted] read ECONNRESET`) surface as scrubbed `Network error` messages instead of crashing pi, matching pi's native auto-retry classifier. The exact Cursor SDK 1.0.23-provenance `WriteIterableClosedError: WritableIterable is closed` race is contained for the Pi session lifecycle because controlled-exec can reject after the originating provider turn; Connect/network suppression remains active-turn scoped; raw Cursor SDK `AbortError` DOMExceptions are suppressed while any provider turn or session process-error guard is active (stall/inter-turn timers). Unrelated failures remain fatal. The observed raw `write EPIPE` uncaught exception (SDK 1.0.23 local shell executor writes child stdin without a stream error listener; 1.0.27 attaches a no-op listener before that write) is still contained only for that exact one-frame shape and only while a local Cursor provider turn is active; a contained closed pipe marks that turn's pooled/resumable agent transport dead so the next turn recreates it. EPIPE outside an active local turn, and the multi-frame synchronous write-path EPIPE from pi's own piped stdout or a dead terminal, stay fatal. The affected run may still report its underlying transport or tool failure normally. Persistent failures may indicate a transient Cursor service or network issue.
550
552
 
551
553
  You can also restart pi with a key in the same shell or launcher that starts pi:
552
554
 
553
555
  ```bash
554
556
  export CURSOR_API_KEY="your-key"
555
- pi --model cursor/composer-2-5
557
+ pi --model cursor/grok-4.6
556
558
  ```
557
559
 
558
560
  Or run a one-shot command:
559
561
 
560
562
  ```bash
561
- pi --api-key "your-key" --model cursor/composer-2-5 -p "Say ok only"
563
+ pi --api-key "your-key" --model cursor/grok-4.6 -p "Say ok only"
562
564
  ```
563
565
 
564
566
  ### `pi --list-models cursor` shows no Cursor models
@@ -612,13 +614,13 @@ pi extension toggles and pi's MCP catalog do not control Cursor ambient MCP. Loc
612
614
  The local pi bridge only exposes tools that are active in the current pi session and present in pi's tool registry at Cursor run start. By default, it does not expose overlapping pi tool names that Cursor already has native equivalents for (`read`, `bash`, `write`, `edit`, `grep`, `find`, and `ls`). Opt in if you intentionally want Cursor to see both the Cursor-native tool and an overlapping built-in pi tool:
613
615
 
614
616
  ```bash
615
- PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1 pi --model cursor/composer-2-5
617
+ PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1 pi --model cursor/grok-4.6
616
618
  ```
617
619
 
618
620
  To disable the bridge for rollback or isolation, start pi with:
619
621
 
620
622
  ```bash
621
- PI_CURSOR_PI_TOOL_BRIDGE=0 pi --model cursor/composer-2-5
623
+ PI_CURSOR_PI_TOOL_BRIDGE=0 pi --model cursor/grok-4.6
622
624
  ```
623
625
 
624
626
  ### First Cursor message is slow (10+ seconds)
@@ -626,14 +628,14 @@ PI_CURSOR_PI_TOOL_BRIDGE=0 pi --model cursor/composer-2-5
626
628
  The extension loads Cursor setting sources with `PI_CURSOR_SETTING_SOURCES=all` by default, which includes user MCP servers from `~/.cursor/mcp.json`. On the first send of a session, the Cursor SDK connects to each configured MCP server before streaming a reply. pi-cursor-sdk shortens the known MCP initialize/listTools timeout path to **10 seconds by default** (the raw Cursor SDK default is 60 seconds), so a dead server should fail fast instead of blocking for a full minute. Unknown MCP protocol timeout stacks keep the SDK default instead of being shortened. A slow or unavailable server can still add roughly that connect timeout before the first reply. Tighten further with:
627
629
 
628
630
  ```bash
629
- PI_CURSOR_MCP_CONNECT_TIMEOUT_SECONDS=5 pi --model cursor/composer-2-5
630
- PI_CURSOR_MCP_CONNECT_TIMEOUT_MS=5000 pi --model cursor/composer-2-5
631
+ PI_CURSOR_MCP_CONNECT_TIMEOUT_SECONDS=5 pi --model cursor/grok-4.6
632
+ PI_CURSOR_MCP_CONNECT_TIMEOUT_MS=5000 pi --model cursor/grok-4.6
631
633
  ```
632
634
 
633
635
  Workarounds if you do not need user-level MCP in pi:
634
636
 
635
637
  ```bash
636
- PI_CURSOR_SETTING_SOURCES=project,plugins,team pi --model cursor/composer-2-5
638
+ PI_CURSOR_SETTING_SOURCES=project,plugins,team pi --model cursor/grok-4.6
637
639
  ```
638
640
 
639
641
  Or fix/disable the slow MCP server in Cursor settings. Maintainer timing probe: `npm run debug:mcp-coldstart`.
@@ -643,14 +645,14 @@ Or fix/disable the slow MCP server in Cursor settings. Maintainer timing probe:
643
645
  The extension raises Cursor SDK's MCP tool-call timeout from 60 seconds to 3600 seconds by default for Cursor SDK MCP `callTool` requests, including the local pi bridge and configured Cursor MCP servers. For longer local MCP tools, set one override:
644
646
 
645
647
  ```bash
646
- PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS=7200 pi --model cursor/composer-2-5
647
- PI_CURSOR_MCP_TOOL_TIMEOUT_MS=7200000 pi --model cursor/composer-2-5
648
+ PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS=7200 pi --model cursor/grok-4.6
649
+ PI_CURSOR_MCP_TOOL_TIMEOUT_MS=7200000 pi --model cursor/grok-4.6
648
650
  ```
649
651
 
650
652
  A bridged pi call additionally uses a local deadline capped by that effective MCP timeout. To fail a stranded bridge call sooner without shortening other MCP servers:
651
653
 
652
654
  ```bash
653
- PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS=120000 pi --model cursor/composer-2-5
655
+ PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS=120000 pi --model cursor/grok-4.6
654
656
  ```
655
657
 
656
658
  ### Tool calls appear as a plain text list instead of pi tool cards
@@ -703,9 +705,11 @@ Local development run:
703
705
 
704
706
  ```bash
705
707
  npm install
706
- CURSOR_API_KEY="your-key" pi --approve -e . --model cursor/composer-2-5
708
+ CURSOR_API_KEY="your-key" pi --approve -e . --model cursor/grok-4.6
707
709
  ```
708
710
 
711
+ After editing `src/`, run `npm run build` before the next `pi -e .` run, or pi loads the previous build.
712
+
709
713
  Maintainer design notes live in [`docs/cursor-model-ux-spec.md`](docs/cursor-model-ux-spec.md).
710
714
 
711
715
  ## License
@@ -0,0 +1,39 @@
1
+ // Generated from Cursor SDK checkpoint tokenDetails.maxTokens on 2026-08-18.
2
+ // Refresh with: npm run refresh:cursor-snapshots -- --write --context-windows ~/.pi/agent/cursor-sdk-context-windows.json
3
+ // Keys are current selectable model IDs. Equivalent default :fast/:slow selections
4
+ // collapse to one key; stale and ambiguous aliases are omitted. Values are observed
5
+ // or conservative default/non-Max-mode limits and may override a catalog context
6
+ // label when the completed SDK checkpoint reports a different effective limit.
7
+ export const BUNDLED_CONTEXT_WINDOWS = {
8
+ "default": 200000,
9
+ "auto-smart": 200000,
10
+ "claude-fable-5@300k": 300000,
11
+ "claude-haiku-4-5": 200000,
12
+ "claude-opus-4-5": 200000,
13
+ "claude-opus-4-8@1m": 300000,
14
+ "composer-2": 200000,
15
+ "composer-2.5": 200000,
16
+ "gemini-2.5-flash": 200000,
17
+ "gemini-3-flash": 200000,
18
+ "gemini-3.1-pro": 200000,
19
+ "gemini-3.5-flash": 200000,
20
+ "gemini-3.6-flash": 200000,
21
+ "gemini-3.7-flash": 200000,
22
+ "glm-5.2": 200000,
23
+ "gpt-5-5@272k": 272000,
24
+ "gpt-5-mini": 272000,
25
+ "gpt-5.1": 272000,
26
+ "gpt-5.2": 272000,
27
+ "gpt-5.3-codex": 272000,
28
+ "gpt-5.4-mini": 272000,
29
+ "gpt-5.4-nano": 272000,
30
+ "gpt-5.5@272k": 272000,
31
+ "gpt-5.6@1m": 272000,
32
+ "grok-4.5": 256000,
33
+ "grok-4.5:slow": 256000,
34
+ "grok-4.6": 256000,
35
+ "kimi-k2.7-code": 200000,
36
+ "kimi-k3": 200000,
37
+ "opus-4.8@1m": 300000,
38
+ "opus-4.8@300k": 300000,
39
+ };
@@ -0,0 +1,92 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
4
+ import { BUNDLED_CONTEXT_WINDOWS } from "./bundled-context-windows.js";
5
+ import { asRecord } from "./cursor-record-utils.js";
6
+ const CONTEXT_WINDOW_CACHE_FILE = "cursor-sdk-context-windows.json";
7
+ let userContextWindowOverrideLoadCount = 0;
8
+ function getCachePath() {
9
+ return join(getAgentDir(), CONTEXT_WINDOW_CACHE_FILE);
10
+ }
11
+ function isPositiveInteger(value) {
12
+ return typeof value === "number" && Number.isInteger(value) && value > 0;
13
+ }
14
+ function parseContextWindowCacheFile(value) {
15
+ const record = asRecord(value);
16
+ if (!record)
17
+ return undefined;
18
+ const { contextWindows } = record;
19
+ if (contextWindows === undefined)
20
+ return {};
21
+ const contextWindowRecord = asRecord(contextWindows);
22
+ if (!contextWindowRecord)
23
+ return undefined;
24
+ return {
25
+ contextWindows: Object.fromEntries(Object.entries(contextWindowRecord).filter((entry) => isPositiveInteger(entry[1]))),
26
+ };
27
+ }
28
+ function loadUserContextWindowOverrides() {
29
+ userContextWindowOverrideLoadCount += 1;
30
+ const path = getCachePath();
31
+ const overrides = new Map();
32
+ if (!existsSync(path))
33
+ return overrides;
34
+ try {
35
+ const parsed = parseContextWindowCacheFile(JSON.parse(readFileSync(path, "utf-8")));
36
+ for (const [modelId, contextWindow] of Object.entries(parsed?.contextWindows ?? {})) {
37
+ overrides.set(modelId, contextWindow);
38
+ }
39
+ }
40
+ catch {
41
+ return overrides;
42
+ }
43
+ return overrides;
44
+ }
45
+ export function loadContextWindowCache() {
46
+ const cache = new Map(Object.entries(BUNDLED_CONTEXT_WINDOWS));
47
+ for (const [modelId, contextWindow] of loadUserContextWindowOverrides()) {
48
+ cache.set(modelId, contextWindow);
49
+ }
50
+ return cache;
51
+ }
52
+ export function getCachedContextWindowExact(modelId) {
53
+ return loadContextWindowCache().get(modelId);
54
+ }
55
+ export function getCachedContextWindow(modelId) {
56
+ const cache = loadContextWindowCache();
57
+ return cache.get(modelId) ?? cache.get("default");
58
+ }
59
+ export function getCheckpointContextWindow(checkpoint) {
60
+ const tokenDetails = asRecord(checkpoint)?.tokenDetails;
61
+ const maxTokens = asRecord(tokenDetails)?.maxTokens;
62
+ return isPositiveInteger(maxTokens) ? maxTokens : undefined;
63
+ }
64
+ export function saveCachedContextWindow(modelId, contextWindow) {
65
+ if (!isPositiveInteger(contextWindow))
66
+ return;
67
+ const overrides = loadUserContextWindowOverrides();
68
+ const bundledContextWindow = BUNDLED_CONTEXT_WINDOWS[modelId] ?? BUNDLED_CONTEXT_WINDOWS.default;
69
+ if (bundledContextWindow === contextWindow) {
70
+ if (!overrides.has(modelId))
71
+ return;
72
+ overrides.delete(modelId);
73
+ }
74
+ else {
75
+ if (overrides.get(modelId) === contextWindow)
76
+ return;
77
+ overrides.set(modelId, contextWindow);
78
+ }
79
+ const path = getCachePath();
80
+ mkdirSync(dirname(path), { recursive: true });
81
+ const data = {
82
+ contextWindows: Object.fromEntries([...overrides.entries()].sort(([a], [b]) => a.localeCompare(b))),
83
+ };
84
+ writeFileSync(path, `${JSON.stringify(data, null, 2)}\n`, { mode: 0o600 });
85
+ }
86
+ export const __testUtils = {
87
+ getCachePath,
88
+ getUserContextWindowOverrideLoadCount: () => userContextWindowOverrideLoadCount,
89
+ resetUserContextWindowOverrideLoadCount: () => {
90
+ userContextWindowOverrideLoadCount = 0;
91
+ },
92
+ };