pi-cursor-sdk 0.5.3 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -1
- package/README.md +62 -816
- package/dist/context.js +11 -5
- package/dist/cursor-agents-context.js +6 -6
- package/dist/cursor-api-key.js +1 -1
- package/dist/cursor-bridge-contract.js +1 -13
- package/dist/cursor-cloud-local-state.js +0 -1
- package/dist/cursor-config.js +1 -17
- package/dist/cursor-fallback-models.generated.js +424 -1
- package/dist/cursor-live-run-coordinator.js +1 -0
- package/dist/cursor-local-run-terminal-error.js +57 -0
- package/dist/cursor-mcp-timeout-override.js +6 -17
- package/dist/cursor-native-tool-display-replay.js +5 -5
- package/dist/cursor-native-tools.js +11 -0
- package/dist/cursor-pi-tool-bridge-env.js +25 -2
- package/dist/cursor-pi-tool-bridge-server.js +98 -48
- package/dist/cursor-pi-tool-bridge-snapshot.js +1 -1
- package/dist/cursor-pi-tool-bridge.js +4 -12
- package/dist/cursor-provider-errors.js +0 -6
- package/dist/cursor-provider-live-run-drain.js +8 -3
- package/dist/cursor-provider-overflow.js +7 -21
- package/dist/cursor-provider-turn-finalize.js +2 -0
- package/dist/cursor-provider-turn-prepare.js +8 -1
- package/dist/cursor-provider-turn-runner.js +17 -6
- package/dist/cursor-provider-turn-send.js +3 -0
- package/dist/cursor-provider.js +1 -4
- package/dist/cursor-runtime-state.js +3 -3
- package/dist/cursor-sdk-event-debug.js +2 -2
- package/dist/cursor-sdk-output-filter.js +1 -1
- package/dist/cursor-sdk-process-error-guard.js +1 -2
- package/dist/cursor-session-agent.js +6 -8
- package/dist/cursor-session-scope.js +1 -7
- package/dist/cursor-session-store.js +3 -2
- package/dist/cursor-state.js +9 -23
- package/dist/cursor-tool-lifecycle.js +0 -3
- package/dist/cursor-tool-manifest.js +3 -1
- package/dist/cursor-tool-presentation-registry.js +2 -4
- package/dist/cursor-tool-visibility.js +0 -3
- package/dist/cursor-transcript-tool-specs.js +1 -2
- package/dist/index.js +21 -0
- package/dist/model-discovery.js +0 -1
- package/dist/model-list-cache.js +4 -9
- package/docs/cursor-live-smoke-checklist.md +4 -4
- package/docs/cursor-model-ux-spec.md +18 -8
- package/docs/cursor-native-tool-replay.md +2 -2
- package/docs/cursor-native-tool-visual-audit.md +1 -1
- package/docs/cursor-testing-lessons.md +22 -4
- package/docs/cursor-tool-surfaces.md +32 -3
- package/docs/development.md +101 -0
- package/docs/platform-smoke-implementation.md +3 -2
- package/docs/reference.md +810 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/package.json +1 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/versions.js +1 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/package.json +1 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/versions.js +1 -1
- package/package.json +14 -6
- package/scripts/platform-smoke/artifact-secrets.mjs +13 -4
- package/scripts/platform-smoke/local-resume-runner.mjs +0 -1
- package/scripts/platform-smoke/target-runtime.mjs +4 -2
- package/scripts/platform-smoke/targets.mjs +0 -1
- package/scripts/steering-rpc-smoke.mjs +1 -1
- package/shared/cursor-sdk-output-filter.d.mts +2 -0
- package/shared/cursor-sdk-output-filter.mjs +92 -28
- package/shared/cursor-sensitive-text.d.mts +1 -0
- package/shared/cursor-sensitive-text.mjs +7 -0
- package/src/context.ts +16 -9
- package/src/cursor-agents-context.ts +6 -6
- package/src/cursor-api-key.ts +1 -1
- package/src/cursor-bridge-contract.ts +1 -15
- package/src/cursor-cloud-local-state.ts +0 -2
- package/src/cursor-config.ts +1 -24
- package/src/cursor-fallback-models.generated.ts +424 -1
- package/src/cursor-live-run-coordinator.ts +5 -0
- package/src/cursor-local-run-terminal-error.ts +58 -0
- package/src/cursor-mcp-timeout-override.ts +6 -30
- package/src/cursor-native-tool-display-replay.ts +4 -6
- package/src/cursor-native-tools.ts +14 -0
- package/src/cursor-pi-tool-bridge-env.ts +31 -2
- package/src/cursor-pi-tool-bridge-server.ts +89 -45
- package/src/cursor-pi-tool-bridge-snapshot.ts +0 -1
- package/src/cursor-pi-tool-bridge.ts +2 -18
- package/src/cursor-provider-errors.ts +0 -8
- package/src/cursor-provider-live-run-drain.ts +8 -2
- package/src/cursor-provider-overflow.ts +6 -24
- package/src/cursor-provider-turn-finalize.ts +2 -0
- package/src/cursor-provider-turn-prepare.ts +10 -1
- package/src/cursor-provider-turn-runner.ts +17 -6
- package/src/cursor-provider-turn-send.ts +2 -0
- package/src/cursor-provider.ts +0 -5
- package/src/cursor-runtime-state.ts +3 -3
- package/src/cursor-sdk-event-debug.ts +2 -2
- package/src/cursor-sdk-output-filter.ts +2 -1
- package/src/cursor-sdk-process-error-guard.ts +1 -3
- package/src/cursor-session-agent.ts +8 -8
- package/src/cursor-session-scope.ts +1 -9
- package/src/cursor-session-store.ts +3 -2
- package/src/cursor-state.ts +9 -36
- package/src/cursor-tool-lifecycle.ts +0 -4
- package/src/cursor-tool-manifest.ts +4 -1
- package/src/cursor-tool-presentation-registry.ts +3 -5
- package/src/cursor-tool-visibility.ts +0 -4
- package/src/cursor-transcript-tool-specs.ts +0 -3
- package/src/index.ts +18 -0
- package/src/model-discovery.ts +0 -1
- package/src/model-list-cache.ts +4 -10
package/README.md
CHANGED
|
@@ -1,886 +1,132 @@
|
|
|
1
1
|
# pi-cursor-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use Cursor models in [Pi](https://pi.dev)'s terminal UI. `pi-cursor-sdk` runs Cursor's SDK agent and connects it to Pi sessions and extension tools.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+

|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Use `pi-cursor-sdk` when you primarily want to use Cursor models **inside pi**.
|
|
10
|
-
|
|
11
|
-
This extension runs Cursor models through `@cursor/sdk` and keeps Cursor's agent loop intact. Local remains the default; explicit cloud runtime starts Cursor Cloud after acknowledgement and preflight. pi integrates around that loop: model discovery, model selection, context-window variants, thinking controls where Cursor exposes them, fast/slow aliases, Cursor mode, session handling, native replay cards, and the optional local pi tool bridge.
|
|
12
|
-
|
|
13
|
-
OpenAI-compatible Cursor proxies are useful when you want a generic `/v1/chat/completions` or `/v1/responses` endpoint for many clients such as curl, the OpenAI SDK, OpenCode, or other tools. That compatibility comes from translating Cursor behavior into OpenAI-shaped requests, responses, and tool calls.
|
|
14
|
-
|
|
15
|
-
For pi users, that translation is usually the wrong abstraction. `pi-cursor-sdk` is pi-specific on purpose: it lets Cursor remain Cursor while making it feel native in pi.
|
|
16
|
-
|
|
17
|
-
| If you want... | Prefer |
|
|
18
|
-
| --- | --- |
|
|
19
|
-
| First-class Cursor usage inside pi | `pi-cursor-sdk` |
|
|
20
|
-
| Cursor's local SDK agent loop preserved, not replaced by an OpenAI-shaped adapter | `pi-cursor-sdk` |
|
|
21
|
-
| pi model picker, `/login`, `/model`, sessions, context display, footer/status UX | `pi-cursor-sdk` |
|
|
22
|
-
| Cursor SDK local-agent tools, settings, MCP, and native replay surfaced in pi | `pi-cursor-sdk` |
|
|
23
|
-
| pi extension tools exposed to Cursor through a local MCP bridge | `pi-cursor-sdk` |
|
|
24
|
-
| A generic OpenAI-compatible localhost `/v1` API for non-pi clients | An OpenAI-compatible Cursor proxy |
|
|
25
|
-
| One Cursor-ish endpoint shared across several unrelated tools | An OpenAI-compatible Cursor proxy |
|
|
7
|
+
*The agent runs locally. It sends model requests to Cursor and returns replies and tool activity to Pi.*
|
|
26
8
|
|
|
27
9
|
## Quick start
|
|
28
10
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
pi install npm:pi-cursor-sdk
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Or install from GitHub:
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
pi install https://github.com/fitchmultz/pi-cursor-sdk
|
|
39
|
-
```
|
|
11
|
+
Requirements: Node.js, Pi, and an API key for Cursor SDK. Check the [supported Node.js and Pi versions](docs/reference.md#requirements). The package installs `@cursor/sdk` for you.
|
|
40
12
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
pi --model cursor/grok-4.6
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
3. In pi, run `/login`, choose `Use an API key`, choose `Cursor`, and paste your Cursor SDK API key.
|
|
48
|
-
|
|
49
|
-
If pi started without a key, run `/cursor-refresh-models` after `/login` to refresh the full live Cursor model catalog without restarting pi. Inside pi, use `/model` to choose another Cursor model.
|
|
50
|
-
|
|
51
|
-
## Requirements
|
|
52
|
-
|
|
53
|
-
- Node.js 24+
|
|
54
|
-
- pi-cursor-sdk 0.5.3 requires official Pi 0.87.1 or later. The latest stable official Pi and current `fitchmultz/pi` main are required compatibility targets, resolved once per workflow run; locked development Pi packages are reproducible snapshots, not validation targets
|
|
55
|
-
- optional Pi and TypeBox peer metadata uses `"*"` ranges per Pi package guidance
|
|
56
|
-
- a Cursor SDK API key saved through `/login`, available as `CURSOR_API_KEY`, or passed with pi's `--api-key`
|
|
57
|
-
|
|
58
|
-
No global `@cursor/sdk` install is required. This package depends on exact `@cursor/sdk@1.0.37`, so normal package installation brings in that SDK. The extension intentionally does not bundle `@cursor/sdk` or its platform packages, because packing from one maintainer OS can ship the wrong optional SDK binary for another OS. The SDK has used its current single-file/new-chunk package layout since 1.0.28. Pi hosts that pass transcript-only provider contexts are supported through Pi 0.87.1's required public replay helpers.
|
|
59
|
-
|
|
60
|
-
## Install
|
|
61
|
-
|
|
62
|
-
### Global install
|
|
13
|
+
Use a user key from Cursor Dashboard → API Keys or a service-account key from Team settings. Team Admin keys do not work. Cursor Desktop and Agent CLI login do not supply the SDK key.
|
|
63
14
|
|
|
64
15
|
```bash
|
|
65
16
|
pi install npm:pi-cursor-sdk
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Alternative GitHub install:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
pi install https://github.com/fitchmultz/pi-cursor-sdk
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Existing extension filters
|
|
75
|
-
|
|
76
|
-
The Pi entrypoint is `dist/index.js`. If you changed extension filters for 0.3.8's `src/index.ts` entrypoint, restore their compiled-entry equivalents: `+src/index.ts` → `+dist/index.js`, `-src/index.ts` → `-dist/index.js`, and `!src/**` → `!dist/**`.
|
|
77
|
-
|
|
78
|
-
To keep Cursor disabled across both entrypoints, retain both `-src/index.ts` and `-dist/index.js`. The package does not rewrite user or project settings.
|
|
79
|
-
|
|
80
|
-
### Project-local install
|
|
81
|
-
|
|
82
|
-
Use `-l` if you want the package recorded in the current project's `.pi/settings.json` instead of your global pi settings:
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
pi install -l npm:pi-cursor-sdk
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
Pi 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:
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
pi --approve --model cursor/grok-4.6
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
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.
|
|
95
|
-
|
|
96
|
-
### Try from a local checkout
|
|
97
|
-
|
|
98
|
-
For development from this repository:
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
npm install # runs prepare, which compiles src/ into dist/ (the manifest entry pi loads)
|
|
102
|
-
pi --approve -e . --model cursor/grok-4.6
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
After editing `src/`, run `npm run build` before the next `pi -e .` run, or pi loads the previous build.
|
|
106
|
-
|
|
107
|
-
## Configure your Cursor SDK API key
|
|
108
|
-
|
|
109
|
-
`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`.
|
|
110
|
-
|
|
111
|
-
Use either a user API key from Cursor Dashboard → API Keys or a service account API key from Team settings. Team Admin API keys are not supported by the Cursor SDK. Then configure the key with one of the methods below.
|
|
112
|
-
|
|
113
|
-
Preferred setup:
|
|
114
|
-
|
|
115
|
-
```bash
|
|
116
17
|
pi --model cursor/grok-4.6
|
|
117
18
|
```
|
|
118
19
|
|
|
119
|
-
|
|
20
|
+
Inside Pi:
|
|
120
21
|
|
|
121
22
|
1. Run `/login`.
|
|
122
|
-
2. Select
|
|
123
|
-
3.
|
|
124
|
-
4.
|
|
125
|
-
5.
|
|
126
|
-
|
|
127
|
-
If pi started without a key, known fallback Cursor models still register so `/login` and CLI model selection remain reachable. Native login, logout, key rotation, and runtime-key changes immediately resync the matching cached catalog or fallback in the same session, without making a catalog request. Run `/cursor-refresh-models` for the full live catalog without restarting pi.
|
|
128
|
-
|
|
129
|
-
Set `PI_CURSOR_HIDE_MODELS_WHEN_LOGGED_OUT=1` to hide unauthenticated Cursor models from the picker and `--list-models`. This is off by default. Known model identities remain CLI-selectable, including `pi --model cursor/grok-4.6 --api-key "your-key"`; `/login` stays reachable. Stored logout does not hide models or delete the matching cache when environment or `models.json` auth remains. Pi's native logout also removes its runtime key override.
|
|
130
|
-
|
|
131
|
-
The default fallback availability policy is not proof of a usable key. A real Cursor SDK API key is still required for Cursor runs.
|
|
132
|
-
|
|
133
|
-
Environment setup:
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
export CURSOR_API_KEY="your-key"
|
|
137
|
-
pi --model cursor/grok-4.6
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
One-shot setup:
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
pi --api-key "your-key" --model cursor/grok-4.6 --cursor-no-fast -p "Say ok only."
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
Pi owns CLI parsing and credential storage. Cursor's public native API-key auth honors runtime keys, stored keys or provider-scoped `env.CURSOR_API_KEY`, composed `models.json` keys, then ambient `CURSOR_API_KEY`. Unresolved placeholder values are not real keys, and unsupported stored credential types do not fall through to ambient auth. Discovery receives the effective native key explicitly; it never reads an unrelated default auth file. Provider turns keep Pi's resolved request key. Environment or `models.json` changes take effect on the next native registry refresh (for example opening `/model`); there is no auth-file watcher.
|
|
147
|
-
|
|
148
|
-
### Model catalog cache
|
|
149
|
-
|
|
150
|
-
The discovered catalog is cached at `~/.pi/agent/cursor-sdk-model-list.json` (written `0600`, keyed by an API-key fingerprint — the key itself is never stored). Startup and native auth mutations are always cache-only: a matching cache, even if expired, or the bundled fallback supplies known models with zero catalog/network calls. The SDK remains in the static extension graph for compiled-Bun loading; cache-only does not mean zero SDK module evaluation. Pi may separately request a network-allowed refresh; fresh matching caches then skip the request. `/cursor-refresh-models` requests a forced native live refresh and reports cancellation or failure truthfully. Authenticated errors prefer the matching cached catalog over the generic fallback.
|
|
23
|
+
2. Select **Use an API key → Cursor**.
|
|
24
|
+
3. Paste your key.
|
|
25
|
+
4. Run `/cursor-refresh-models`.
|
|
26
|
+
5. Enter your prompt.
|
|
151
27
|
|
|
152
|
-
|
|
28
|
+
Keep your key out of `cursor-sdk.json` and shared logs. See [installation options](docs/reference.md#install) for GitHub and project-local installs.
|
|
153
29
|
|
|
154
|
-
|
|
30
|
+
## Models and controls
|
|
155
31
|
|
|
156
|
-
|
|
157
|
-
# Cache lifetime in milliseconds (default 86400000 = 24h).
|
|
158
|
-
PI_CURSOR_SDK_MODEL_CACHE_TTL_MS=3600000 pi --model cursor/grok-4.6
|
|
159
|
-
|
|
160
|
-
# Disable cache reads/writes; cache-only phases still use the fallback.
|
|
161
|
-
PI_CURSOR_SDK_DISABLE_MODEL_CACHE=1 pi --model cursor/grok-4.6
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
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
|
-
|
|
166
|
-
## Verify your setup
|
|
167
|
-
|
|
168
|
-
List Cursor models:
|
|
169
|
-
|
|
170
|
-
```bash
|
|
171
|
-
pi --list-models cursor
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
Expected behavior:
|
|
175
|
-
|
|
176
|
-
- with a valid key, Cursor models appear under the `cursor` provider
|
|
177
|
-
- if discovery cannot authenticate or reach Cursor, pi may still show fallback Cursor models; after adding auth with `/login`, fallback model runs can use the saved key, and `/cursor-refresh-models` refreshes the live catalog
|
|
178
|
-
|
|
179
|
-
Smoke test:
|
|
32
|
+
Use `/model` to select a model. Use these commands to select a model at startup:
|
|
180
33
|
|
|
181
34
|
```bash
|
|
182
|
-
pi --model cursor/grok-4.6 --cursor-no-fast --no-session --mode json \
|
|
183
|
-
-p "Reply exactly PI_CURSOR_MODEL_OK and nothing else."
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
Expected: the final assistant text is `PI_CURSOR_MODEL_OK`. If auth is missing or invalid, pi should tell you to configure a Cursor SDK API key via `/login`, `CURSOR_API_KEY`, or `--api-key`.
|
|
187
|
-
|
|
188
|
-
## Choosing a model
|
|
189
|
-
|
|
190
|
-
Choose Cursor models interactively with `/model`, or pass a model on the command line:
|
|
191
|
-
|
|
192
|
-
```bash
|
|
193
|
-
pi --model cursor/grok-4.6
|
|
194
|
-
pi --model cursor/gpt-5.5@1m
|
|
195
|
-
pi --model cursor/gpt-5.5@272k
|
|
196
|
-
pi --model cursor/claude-opus-4-8@300k
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
How to read model IDs:
|
|
200
|
-
|
|
201
|
-
- `cursor/...` is the Cursor provider registered by this extension
|
|
202
|
-
- `@1m`, `@272k`, and `@300k` are context-window variants
|
|
203
|
-
- `:medium`, `:high`, `:xhigh`, and `:max` are pi thinking-level suffixes for models where the Cursor SDK exposes the corresponding pi-controllable thinking parameter
|
|
204
|
-
- unambiguous latest-style Cursor aliases returned by `Cursor.models.list()` are registered too, using the same context suffixes when the target model has context variants; aliases shared by multiple base models or colliding with a base model ID are skipped because their SDK resolution and displayed metadata can diverge
|
|
205
|
-
|
|
206
|
-
Examples with pi thinking controls:
|
|
207
|
-
|
|
208
|
-
```bash
|
|
209
|
-
pi --model cursor/gpt-5.5@1m:medium
|
|
210
|
-
pi --model cursor/gpt-5.5@272k:xhigh
|
|
211
|
-
pi --model cursor/claude-opus-4-7@1m:max
|
|
212
35
|
pi --model cursor/gpt-5.5@1m --thinking medium
|
|
36
|
+
pi --model cursor/grok-4.6:slow
|
|
213
37
|
```
|
|
214
38
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
## Thinking support
|
|
218
|
-
|
|
219
|
-
All Cursor SDK models should be treated as thinking-capable Cursor models. The `thinking` column in `pi --list-models` is narrower: it only means pi can control a Cursor SDK thinking parameter for that model.
|
|
220
|
-
|
|
221
|
-
For models where Cursor exposes `reasoning`, `effort`, `reasoning_effort`, or boolean `thinking` parameters, pi's native thinking controls map to Cursor SDK params:
|
|
222
|
-
|
|
223
|
-
- `reasoning=none|low|medium|high|extra-high`
|
|
224
|
-
- `effort=low|medium|high|xhigh|max`
|
|
225
|
-
- `reasoning_effort=low|medium|high|xhigh|max` where exposed by the catalog
|
|
226
|
-
- `thinking=false|true` for boolean thinking models
|
|
227
|
-
|
|
228
|
-
Pi `xhigh` maps to Cursor `xhigh` or `extra-high`; Pi `max` maps only to a distinct Cursor `max` value. Gemini 3.8 Flash exposes only `low`, `medium`, and `high` through `reasoning_effort`; its SDK default remains `high`.
|
|
229
|
-
|
|
230
|
-
For Claude models with boolean `thinking` and either `effort` or `reasoning_effort`, enabled pi levels send `thinking=true` and the mapped effort value; `off` sends `thinking=false` and omits the effort parameter. Haiku 5.5 exposes all five enabled effort levels (`low`, `medium`, `high`, `xhigh`, `max`) at both `@300k` and `@1m`.
|
|
231
|
-
|
|
232
|
-
### Why some Cursor models show `thinking=no`
|
|
233
|
-
|
|
234
|
-
In `pi --list-models`, `thinking=no` means pi cannot control the model's thinking level with `--thinking`, a final `:medium` model suffix, or shift+tab. It does not mean the Cursor model cannot think.
|
|
235
|
-
|
|
236
|
-
Some Cursor SDK models do not expose a `reasoning`, `effort`, `reasoning_effort`, or `thinking` parameter for the extension to set. Cursor thinking is still enabled/supported by the model, and Cursor may still emit thinking deltas. The extension surfaces those deltas through pi's native thinking rendering when the SDK emits them.
|
|
237
|
-
|
|
238
|
-
## Fast mode
|
|
239
|
-
|
|
240
|
-
Use `/cursor-fast` to persistently toggle fast mode for the selected unsuffixed Cursor model when the model supports Cursor's `fast` parameter.
|
|
241
|
-
|
|
242
|
-
Fast preferences are remembered per selected Cursor SDK model ID or alias and stored:
|
|
243
|
-
|
|
244
|
-
- in the current session with `pi.appendEntry()`
|
|
245
|
-
- globally in `~/.pi/agent/cursor-sdk.json`
|
|
246
|
-
|
|
247
|
-
For one run, force fast on or off without changing saved defaults:
|
|
248
|
-
|
|
249
|
-
```bash
|
|
250
|
-
pi --model cursor/gpt-5.5@1m --cursor-fast -p "Say ok only"
|
|
251
|
-
pi --model cursor/grok-4.6 --cursor-no-fast -p "Say ok only"
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
For per-agent control, select the virtual model alias instead of mutating the shared saved default:
|
|
255
|
-
|
|
256
|
-
```bash
|
|
257
|
-
pi --model cursor/grok-4.6:slow -p "Say ok only"
|
|
258
|
-
pi --model cursor/gpt-5.5@1m:fast -p "Say ok only"
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
The `:fast` and `:slow` aliases are available only for Cursor models whose catalog exposes a `fast` parameter. They override saved `/cursor-fast` session/global defaults while leaving `--cursor-fast` and `--cursor-no-fast` as explicit process-level force flags. `/cursor-fast` does not persist a new default while a virtual fast/slow alias is selected; switch to the unsuffixed model first.
|
|
262
|
-
|
|
263
|
-
Composer 2 and Composer 2.5 can default to fast. Use `--cursor-no-fast` or a `:slow` virtual alias for a one-shot no-fast Composer run. In print mode (`-p`), `--cursor-no-fast` is silent and does not write `~/.pi/agent/cursor-sdk.json`.
|
|
264
|
-
|
|
265
|
-
In interactive mode, the footer shows Cursor status only while a Cursor model is active. Set `PI_CURSOR_FOOTER=0` to hide this status; it is visible by default. This controls display only: runtime, mode, and transport selection and validation are unchanged. Fast-capable models show fast state explicitly, and fast and plan mode share one Cursor status value so they do not overwrite each other:
|
|
266
|
-
|
|
267
|
-
```text
|
|
268
|
-
cursor:local · fast:n/a
|
|
269
|
-
cursor:local · fast:n/a · plan
|
|
270
|
-
cursor:local · fast:off
|
|
271
|
-
cursor:local · fast:on
|
|
272
|
-
cursor:local · fast:off · plan
|
|
273
|
-
cursor:local · fast:on · plan
|
|
274
|
-
cursor:local · fast:on · http1
|
|
275
|
-
cursor:cloud · fast:n/a
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
`cursor:local` / `cursor:cloud` shows the selected Cursor runtime. `fast:off` means fast mode is off. `fast:n/a` means the active runtime/model does not expose a local fast toggle. `http1` appears when HTTP/1.1/SSE transport is enabled for local Cursor SDK agents. If you do not see `plan`, Cursor SDK mode is the default `agent` mode.
|
|
279
|
-
|
|
280
|
-
## Cursor SDK mode
|
|
281
|
-
|
|
282
|
-
Cursor SDK conversation mode is Cursor-only extension state. It is not a pi model variant, not pi thinking/reasoning, not a `:fast`/`:slow` virtual fast alias, and not pi's separate read-only plan-mode extension.
|
|
283
|
-
|
|
284
|
-
Default mode is `agent`. Start a one-shot run in a specific mode:
|
|
285
|
-
|
|
286
|
-
```bash
|
|
287
|
-
pi --model cursor/grok-4.6 --cursor-mode agent
|
|
288
|
-
pi --model cursor/grok-4.6 --cursor-mode plan
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
Change the session mode interactively:
|
|
292
|
-
|
|
293
|
-
```text
|
|
294
|
-
/cursor-mode agent
|
|
295
|
-
/cursor-mode plan
|
|
296
|
-
/cursor-mode
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
`/cursor-mode` with no argument reports the current mode and usage. The CLI flag does not persist to the session; slash-command changes are persisted with `pi.appendEntry()`.
|
|
300
|
-
|
|
301
|
-
Maintainers can run `/cursor-tools` in a Cursor model session to print bridge/manifest enablement, effective `PI_CURSOR_SETTING_SOURCES`, and the current registry's bridge exposure eligibility. This is not a live-run connection or invocation check; use the [bridge diagnostics](#cursor-provider-tool-contract) below for per-run observations. See [Cursor dogfood checklist](docs/cursor-dogfood-checklist.md).
|
|
302
|
-
|
|
303
|
-
For conversation agents, the extension seeds the mode through `Agent.create({ mode })` and sends it on each `agent.send(..., { mode })` so `/cursor-mode` and `--cursor-mode` remain the source of truth when a pooled agent is reused. LOCAL compaction/tree summary agents always use text-only `agent` mode.
|
|
304
|
-
|
|
305
|
-
Cursor SDK `plan` mode can produce plan-oriented output and Cursor todo/plan activity, but those replay cards remain display-only. They do not drive pi's plan-mode extension, pi todos, or active tool state.
|
|
306
|
-
|
|
307
|
-
## Cursor local agent config and safety controls
|
|
308
|
-
|
|
309
|
-
`/cursor-refresh-config` calls the current pooled SDK agent's `agent.reload()` so Cursor reloads its filesystem config such as local hooks, project MCP, and Cursor-managed subagents without restarting pi. Extension `cursor-sdk.json` definitions below are captured on the next ordinary turn; changed definitions recreate the pooled agent instead of relying on SDK reload.
|
|
310
|
-
|
|
311
|
-
**Hook enforcement is not qualified by settings loading or replay cards.** SDK 1.0.37 source retains Shell `preToolUse` command-rewrite plumbing. The retained SDK 1.0.36 offline probe executed a rewritten command using private lexical bindings and permissive approval; it is not an executed SDK 1.0.37 canary. That is not an end-to-end Pi/rtk or security-policy guarantee. Replay may show the original model arguments before the SDK applies a rewrite. Verify the hook decision and actual executed command together when relying on hooks; the reported native-Agent/Pi discrepancy remains open in [#173](https://github.com/fitchmultz/pi-cursor-sdk/issues/173).
|
|
312
|
-
|
|
313
|
-
Cursor SDK local safety controls stay off by default. Enable them explicitly for one run:
|
|
314
|
-
|
|
315
|
-
```bash
|
|
316
|
-
PI_CURSOR_AUTO_REVIEW=1 PI_CURSOR_SANDBOX=1 pi --model cursor/grok-4.6
|
|
317
|
-
pi --model cursor/grok-4.6 --cursor-auto-review --cursor-sandbox
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
For manual stuck-run recovery only, explicitly force-expire the active persisted local SDK run before sending:
|
|
321
|
-
|
|
322
|
-
```bash
|
|
323
|
-
PI_CURSOR_LOCAL_FORCE=1 pi --model cursor/grok-4.6
|
|
324
|
-
pi --model cursor/grok-4.6 --cursor-local-force
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
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.
|
|
328
|
-
|
|
329
|
-
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:
|
|
330
|
-
|
|
331
|
-
```bash
|
|
332
|
-
pi --model cursor/grok-4.6 --cursor-no-local-resume
|
|
333
|
-
PI_CURSOR_LOCAL_RESUME=0 pi --model cursor/grok-4.6
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
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. By default, 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. With default storage selected, 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.
|
|
337
|
-
|
|
338
|
-
If a default local-store error names a rejected link or non-directory, make that SDK-owned prefix/component a real directory without discarding its data, or relocate via a link at a higher ancestor such as `~/.cursor/projects` instead. Custom roots reject user-controlled ancestor links too.
|
|
339
|
-
|
|
340
|
-
### Custom local SQLite root
|
|
341
|
-
|
|
342
|
-
For persistent LOCAL conversations, set `PI_CURSOR_SDK_STATE_ROOT` or user `~/.pi/agent/cursor-sdk.json`:
|
|
343
|
-
|
|
344
|
-
```json
|
|
345
|
-
{ "local": { "storeRoot": "/absolute/private/cursor-state" } }
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
Environment wins over user; blank values are absent. Project, session, CLI and built-in settings cannot select a root. With neither set, SDK-default storage/migration is unchanged. Selection is captured once per turn and at explicit cleanup entry, not reread after asynchronous work.
|
|
349
|
-
|
|
350
|
-
Custom layout: `<canonical-root>/<sha256(resolve(cwd))[0:32]>/pi-sessions/<session-hash>/`. Only extension SQLite/checkpoints move—not auth, settings/rules, model caches or IDE data. Fileless and LOCAL compaction/tree stores ignore persistent selection entirely, even when its path is unusable.
|
|
351
|
-
|
|
352
|
-
Use a fully qualified native absolute path, not a filesystem/share root, relative/device path, or a path with explicit `.`/`..` components. No tilde/environment expansion occurs. Invalid winning paths fail closed, never falling back to default. POSIX ancestors must be root/current-user owned and not group/other writable, except trusted sticky system temporary directories; after shared directories, components must belong to the current user. Owned destinations are private (0700). User-controlled links/junctions and linked/nonregular fixed SQLite files are rejected; verified root-owned system aliases such as macOS `/var` are supported.
|
|
353
|
-
|
|
354
|
-
On Windows, choose a user-controlled, ACL-protected location. Node-visible links/junctions, type, identity and writability are checked, but ACLs are not hardened and not every reparse-point type is guaranteed to be rejected. The SDK opens by pathname, including lazy checkpoints; these checks are not a sandbox against malicious same-user processes or administrators.
|
|
355
|
-
|
|
356
|
-
Changing root replaces a live pooled agent on the next turn and bootstraps from the Pi transcript. Custom resume/cleanup admits only the exact current custom **session** identity; identity-less legacy, SDK-default, other-root and other-session addresses are never reinterpreted. Old data is retained: no copy, migration, merge or automatic deletion. Run explicit cleanup **before** relocating if desired: cleanup at B can durably mark A's candidates non-retryable, and returning to A does not revive them. Manually retained state remains your responsibility after retiring its sessions and stopping their processes.
|
|
357
|
-
|
|
358
|
-
Config can also set non-secret defaults in `~/.pi/agent/cursor-sdk.json` or trusted `.pi/cursor-sdk.json`. Project config activates only when Pi's project-trust flow reached this extension and approved the project, or the run started with explicit `--approve`; Pi's implicit trust for a project with no recognized resources is not enough. Because project-local package extensions load after the trust event, `pi install -l` users must pass `--approve` on every run that reads or writes `.pi/cursor-sdk.json`. A trust resource added after trust resolution requires restarting pi. `/cursor-runtime ... --save-project` requires the same trust provenance and does not create Pi trust resources automatically. Explicit runtime, fast-default, and HTTP transport saves preserve unrecognized fields, reject malformed or non-object JSON without rewriting it, and serialize concurrent writers. A completed global preference write is retained if Pi's subsequent session-journal append fails, because Pi may already have mutated the in-memory branch; the command reports that partial journal failure and ignores the uncertain session entry until a later successful save or session restart. If a process is force-killed during the tiny update window, the next save reports the `.lock` path; remove it only after confirming no pi process is writing that config.
|
|
359
|
-
|
|
360
|
-
```json
|
|
361
|
-
{
|
|
362
|
-
"runtime": "local",
|
|
363
|
-
"local": {
|
|
364
|
-
"autoReview": true,
|
|
365
|
-
"sandboxOptions": { "enabled": true },
|
|
366
|
-
"resume": true
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
### SDK-native custom agents
|
|
372
|
-
|
|
373
|
-
Define named Cursor delegates in user `~/.pi/agent/cursor-sdk.json` or trusted project `.pi/cursor-sdk.json`:
|
|
374
|
-
|
|
375
|
-
```json
|
|
376
|
-
{
|
|
377
|
-
"subagents": {
|
|
378
|
-
"reviewer": {
|
|
379
|
-
"description": "Review code changes for correctness and maintainability.",
|
|
380
|
-
"prompt": "Inspect the changes and report concrete findings without editing.",
|
|
381
|
-
"model": "grok-4.6:slow",
|
|
382
|
-
"thinking": "high",
|
|
383
|
-
"fast": false
|
|
384
|
-
},
|
|
385
|
-
"helper": {
|
|
386
|
-
"description": "Investigate a focused question.",
|
|
387
|
-
"prompt": "Research the question and return concise evidence.",
|
|
388
|
-
"model": "inherit"
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
- Names follow this extension's policy: 1–64 characters, starting with an ASCII letter, then letters, digits, `.`, `_`, or `-`. Required `description` and `prompt` must be nonblank strings; text is trimmed. Invalid entries are skipped individually. Invalid optional `model`, `thinking`, or `fast` values are omitted; unsupported fields, including per-entry MCP, are not forwarded.
|
|
395
|
-
- A trusted project with any valid definitions replaces the **whole** user set, not individual names. Empty/all-invalid project sets fall back to user definitions. No CLI, environment, or session override exists. Keep definitions non-secret.
|
|
396
|
-
- `model` uses a registered Cursor model ID **without** the `cursor/` provider prefix; set thinking separately to `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max`. Omitted model and explicit `inherit` both inherit the parent model in SDK 1.0.37; `thinking`/`fast` do not override inherited models.
|
|
397
|
-
- Explicit models use catalog metadata for aliases, context and thinking. `:fast`/`:slow` wins over the entry's `fast`; unsuffixed models use entry `fast`, otherwise the catalog default. Parent thinking, `/cursor-fast`, saved fast defaults and process fast flags do not affect the definition. Unknown IDs pass through unchanged without invented parameters or a catalog request.
|
|
398
|
-
- **SDK 1.0.37 LOCAL ceiling:** its converter sends only the selected model ID or `inherit`, dropping all thinking/fast/context parameters. Thus `grok-4.6:slow` resolves to `grok-4.6`, but does not enforce child slow mode locally. Cloud conversion preserves the full selection; service acceptance/honoring of those parameters is not qualified here. Resource inheritance (`local.subagentInherit`) is not a model-parameter workaround.
|
|
399
|
-
- Definitions are passed through public SDK `agents` on ordinary create/resume and cloud creation. Changed resolved content replaces the local pooled agent on the next turn and rejects stale resume handles, bootstrapping from the Pi transcript; equivalent reordered content reuses it. Resume keys contain only a digest, not definition text. Removing all definitions restores the original no-feature key.
|
|
400
|
-
|
|
401
|
-
This is Cursor SDK-native delegation by configured name, not a second Pi subagent implementation. When exposed, `pi__subagent` remains preferred. LOCAL compaction/tree summary agents receive no definitions, tools, settings or MCP; bug-report streams retain ordinary capabilities.
|
|
402
|
-
|
|
403
|
-
### Cloud runtime and acknowledgement
|
|
404
|
-
|
|
405
|
-
Cloud/runtime keys are minimal and explicit. Defaults stay local runtime with the loopback MCP bridge as the sole Pi-tool transport, no inline cloud MCP, and no local-state/env-file forwarding. SDK `customTools` remains deferred pending SDK cancellation/deadline support. Invalid non-empty `--cursor-runtime`, `--cursor-cloud-context`, `PI_CURSOR_RUNTIME`, or `PI_CURSOR_CLOUD_CONTEXT` values fail closed instead of falling through to lower-precedence config.
|
|
406
|
-
|
|
407
|
-
If `runtime` is explicitly set to `cloud` with `--cursor-runtime cloud`, `PI_CURSOR_RUNTIME=cloud`, `/cursor-runtime cloud`, or config, the provider starts a Cursor cloud agent after preflight instead of silently running local.
|
|
408
|
-
|
|
409
|
-
On first interactive use, `/cursor-runtime cloud` shows one confirmation covering remote execution, fresh context by default (explicit bootstrap opt-in), unavailable Pi-local tools/bridge and Pi env forwarding, Cursor's ability to branch/commit/push/open PRs, retained cloud agents, and Max Mode billing at Cursor API pricing (including possible spend-limit setup). Cancelling that first-use confirmation writes no session or config state.
|
|
410
|
-
|
|
411
|
-
Use `/cursor-runtime cloud --save-user` for a persistent personal acknowledgement or `--cursor-cloud-ack` / `PI_CURSOR_CLOUD_ACK=1` for non-interactive runs; acknowledged CLI, environment, session, or user state is not prompted again.
|
|
412
|
-
|
|
413
|
-
Project config may save a cloud runtime default but not first-use acknowledgement or repo/branch/env/context/direct-push/PR-control/local-state preferences.
|
|
414
|
-
|
|
415
|
-
### Cloud pull-request controls
|
|
416
|
-
|
|
417
|
-
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.
|
|
418
|
-
|
|
419
|
-
```bash
|
|
420
|
-
pi --model cursor/grok-4.6 --cursor-runtime cloud --cursor-cloud-ack \
|
|
421
|
-
--cursor-cloud-repo https://github.com/your-org/your-repo \
|
|
422
|
-
--cursor-cloud-branch main \
|
|
423
|
-
--cursor-cloud-auto-create-pr --cursor-cloud-skip-reviewer-request
|
|
424
|
-
|
|
425
|
-
PI_CURSOR_CLOUD_ACK=1 \
|
|
426
|
-
PI_CURSOR_CLOUD_REPO=https://github.com/your-org/your-repo \
|
|
427
|
-
PI_CURSOR_CLOUD_BRANCH=main \
|
|
428
|
-
PI_CURSOR_CLOUD_AUTO_CREATE_PR=1 \
|
|
429
|
-
PI_CURSOR_CLOUD_SKIP_REVIEWER_REQUEST=1 \
|
|
430
|
-
pi --model cursor/grok-4.6 --cursor-runtime cloud
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
User config uses `cloud.autoCreatePR` and `cloud.skipReviewerRequest`:
|
|
434
|
-
|
|
435
|
-
```json
|
|
436
|
-
{
|
|
437
|
-
"runtime": "cloud",
|
|
438
|
-
"cloud": {
|
|
439
|
-
"autoCreatePR": true,
|
|
440
|
-
"skipReviewerRequest": true
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
The resolver follows cloud precedence (CLI, environment, session, then user) with user safety denials; project config is excluded. The current public inputs are CLI/environment one-shot controls and user config—there is no PR-control session command.
|
|
446
|
-
|
|
447
|
-
### Cloud repository and local-state validation
|
|
448
|
-
|
|
449
|
-
An explicit `--cursor-cloud-branch` / `PI_CURSOR_CLOUD_BRANCH` requires an explicit `--cursor-cloud-repo` / `PI_CURSOR_CLOUD_REPO` because the SDK exposes `startingRef` only on `cloud.repos` entries. Repository values must be HTTPS repository URLs without userinfo, query parameters, or fragments; invalid values fail before `Agent.create()`, and error scrubbing removes URL/SCP-style userinfo.
|
|
450
|
-
|
|
451
|
-
When an explicit cloud repo matches local Git state, preflight requires exactly one remote whose effective fetch and push URLs identify that target plus a locally observable, non-symbolic remote-tracking ref uniquely covered by that remote's fetch refspec for the requested branch. Local HTTPS remotes can match the same HTTPS identity; equivalent GitHub SSH and scp-style remotes can also match. Other hosts retain transport-specific identity, and host/path matching remains conservative with GitHub-specific case and lowercase `.git` normalization.
|
|
452
|
-
|
|
453
|
-
`refs/heads/<branch>` is normalized to `<branch>` for both inspection and SDK options; invalid Git branch names and other `refs/*` forms are rejected. An explicit repo without `startingRef` is unverifiable locally because the server default is unknown. Inside a Git worktree, full commit SHAs remain unverified and require the explicit local-state override because local tracking refs do not prove which matching remote contains that commit.
|
|
454
|
-
|
|
455
|
-
Mismatch, ambiguity, missing refs, or Git errors fail closed. This is local tracking evidence rather than a fetch, so fetch before starting cloud work when remote state may have changed.
|
|
39
|
+
The `cursor/` prefix selects this provider. `@1m` selects a context window from Cursor's catalog. `--thinking` sets the thinking level when Cursor exposes that control. Models with Cursor's `fast` parameter also have `:fast` and `:slow` choices.
|
|
456
40
|
|
|
457
|
-
|
|
41
|
+
Run `pi --list-models cursor` to see available models. Startup can use a cached or fallback catalog. A model in the list does not prove that your key works.
|
|
458
42
|
|
|
459
|
-
|
|
43
|
+
Run these commands inside Pi:
|
|
460
44
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
### Cloud reporting and durable lifecycle
|
|
468
|
-
|
|
469
|
-
When a pi session has a title, cloud agents are created with that title for easier dashboard/list matching.
|
|
470
|
-
|
|
471
|
-
At cloud run completion, pi streams display-only cloud telemetry when Cursor reports it: agent/run IDs, pushed branch, repository and PR URL, passive artifact paths, and raw cloud usage.
|
|
45
|
+
| Command | Action |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `/cursor-fast` | Toggle and save fast mode for the selected model, when supported. Select the model without `:fast` or `:slow` to change its default. |
|
|
48
|
+
| `/cursor-mode plan` | Use Cursor plan mode. Use `/cursor-mode agent` to return to agent mode. |
|
|
49
|
+
| `/cursor-refresh-config` | Reload filesystem settings in the current Cursor agent. |
|
|
472
50
|
|
|
473
|
-
|
|
51
|
+
For one run, pass `--cursor-fast`, `--cursor-no-fast`, or `--cursor-mode plan`. See the [model reference](docs/reference.md#choosing-a-model) for selection rules and [fast mode](docs/reference.md#fast-mode) for saved preferences.
|
|
474
52
|
|
|
475
|
-
|
|
53
|
+
The footer shows status such as `cursor:local · fast:off`, with `plan` or `http1` when enabled. Set `PI_CURSOR_FOOTER=0` to hide the Cursor status.
|
|
476
54
|
|
|
477
|
-
|
|
55
|
+
## Tools and settings
|
|
478
56
|
|
|
479
|
-
|
|
57
|
+
Cursor controls file tools, shell commands, edits, and configured MCP servers. The local MCP bridge exposes active Pi extension tools as `pi__*` names. The bridge is on by default. Pi hides matching built-ins from the bridge by default.
|
|
480
58
|
|
|
481
|
-
|
|
59
|
+
**Availability:** Some older releases **ignore `PI_CURSOR_NATIVE_TOOLS` and do not provide `/cursor-abort`**. Check your installed version against the [version boundary](docs/cursor-tool-surfaces.md#the-three-surfaces) before relying on either control; a development version label alone does not prove availability.
|
|
482
60
|
|
|
483
|
-
|
|
61
|
+
**Pi's `--no-tools`, `--tools`, and `--exclude-tools` do not disable Cursor tools or Cursor MCP servers.** For local ordinary turns on a supporting revision, opt in to `PI_CURSOR_NATIVE_TOOLS=0` to allow only MCP through the public SDK tool surface (including disabling native task/subagents). It leaves configured Cursor MCP available unless you also disable ambient setting sources. Cloud rejects this opt-out for both ordinary and selected-Cloud summary requests; only existing isolated LOCAL summary agents remain unaffected with `tools: []`.
|
|
484
62
|
|
|
485
|
-
|
|
63
|
+
`PI_CURSOR_NATIVE_TOOLS` accepts `0`, `false`, `off`, `none`, `no`, and `disabled` as off (trimmed, case-insensitive); unset, blank, or unrecognized values keep native tools **on**.
|
|
486
64
|
|
|
487
|
-
|
|
65
|
+
A policy mismatch preserves the pending local run: restore its prior policy to finish, or use `/cursor-abort` to explicitly release this session's pending local run before retrying. The command also stops an active owning Cursor Pi turn. Pi's normal abort only signals an active Pi turn; after the mismatch error has settled, it does not reach the old Cursor waiter. Neither recovery path undoes already-executed work.
|
|
488
66
|
|
|
489
|
-
|
|
67
|
+
Local runs leave Cursor auto-review and sandboxing off by default. Read the [safety controls and hook limits](docs/reference.md#cursor-local-agent-config-and-safety-controls) before you depend on those controls or Cursor hooks.
|
|
490
68
|
|
|
491
69
|
```bash
|
|
492
|
-
/cursor-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
They only accept cloud agent IDs recorded in the current session branch or its branch-bound durable sidecar; agent intents are fsynced before send and returned run IDs are recorded before abort handling or waiting so rejected, failed, cancelled, or first-turn-crashed sends remain cleanup-eligible. Persistence failures fail closed with Cursor Cloud dashboard cleanup guidance.
|
|
70
|
+
# Verify the installed version supports the native-tool opt-out and /cursor-abort.
|
|
71
|
+
# MCP-only local agent; explicitly expose Pi builtins through the Pi execution path.
|
|
72
|
+
PI_CURSOR_NATIVE_TOOLS=0 PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1 PI_CURSOR_SETTING_SOURCES=none pi --model cursor/grok-4.6
|
|
498
73
|
|
|
499
|
-
|
|
74
|
+
# Disable the Pi tool bridge.
|
|
75
|
+
PI_CURSOR_PI_TOOL_BRIDGE=0 pi --model cursor/grok-4.6
|
|
500
76
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
/cursor-local-resume-cleanup --yes
|
|
77
|
+
# Disable Cursor settings, rules, plugins, and MCP configuration loaded from disk.
|
|
78
|
+
PI_CURSOR_SETTING_SOURCES=none pi --model cursor/grok-4.6
|
|
504
79
|
```
|
|
505
80
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
It only deletes superseded local `agent-*` IDs that this extension recorded as cleanup candidates, one exact ID at a time through the Cursor SDK using the candidate's recorded store identity (or, only with default storage selected, the SDK default workspace store for legacy candidates without one), and protects agents still resumable from any session-tree branch. Before SDK deletion it verifies and fsyncs an exact intent in the Pi session JSONL, then verifies and fsyncs the result; a missing or non-durable intent prevents deletion, while a missing or non-durable result leaves the durable intent—and a conservative current-process marker—blocking automatic retry. A candidate with a recorded store identity that is invalid for the current session is durably marked non-retryable and excluded from later cleanup attempts. It does not sweep any SDK store or call lower-level empty delete filters. Removing a pi session file does not automatically remove its persisted store directory. After permanently retiring that session and confirming no pi process is using it, a recorded root may be removed manually only when it is the exact cwd/session-derived current or surviving legacy `pi-sessions/<session-hash>/` directory. Do not remove a stale recorded MD5 path after migration: resolve and verify the actual owning directory first. Never manually remove the SDK default workspace root, which legacy entries may record and other sessions may share.
|
|
509
|
-
|
|
510
|
-
Only enabled local safety values are passed to `Agent.create({ local })`; false/default values are omitted to preserve the current local-agent behavior. Local force is one-shot/manual-only through CLI/env and is passed only to the next `Agent.send({ local: { force: true } })`. Local resume is enabled by default for local runtime; opt out with `local.resume: false`, `--cursor-no-local-resume`, or `PI_CURSOR_LOCAL_RESUME=0`. Changes take effect on the next turn without recreating a healthy pooled agent.
|
|
81
|
+
Cursor activity cards show recorded results. They do not run tools again. Pi `tool_call` hooks cannot govern already-executed Cursor-native work; hiding replay or disabling the bridge is not enforcement. MCP-only is not a sandbox: exposed Pi/MCP tools can themselves execute arbitrary work. Cursor plan and todo cards do not control Pi's separate plan-mode extension or Pi todos.
|
|
511
82
|
|
|
512
|
-
|
|
83
|
+
See [tool surfaces](docs/cursor-tool-surfaces.md) for bridge options and [native replay](docs/cursor-native-tool-replay.md) for activity cards and SDK limits.
|
|
513
84
|
|
|
514
|
-
|
|
85
|
+
## Sessions and images
|
|
515
86
|
|
|
87
|
+
The extension reuses a Cursor agent for compatible local turns. Pi can reconnect to a recorded local agent after a restart. If reconnect fails, the extension starts a new agent from the Pi transcript and shows a continuity note. See [resume and storage](docs/reference.md#cursor-local-agent-config-and-safety-controls) for matching rules and cleanup commands.
|
|
516
88
|
|
|
517
|
-
|
|
89
|
+
Images in the current request go to Cursor. Earlier images become placeholders in the transcript. Reattach an image for a later question about it.
|
|
518
90
|
|
|
519
|
-
|
|
91
|
+
## Usage
|
|
520
92
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
Use the separate accounting view for recorded Cursor facts:
|
|
93
|
+
Pi's default footer and `/stats` keep their native context accounting. Use these commands for separate Cursor billing data:
|
|
524
94
|
|
|
525
95
|
```text
|
|
526
96
|
/cursor-usage
|
|
527
97
|
/cursor-usage refresh
|
|
528
98
|
/cursor-usage export cursor-usage.json
|
|
529
|
-
/cursor-usage help
|
|
530
99
|
```
|
|
531
100
|
|
|
532
|
-
|
|
533
|
-
- **Refresh:** public `Agent.getUsage()` only, up to 32 recorded agents with a five-second limit each; no model sends or automatic polling. An unavailable endpoint remains unavailable—there is no private dashboard fallback.
|
|
534
|
-
- **Export:** creates a new private JSON file without replacing existing files. It contains IDs, lineage, usage, configured pricing, and observation status, not prompts or tool content. Inspect local paths/identifiers before sharing.
|
|
535
|
-
- **Honest limits:** observations may lag or revise; they are not final invoices. Known aggregate usage/cost stays visible even when inherited run history is incomplete; full run snapshots and aggregate-only remainders are withheld rather than invented. Unavailable refreshes retain explicitly labeled latest-known observations. LOCAL client run IDs do not join billing UUIDs. Resumed history without a known creation record is marked unknown; shared-lineage and multiple-origin observations are not billed to the current branch. Current official Pi has no public extension API for complete native invoice totals.
|
|
536
|
-
|
|
537
|
-
Before a send, the extension records a unique public native branch claim and a validated, fsynced intent. Usage journals live beside the Pi session JSONL as `cursor-usage-<session-id-hash>.journal`; they retain late facts for the original owner without writing a switched session or sibling branch. Fileless sessions are explicitly ephemeral. Missing or torn inherited journals remain explicitly incomplete. Known claims outside the current branch are shown as other-branch facts; same-directory, same-ID recovery with a lost initial claim is shown as unclaimed history. Neither is newly recognized current-branch spend. If every origin reference is lost after moving directories, the extension cannot discover that history without unsafe scanning.
|
|
538
|
-
|
|
539
|
-
Each origin journal has a **16 MiB ceiling**. Persistence failure before a send prevents that send. Later failure may warn once while the original owner is current; `/cursor-usage` exposes incomplete accounting without changing the response's outcome. For a torn trailing frame, view/export preserves the validated prefix and reports the incomplete journal; further appends fail closed without changing its bytes. For ceiling or torn-tail recovery, export and retain the old session/journal, then fork the conversation into a new native session or start a new session. Do not delete or truncate the journal to continue an old agent lineage. `/cursor-usage help` also documents this recovery.
|
|
540
|
-
|
|
541
|
-
## Cursor provider tool contract
|
|
542
|
-
|
|
543
|
-
See [Cursor tool surfaces in pi](docs/cursor-tool-surfaces.md) for a concise guide to callable vs display-only tools, MCP catalog limits, JSONL ID patterns, and how pi toggles differ from Cursor ambient MCP.
|
|
544
|
-
|
|
545
|
-
Local Cursor runs use two separate tool surfaces:
|
|
546
|
-
|
|
547
|
-
- **Cursor-native surface:** Cursor local-agent tools, Cursor settings, plugins, and configured Cursor MCP servers. These remain owned by the Cursor SDK local agent path. Pi CLI tool toggles such as `--no-tools`, `--tools`, and `--exclude-tools` do not disable this Cursor-native surface.
|
|
548
|
-
- **pi bridge surface:** pi-cursor-sdk exposes bridgeable active pi tools through a per-run local loopback MCP bridge when the bridge is enabled and the current pi tool registry has exposed tools. Pi CLI tool toggles affect this bridge surface because they change pi's active tool registry.
|
|
549
|
-
|
|
550
|
-
The bridge uses stable MCP v2 with `@modelcontextprotocol/server@2.3.1`, `@modelcontextprotocol/hono@2.0.2`, `hono@4.13.13`, and `@hono/node-server@2.1.3`, bundled as its runtime closure. It binds only to loopback and validates Hono `Host` and `Origin` headers.
|
|
551
|
-
|
|
552
|
-
Bridge capabilities are snapshotted from `pi.getActiveTools()` and `pi.getAllTools()` for each Cursor run, including per-tool prompt guidelines when pi exposes them. Cursor sees active bridgeable pi tools as collision-safe MCP names such as `pi__sem_reindex` only when they are exposed in that current run. When exposed, Cursor is instructed to prefer `pi__mcp` for MCP work and `pi__subagent` for delegation; Cursor-configured MCP and Cursor-native subagents are fallbacks when the matching pi tool is not exposed or is unavailable. Pi session output, tool cards, confirmations, hooks, renderers, history, and abort behavior use the real pi tool name, such as `sem_reindex`. The bridge queues Cursor's MCP call, emits a normal pi `toolCall`, waits for the matching pi `toolResult`, and resolves that result back into the same live Cursor SDK run without creating a new `Agent`, unless the run was disposed, aborted, or cancelled. The bridge does not call pi tool `execute()` handlers directly.
|
|
553
|
-
|
|
554
|
-
Overlapping built-in pi tools (`read`, `bash`, `write`, `edit`, `grep`, `find`, `ls`) are hidden by default because Cursor local agents already have native equivalents. Extension/custom tools and non-overlapping active tools present in pi's active tool registry normally remain exposed. The bridge also exposes `cursor_ask_question` as `pi__cursor_ask_question` when `PI_CURSOR_ASK_QUESTION=1`. It is off by default so Cursor does not block on questionnaires. For local runtime, when pi has visible Agent Skills loaded, the extension rewrites pi's skill catalog for Cursor and exposes `cursor_activate_skill` as `pi__cursor_activate_skill`; Cursor should call that bridge tool with a listed skill name to load the full `SKILL.md` and bundled resource list before applying the skill. If the local bridge is disabled, the catalog remains available and instructs Cursor to fall back to reading the listed `SKILL.md` path directly. Cloud runtime preserves Pi project instructions but omits Pi's local skill catalog and keeps `cursor_activate_skill` inactive because the bridge and local absolute skill paths are unavailable there.
|
|
555
|
-
|
|
556
|
-
Cursor-native tool replay is separate from the bridge. Replay cards are display-only recorded Cursor SDK activity. They never re-run Cursor-side commands, reapply Cursor edits, call MCP servers, or mutate pi state. See [Cursor native tool replay](docs/cursor-native-tool-replay.md).
|
|
557
|
-
|
|
558
|
-
Footer display control: `PI_CURSOR_FOOTER=0` hides the Cursor status without hiding Pi's model or usage footer. Like other boolean controls, it accepts `0`, `false`, `off`, `none`, `no`, and `disabled` to hide; `1`, `true`, `on`, `yes`, and `enabled` to show (case-insensitive). Unset, blank, or unrecognized values keep the default visible status.
|
|
559
|
-
|
|
560
|
-
Bridge controls:
|
|
561
|
-
|
|
562
|
-
```bash
|
|
563
|
-
# Opt in to Cursor's interactive question tool through pi UI.
|
|
564
|
-
PI_CURSOR_ASK_QUESTION=1 pi --model cursor/grok-4.6
|
|
565
|
-
|
|
566
|
-
# Roll back to Cursor SDK tools/settings/MCP only; do not expose active pi tools through the bridge.
|
|
567
|
-
PI_CURSOR_PI_TOOL_BRIDGE=0 pi --model cursor/grok-4.6
|
|
568
|
-
|
|
569
|
-
# Opt in to also expose overlapping pi tool names through the bridge.
|
|
570
|
-
PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1 pi --model cursor/grok-4.6
|
|
571
|
-
|
|
572
|
-
# Override Cursor SDK MCP tool-call timeout, including bridged pi tools and configured Cursor MCP servers.
|
|
573
|
-
PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS=7200 pi --model cursor/grok-4.6
|
|
574
|
-
PI_CURSOR_MCP_TOOL_TIMEOUT_MS=7200000 pi --model cursor/grok-4.6
|
|
575
|
-
|
|
576
|
-
# Fail a stranded pi bridge CallTool sooner than the effective MCP tool timeout.
|
|
577
|
-
PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS=120000 pi --model cursor/grok-4.6
|
|
578
|
-
|
|
579
|
-
# Override known MCP initialize/listTools timeouts on first send (default 10s).
|
|
580
|
-
PI_CURSOR_MCP_CONNECT_TIMEOUT_SECONDS=5 pi --model cursor/grok-4.6
|
|
581
|
-
PI_CURSOR_MCP_CONNECT_TIMEOUT_MS=5000 pi --model cursor/grok-4.6
|
|
582
|
-
|
|
583
|
-
# Force Cursor SDK local-agent backend streams to HTTP/1.1/SSE instead of HTTP/2.
|
|
584
|
-
env 'PI_CURSOR_HTTP_1_1=true' pi --model cursor/grok-4.6
|
|
585
|
-
# Or toggle it inside an interactive Cursor session.
|
|
586
|
-
/cursor-http on
|
|
587
|
-
|
|
588
|
-
# Disable bootstrap callable-surface manifest (on by default).
|
|
589
|
-
PI_CURSOR_TOOL_MANIFEST=0 pi --model cursor/grok-4.6
|
|
590
|
-
|
|
591
|
-
# Emit scrubbed bridge diagnostics as JSONL to stderr with prefix [pi-cursor-sdk:bridge].
|
|
592
|
-
PI_CURSOR_PI_TOOL_BRIDGE_DEBUG=1 pi --model cursor/grok-4.6
|
|
593
|
-
```
|
|
594
|
-
|
|
595
|
-
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`.
|
|
596
|
-
|
|
597
|
-
`PI_CURSOR_ASK_QUESTION=1` enables only `cursor_ask_question`, leaving the rest of the pi bridge available; it is off by default. `PI_CURSOR_PI_TOOL_BRIDGE=0` is the supported rollback flag and disables the bridge entirely. Both flags treat `false`, `off`, `none`, `no`, and `disabled` as off; `1`, `true`, `on`, `yes`, and `enabled` as on. `PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1` opts in to exposing overlapping pi tool names that Cursor already has native equivalents for. The installed Cursor SDK uses a 60-second MCP protocol default with no public per-server timeout option. pi-cursor-sdk overrides that seam in two directions by default: MCP `callTool` requests are extended to 3600 seconds for long-running local MCP tools (including the pi bridge and configured Cursor MCP servers), and known MCP initialize/listTools requests on first send are shortened to 10 seconds so unavailable configured MCP servers fail fast instead of blocking for a full minute. Unknown Cursor SDK MCP protocol timeout stacks keep the SDK default instead of being shortened. Override tool-call timeouts with `PI_CURSOR_MCP_TOOL_TIMEOUT_MS` or `PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS`, and first-send initialize/listTools timeouts with `PI_CURSOR_MCP_CONNECT_TIMEOUT_MS` or `PI_CURSOR_MCP_CONNECT_TIMEOUT_SECONDS`. Bridged calls also have a local fail-closed deadline that defaults to the effective MCP tool timeout; lower it with `PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS` when a lost pi result should fail sooner. On expiry, the bridge rejects and removes the pending call and aborts active pi execution when available. The bridge's `listTools` handler returns its snapshot synchronously, so a Cursor UI label such as `GetMcpTools` does not by itself identify a `listTools` deadlock; the durable bridge waiter is `CallTool` awaiting its matching pi result.
|
|
598
|
-
|
|
599
|
-
Pending pi bridge calls keep their owning local Cursor live run active, including queued calls, long-running tools, and questions awaiting human input. After the last owned call settles and the provider drain lease ends, the full idle cleanup window (five minutes by default) restarts—even if cleanup was requested before the lease. A pending call in another session does not delay cleanup. This is not an answer timeout: explicit abort/shutdown/reset/compaction and the fail-closed MCP/bridge deadline (one hour by default) still clean up pending work. Abandoned display-only native replay retains its idle expiry.
|
|
600
|
-
|
|
601
|
-
`PI_CURSOR_LIVE_RUN_IDLE_DISPOSE_MS` sets that window for eligible retained local replay runs. It defaults to `300000` (five minutes); only decimal digits representing an integer from `1` through `2147483647` are accepted. Unset, blank, malformed (including surrounding whitespace), and out-of-range values fall back to five minutes. For example, `PI_CURSOR_LIVE_RUN_IDLE_DISPOSE_MS=900000 pi --model cursor/grok-4.6` selects fifteen minutes. The full configured window restarts after the last owned pending call settles and the provider drain lease ends. This environment-only setting does not change bridge/MCP deadlines or explicit abort/shutdown cleanup, and is not a fix for backend authentication, transport, or lost-executor failures.
|
|
101
|
+
Refresh requests public billing data without a model prompt. Export creates a private JSON file and does not overwrite existing files. Billing data can lag or change. It is not a final invoice.
|
|
602
102
|
|
|
603
|
-
|
|
103
|
+
Check paths and identifiers before you share an export. See [usage and journal recovery](docs/reference.md#context-compaction-and-cursor-usage) for details.
|
|
604
104
|
|
|
605
|
-
|
|
105
|
+
## Optional Cursor Cloud
|
|
606
106
|
|
|
607
|
-
|
|
107
|
+
Local is the default. Run `/cursor-runtime cloud` to see the first-use confirmation. Cloud can commit, push, and open PRs. It uses Max Mode billing at Cursor API pricing.
|
|
608
108
|
|
|
609
|
-
|
|
610
|
-
- `mcp_initialized`: the server received a validated `notifications/initialized`.
|
|
611
|
-
- `mcp_tools_list`: the catalog handler produced `toolCount` tools after request validation, not proof the client received or model consumed them.
|
|
612
|
-
- `request_queued` / `request_resolved` / `request_rejected`: actual bridge call handling.
|
|
109
|
+
Cloud requires a persisted Pi session and starts with fresh context by default. Cloud has no local Pi tool bridge or Pi environment forwarding. Cloud agents remain in Cursor until you explicitly archive or delete them.
|
|
613
110
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
### Maintainer cost-conscious verification
|
|
617
|
-
|
|
618
|
-
Run offline/faux tests, native contracts, type checks, builds, and package checks first; preserve offline cross-platform CI. Reuse retained evidence for unchanged tested inputs. Real Cursor calls are only for the smallest meaningful changed-behavior check that needs real-service proof, on one representative environment. Docs/metadata-only changes need no paid testing. Do not replay full paid campaigns, run host matrices merely for matrix coverage, or automatically retry paid failures. Automated Cursor PR reviews continue unchanged.
|
|
619
|
-
|
|
620
|
-
No paid Cursor Cloud testing for generic PRs or releases. Only a PR or issue explicitly focused on Cursor Cloud may use a necessary focused Cloud check; incidental Cloud code changes do not qualify. Cloud product capabilities, offline contracts, and explicit smoke commands remain available. Even for Cloud-focused work, the multi-lane `npm run smoke:cloud` is optional, not an unconditional gate; selected checks retain run/evidence and agent/repository cleanup requirements.
|
|
621
|
-
|
|
622
|
-
[Platform smoke](docs/platform-smoke.md) documents existing single-suite/single-target commands and the optional comprehensive `npm run smoke:platform:all` matrix. The matrix uses packed installs, PTY/ConPTY ANSI capture, host-rendered xterm/PNG evidence, JSONL assertions, bridge diagnostics, usage/cache checks, abort cleanup, artifact manifests, and redaction scans. `.artifacts/platform-smoke/latest.json` points to each platform run's evidence. Report exactly the scope observed, not unrun matrix coverage.
|
|
623
|
-
|
|
624
|
-
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 only when a changed TUI/card/runtime behavior needs new live evidence. Select one relevant check rather than executing every helper. `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.
|
|
625
|
-
|
|
626
|
-
### Maintainer Cursor SDK event capture
|
|
627
|
-
|
|
628
|
-
Use `npm run debug:sdk-events` to capture timestamped `run.stream()`, `onDelta`, and `onStep` timelines for one direct `@cursor/sdk` run.
|
|
629
|
-
|
|
630
|
-
Use `npm run debug:provider-events` to capture the same `onDelta`/`onStep` payloads **through pi's Cursor provider** (session agent reuse, bridge, native replay, send planning). Artifacts default under gitignored `.debug/cursor-sdk-events/`. Interactive multi-turn pi sessions group turns under `.debug/cursor-sdk-events/sessions/<session-slug>/turn-NNN-.../` with a `session.json` index. You can also opt in during any pi run with `PI_CURSOR_SDK_EVENT_DEBUG=1`; capture is file-only by default so the pi TUI stays normal. Each cumulative JSONL artifact is capped at 2 MiB, ends with an `artifact_truncated` record when capped, and is listed in `summary.json` under `truncatedJsonlFiles`.
|
|
631
|
-
|
|
632
|
-
See [Cursor testing lessons](docs/cursor-testing-lessons.md#cursor-sdk-event-capture-probe) for usage, artifact layout, and safety notes.
|
|
633
|
-
|
|
634
|
-
## Fallback models
|
|
635
|
-
|
|
636
|
-
If no matching cached catalog is available in a cache-only phase, auth is missing, or live discovery fails or returns no models, the extension retains known bundled fallback identities and notifies interactive users when possible. By default these models remain available without auth. With `PI_CURSOR_HIDE_MODELS_WHEN_LOGGED_OUT=1`, unauthenticated picker/list availability is empty, but known CLI selection and native login remain functional. Pi owns `--api-key` parsing.
|
|
637
|
-
|
|
638
|
-
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 and 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`; its generator provenance records SDK 1.0.37 and 46 models from the authenticated catalog-only refresh on 2026-10-07. That refresh added Claude Haiku 5.5 (`claude-haiku-5-5`), preserving all 45 prior model records from the SDK 1.0.36 capture on 2026-10-06. The 33 bundled checkpoint-derived entries were unchanged; no Agent/model turn or Cloud run was performed. 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.
|
|
639
|
-
|
|
640
|
-
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.
|
|
641
|
-
|
|
642
|
-
## Limits
|
|
643
|
-
|
|
644
|
-
- **Commit/PR attribution has no supported opt-out.** SDK 1.0.37 exposes neither attribution control through public create/local/send/configure options. CLI-file edits and SDK-internal patches are not supported extension settings; [#302](https://github.com/fitchmultz/pi-cursor-sdk/issues/302) tracks both controls.
|
|
645
|
-
|
|
646
|
-
- **Cloud runtime is explicit and minimal.** Local remains the default. Cloud runs create Cursor cloud agents only after first-use acknowledgement and safety preflight, use fresh context by default, do not expose the pi bridge or local MCP, do not forward pi env vars, support explicit Cursor-managed environment selection, name agents from the pi session title when available, stream display-only agent/run/branch/PR/artifact/raw-usage telemetry when available, and record only explicit session-branch lifecycle commands for cleanup (`/cursor-cloud list|archive|delete`).
|
|
647
|
-
- **The pi tool bridge is local and MCP-backed.** Bridgeable active pi tools are exposed to local Cursor agents through a tokenized `127.0.0.1` MCP endpoint; internal Cursor replay activity names are excluded, and overlapping built-in pi tools are hidden by default. Set `PI_CURSOR_PI_TOOL_BRIDGE=0` to disable it or `PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1` to expose overlapping built-ins too.
|
|
648
|
-
- **Cursor native tool replay is display-only.** Replay renders recorded Cursor SDK activity and never re-runs Cursor-side commands, reapplies Cursor edits, calls MCP servers, or mutates pi state. Workflow tools such as Cursor mode/task/todo/plan activity are not pi workflow controls. See [Cursor native tool replay](docs/cursor-native-tool-replay.md) for supported replay cards, ordering, conflict handling, and opt-out flags.
|
|
649
|
-
- **Cursor run state can span tool-use turns.** Within a pi session, the extension reuses one Cursor SDK agent across compatible follow-up turns and sends incremental prompts when context still matches. It recreates the agent when context diverges, after compaction or `/tree` navigation, on API key changes, after send errors, or on session shutdown. For bridged pi tools, the matching pi `toolResult` resolves into the same live Cursor SDK run without creating a new `Agent`, unless the run was disposed, aborted, or cancelled. Replay can also split one live Cursor SDK run across pi `toolUse` turns for display.
|
|
650
|
-
- **Final assistant text is the last non-empty text part.** Composer responses can produce one assistant message with early progress `text`, thinking/tool metadata, and a later final `text` report. Consumers that need a final answer should scan assistant message content from the end and use the last non-empty `text` part, not the first. Cursor `thinking` deltas are shown as thinking traces when the SDK emits them; those traces can include draft answers or copied exact-output targets and are intentionally not collapsed by this extension.
|
|
651
|
-
- **Cursor setting sources default to all.** The extension passes `local.settingSources: ["all"]` by default so configured Cursor MCP servers, plugin tools, project/user settings, and related Cursor-native capabilities are available like they are in Cursor. To narrow loading, set a comma-separated list such as `PI_CURSOR_SETTING_SOURCES=project,user,plugins`. To disable ambient setting sources, set `PI_CURSOR_SETTING_SOURCES=none`. Verified framed SDK inventory/rules/skills completion logs and exact hook-compatibility notices are filtered without changing settings, hooks, plugin trust, or parser enforcement. An outside-root local-plugin symlink rejection or the exact native-parser-unavailable warning instead produces a bounded native notice with recovery guidance, recorded as non-model session data without raw paths. Outside the retained creation-only mute around `Agent.create()`, other failures (including hook symlink refusals, ignore-mapping errors, and missing ripgrep configuration) retain their original output. The two recognized capability notices escape that creation mute.
|
|
652
|
-
- **AGENTS.md / CLAUDE.md are not duplicated on Cursor models when Cursor loads the same rules.** Pi discovers global and project context files (`AGENTS.md`, `CLAUDE.md`, and case variants) unless you start with `-nc`. On `cursor/*` models the extension removes only `<project_instructions>` blocks that overlap Cursor `settingSources` via the `before_agent_start` hook: `user` for `~/.pi/agent/AGENTS.md`, `project` for repo/parent `AGENTS.md` and `CLAUDE.md` (verified Cursor behavior: local agents load project `AGENTS.md` and `CLAUDE.md` alongside Cursor rules). `~/.pi/agent/CLAUDE.md` is not stripped (Cursor user rules use `~/.claude/CLAUDE.md`, not pi's agent dir). With `PI_CURSOR_SETTING_SOURCES=none` or `plugins`-only, pi context is left intact. Set `PI_CURSOR_PRESERVE_PI_AGENTS_MD=1` to keep duplicate injection.
|
|
653
|
-
- **Max Mode is not a manual pi variant.** Cursor's SDK may enable Max Mode automatically for models that require it. This extension only advertises exact context-window variants that the SDK catalog exposes and otherwise uses conservative SDK-derived default/non-Max context windows.
|
|
654
|
-
- **Output token limits are conservative.** Cursor SDK model metadata does not currently expose output token limits directly.
|
|
655
|
-
- **Local token usage uses Cursor SDK data when safely attributable.** In-time LOCAL raw `turn-ended` usage keeps full-prompt input with cache as a partition: pi maps `input = inputTokens - cacheRead - cacheWrite`, retains the cache fields, and sets `totalTokens = inputTokens + outputTokens`. Fallback components and total describe the same estimated current context. Late SDK usage is not retroactively applied to an emitted pi message, but every raw turn remains separately recorded by the [Cursor usage ledger](#context-compaction-and-cursor-usage). Raw Cloud telemetry is retained without assuming LOCAL normalization.
|
|
656
|
-
- **Configured cost is separate from Cursor billing.** Discovered models register zero rates. `models.json` per-million `cost` overrides, including tiers, use pi's native pricing helper on each emitted message's coherent context components. Fallback has no inferred cache split; split-message estimates can differ from actual internal request pricing. Public `getUsage()` billed input/cache/output categories are already disjoint—cache is not subtracted again—and optional `cost.rawCostCents` / `cost.chargedCents` are retained separately in floating-point cents. Neither these revisable observations nor native configured estimates promise invoice reconciliation.
|
|
111
|
+
Run `/cursor-cloud list` to see agents recorded for your session branch. Read the [Cloud setup and cleanup guide](docs/reference.md#cloud-runtime-and-acknowledgement) before you start a remote run.
|
|
657
112
|
|
|
658
113
|
## Troubleshooting
|
|
659
114
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
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.
|
|
667
|
-
|
|
668
|
-
SDK 1.0.37 source preserves SDK 1.0.36's client bearer refresh and unauthenticated handling, but those mechanisms do not establish the cause of [#247](https://github.com/fitchmultz/pi-cursor-sdk/issues/247)'s historical idle failure. Reloading filesystem config is not a public auth-reset API. No guessed idle TTL or extension-level automatic resend is added: resending can duplicate executed tool effects.
|
|
669
|
-
|
|
670
|
-
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 SDK-provenance `WriteIterableClosedError: WritableIterable is closed` race remains guarded for the Pi session lifecycle; 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. Unrelated failures remain fatal. The old raw child-stdin EPIPE workaround was removed because Cursor SDK fixed that path by 1.0.27. Persistent failures may indicate a transient Cursor service or network issue.
|
|
671
|
-
|
|
672
|
-
You can also restart pi with a key in the same shell or launcher that starts pi:
|
|
673
|
-
|
|
674
|
-
```bash
|
|
675
|
-
export CURSOR_API_KEY="your-key"
|
|
676
|
-
pi --model cursor/grok-4.6
|
|
677
|
-
```
|
|
678
|
-
|
|
679
|
-
Or run a one-shot command:
|
|
680
|
-
|
|
681
|
-
```bash
|
|
682
|
-
pi --api-key "your-key" --model cursor/grok-4.6 -p "Say ok only"
|
|
683
|
-
```
|
|
684
|
-
|
|
685
|
-
### Embedded sessions report concurrent Cursor turns
|
|
686
|
-
|
|
687
|
-
In-process sessions using independent `ModelRuntime` instances (the SDK default on supported Pi hosts) support concurrent turns, children launched inside parent tools, and direct compaction/tree/bug-report summaries. Each provider registration captures its own session, bridge, storage, and debug scope. Fork-inherited tool-result IDs cannot drain a parent's live run; replay wrappers reject foreign-owner or wrong-tool results without consuming the original card or executing work. Native request-header receipts verify the calling session before SDK/storage work, including auxiliary streams. Explicitly sharing a `ModelRuntime` overwrites its Cursor registration: requests from another session fail closed rather than entering the sibling's scope. Use independent runtimes, or reload the intended session to restore its registration; catalog refresh does not replace a sibling's provider. A not-yet-bound or shut-down provider closure cannot send. **Migration from 0.4.0:** bare `ctx.modelRegistry.complete(...)` and `ctx.modelRegistry.streamSimple(...)` calls lack the native receipt and are unsupported for Cursor, including custom compaction integrations; bind/refresh/reload does not fix that path. Use the owning AgentSession's stream path or an independent child AgentSession. CLI flags and their one-shot local-force consumption remain owned by each embedded session runtime across reload. Cursor SDK HTTP/1.1 transport configuration and environment/user defaults remain process-global; branch preferences are session-scoped, not independent SDK transport configurations. See [multi-session embedding semantics](docs/cursor-model-ux-spec.md#multi-session-embedding).
|
|
688
|
-
|
|
689
|
-
Independent SessionManagers opening the same persisted file have separate transient Cursor pools, generations and live-run ownership. Reload/tree/shutdown of one manager does not invalidate the other's resources. Durable store/resume/lineage identities remain unchanged; an atomic process-local agent claim prevents a sibling from resuming or deleting a still-owned handle. Failed or timed-out SDK disposal retains that claim until successful disposal or process exit. This fixes a reproduced same-file `Cursor session agent scope is closed` trigger, not every cause reported in [#282](https://github.com/fitchmultz/pi-cursor-sdk/issues/282). It is not a cross-process lock or qualification of concurrent real SQLite/journal writes to one file; use native forks or separate files for independent conversations.
|
|
690
|
-
|
|
691
|
-
### Native shell parsing or module loading fails
|
|
692
|
-
|
|
693
|
-
Before loading the SDK, the extension resolves the installed `@cursor/sdk-<platform>-<arch>` package relative to `@cursor/sdk` and supplies its `vendor` directory through the SDK's `CURSOR_TREE_SITTER_VENDOR_DIR`. This lets native Bash parsing work when Pi's launcher and extension live in separate installation trees. The platform package must be installed; the extension does not download or bundle replacement native binaries.
|
|
694
|
-
|
|
695
|
-
An explicitly set `CURSOR_TREE_SITTER_VENDOR_DIR` is left untouched. Use an absolute path to a vendor directory containing both `tree-sitter` and `tree-sitter-bash`, or unset it to use package-relative discovery. Empty and relative overrides are also preserved; the SDK decides whether to use them or its own fallback lookup.
|
|
696
|
-
|
|
697
|
-
The automatically selected path is process-wide and inherited by bash commands and child Pi processes. A child running another extension install or worktree treats that inherited value as an explicit override, even if the parent's install has moved or been deleted. To rediscover the child's own parser package, launch it with `env -u CURSOR_TREE_SITTER_VENDOR_DIR pi -e .` (or remove the variable from the child environment on Windows). Alternatively, set an absolute vendor path for the child's install. Inherited overrides are not validated or replaced automatically.
|
|
698
|
-
|
|
699
|
-
A `ResolveMessage`, missing module, or missing `protoBase64` export is a loader problem, not evidence of a bad API key. The static SDK and bridge imports in 0.5.1 also repair the compiled-Bun extension graph. A packed installation reached expected invalid-key handling in official compiled Pi 1.0.3 on macOS arm64. The retained SDK 1.0.36 installed-package probe showed its nested Connect 1.7.0 / Protobuf 1.10.0 graph linking normally; forcing its Protobuf import to the root 2.16.0 package reproduces the exact missing export. That does not establish the unnamed Windows hosts' resolution in [#233](https://github.com/fitchmultz/pi-cursor-sdk/issues/233); their importer-relative paths and bootstrap remain necessary. The credential-free real-SDK first-send test reaches a blocked key-exchange boundary, not authenticated inference or every embedded loader.
|
|
700
|
-
|
|
701
|
-
SDK 1.0.37 source retains the parser-unavailable branch returning `parsingFailed`; the retained SDK 1.0.36 private package probe still executed the command. It does not itself establish why Pi received SIGTERM in the non-Cursor/opencode report [#339](https://github.com/fitchmultz/pi-cursor-sdk/issues/339). Warning text alone cannot identify the emitting artifact or signal sender.
|
|
702
|
-
|
|
703
|
-
### `pi --list-models cursor` shows no Cursor models
|
|
704
|
-
|
|
705
|
-
With `PI_CURSOR_HIDE_MODELS_WHEN_LOGGED_OUT=1`, this is expected until Cursor has effective native auth. Run `/login`, supply `CURSOR_API_KEY` or pi's `--api-key`, or unset the flag to restore default fallback availability. Known CLI model selection remains available either way.
|
|
706
|
-
|
|
707
|
-
If the flag is not the cause, confirm the package is installed:
|
|
708
|
-
|
|
709
|
-
```bash
|
|
710
|
-
pi list
|
|
711
|
-
```
|
|
712
|
-
|
|
713
|
-
Then reinstall if needed:
|
|
714
|
-
|
|
715
|
-
```bash
|
|
716
|
-
pi install npm:pi-cursor-sdk
|
|
717
|
-
```
|
|
718
|
-
|
|
719
|
-
### `pi --list-models` shows `thinking=no`
|
|
720
|
-
|
|
721
|
-
That does not mean the model cannot think. It means the Cursor SDK does not expose a pi-controllable thinking parameter for that model. The model may still think internally and may still emit thinking deltas that pi renders natively.
|
|
722
|
-
|
|
723
|
-
### I do not see `cursor:local` / `cursor:cloud` or `plan` in the footer
|
|
724
|
-
|
|
725
|
-
The Cursor footer appears only while a Cursor model is active and `PI_CURSOR_FOOTER` is enabled (the default). Remove `PI_CURSOR_FOOTER=0` or set it to `1` to restore the status. Fast-capable local models show `cursor:local · fast:on` or `cursor:local · fast:off`; Cursor models without a fast parameter show `cursor:local · fast:n/a`. Cloud runtime shows `cursor:cloud · fast:n/a`. Cursor SDK mode is the default `agent` mode when `plan` is absent. When both are active, pi shows one combined Cursor status such as `cursor:local · fast:on · plan` or `cursor:cloud · fast:n/a · plan`.
|
|
726
|
-
|
|
727
|
-
### My Cursor app settings or rules do not seem to apply
|
|
728
|
-
|
|
729
|
-
Cursor setting sources are loaded with `PI_CURSOR_SETTING_SOURCES=all` by default. To narrow loading, set `PI_CURSOR_SETTING_SOURCES=project,user,plugins` or another comma-separated list. If you explicitly disabled sources with `PI_CURSOR_SETTING_SOURCES=none`, remove that override.
|
|
730
|
-
|
|
731
|
-
### Cursor does not call my web search MCP/tool
|
|
732
|
-
|
|
733
|
-
Cursor SDK local agents load MCP servers from Cursor setting sources and inline SDK config. This extension enables all Cursor setting sources by default, so a missing web search tool usually means it is not configured in Cursor or the run was started with a narrowing/disable override such as `PI_CURSOR_SETTING_SOURCES=none`.
|
|
734
|
-
|
|
735
|
-
### I do not see Cursor web search or web fetch in pi's tool UI
|
|
736
|
-
|
|
737
|
-
pi shows **Cursor web search** / **Cursor web fetch** activity cards only when the installed `@cursor/sdk` reports completed replayable tool data. Supported sources are SDK `mcp` completions whose `toolName` is `WebSearch` / `web_search` / `WebFetch` / similar, host tool names that normalize to those labels, and local Cursor transcript `webSearchToolCall` / `webFetchToolCall` records available through `Agent.messages.list()` after the run. This is separate from SDK `semSearch`, which is semantic **codebase** search.
|
|
738
|
-
|
|
739
|
-
Known SDK boundary: some local Cursor web search activity is not emitted through live `onDelta`, `onStep`, or `run.stream()` tool events. When that happens, pi can only reconstruct a card from the local agent transcript after `run.wait()` finishes, so the **Cursor web search** card may appear after assistant text rather than as a live in-progress card. Buffering all assistant text until `run.wait()` would make the ordering prettier but would break normal streaming, so pi does not do that.
|
|
740
|
-
|
|
741
|
-
Known SDK boundary: Cursor SDK `task` activity is shown as **Cursor subagent** because it represents Cursor-spawned child-agent work, but the SDK does not always emit a live nested subagent action stream. Pi shows the subagent start, final output, kind/model/short-ID metadata, and any `conversationSteps` tool-call summaries Cursor returns. If Cursor only returns final subagent text, pi cannot show the subagent's internal read/shell/MCP steps.
|
|
742
|
-
|
|
743
|
-
Many runs never expose web activity as replayable SDK tool completions or local transcript web tool records. The model may still answer from internal Cursor web tooling or only mention search in assistant text/thinking. In that case pi cannot render a tool card because there is no completed SDK tool-call payload to replay. Capture a run with `npm run debug:provider-events` when investigating; if `on-delta.jsonl`, `on-step.jsonl`, `stream-events.jsonl`, `coordinator-events.jsonl`, and `display-decisions.jsonl` have no completed or transcript web tool data, the limitation is on the Cursor SDK surface, not pi replay registration.
|
|
744
|
-
|
|
745
|
-
**Web fetch:** `pi-cursor-sdk` can display `webFetchToolCall` transcript records and web-fetch-shaped MCP/host completions when Cursor reports them. It cannot make Cursor expose or execute a `WebFetch` tool. If Cursor's current local SDK tool set does not include WebFetch, pi cannot fetch a URL through Cursor web fetch; use an allowed browser/shell/MCP tool instead.
|
|
746
|
-
|
|
747
|
-
### I disabled MCP in pi but Cursor still has extra tools
|
|
748
|
-
|
|
749
|
-
pi extension toggles and pi's MCP catalog do not control Cursor ambient MCP. Local Cursor agents load MCP servers from Cursor setting sources (`PI_CURSOR_SETTING_SOURCES=all` by default), including `~/.cursor/mcp.json`. To remove a server, edit or clear that file (or Cursor MCP settings) and restart the pi session, or narrow/disable sources with `PI_CURSOR_SETTING_SOURCES=none` or a comma-separated subset. See [Cursor tool surfaces in pi](docs/cursor-tool-surfaces.md).
|
|
750
|
-
|
|
751
|
-
### Cursor does not call my pi extension tool
|
|
752
|
-
|
|
753
|
-
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:
|
|
754
|
-
|
|
755
|
-
```bash
|
|
756
|
-
PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1 pi --model cursor/grok-4.6
|
|
757
|
-
```
|
|
758
|
-
|
|
759
|
-
To disable the bridge for rollback or isolation, start pi with:
|
|
760
|
-
|
|
761
|
-
```bash
|
|
762
|
-
PI_CURSOR_PI_TOOL_BRIDGE=0 pi --model cursor/grok-4.6
|
|
763
|
-
```
|
|
764
|
-
|
|
765
|
-
### First Cursor message is slow (10+ seconds)
|
|
766
|
-
|
|
767
|
-
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:
|
|
768
|
-
|
|
769
|
-
```bash
|
|
770
|
-
PI_CURSOR_MCP_CONNECT_TIMEOUT_SECONDS=5 pi --model cursor/grok-4.6
|
|
771
|
-
PI_CURSOR_MCP_CONNECT_TIMEOUT_MS=5000 pi --model cursor/grok-4.6
|
|
772
|
-
```
|
|
773
|
-
|
|
774
|
-
Workarounds if you do not need user-level MCP in pi:
|
|
775
|
-
|
|
776
|
-
```bash
|
|
777
|
-
PI_CURSOR_SETTING_SOURCES=project,plugins,team pi --model cursor/grok-4.6
|
|
778
|
-
```
|
|
779
|
-
|
|
780
|
-
Or fix/disable the slow MCP server in Cursor settings. Maintainer timing probe: `npm run debug:mcp-coldstart`.
|
|
781
|
-
|
|
782
|
-
### A Cursor MCP tool times out
|
|
783
|
-
|
|
784
|
-
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:
|
|
785
|
-
|
|
786
|
-
```bash
|
|
787
|
-
PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS=7200 pi --model cursor/grok-4.6
|
|
788
|
-
PI_CURSOR_MCP_TOOL_TIMEOUT_MS=7200000 pi --model cursor/grok-4.6
|
|
789
|
-
```
|
|
790
|
-
|
|
791
|
-
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:
|
|
792
|
-
|
|
793
|
-
```bash
|
|
794
|
-
PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS=120000 pi --model cursor/grok-4.6
|
|
795
|
-
```
|
|
796
|
-
|
|
797
|
-
### Tool calls appear as a plain text list instead of pi tool cards
|
|
798
|
-
|
|
799
|
-
This usually needs session JSONL to classify. Common cases:
|
|
800
|
-
|
|
801
|
-
- **Model text echo:** Assistant `text` blocks contain lines like `Tool call`, `Cursor activity`, or `call cursor-replay-…` without matching `toolCall` blocks — narration is not tool execution. Structured history now uses `Historical tool request/result/error` labels, retaining arguments, IDs and errors without implying an unmatched request completed. This reduces an imitable template; it does not prevent model narration or strip legitimate prose/code examples. Raw assistant history is preserved and prose is never converted into tool calls or automatically resent. See [Tool calls listed as plain text (#40 triage)](docs/cursor-testing-lessons.md#tool-calls-listed-as-plain-text-40-triage).
|
|
802
|
-
- **Stale replay routing / plan-strip:** Error `toolResult` or error assistant messages contain `Tool grep/cursor/find/ls not found`, or provider debug shows `inactive_trace` after plan-mode execute stripped active tools — tracked in **#52** (distinct from model text echo and #55).
|
|
803
|
-
- **Replay vs execution:** `cursor-replay-*` IDs and neutral **Cursor MCP** activity cards are display-only recorded Cursor results; they do not re-run browser/MCP work. See [Cursor native tool replay](docs/cursor-native-tool-replay.md).
|
|
804
|
-
- **Run failure / discarded tools:** A red toast with scrubbed detail may indicate an SDK failure (#55). Started-but-never-completed Cursor tools surface neutral **Cursor … did not complete** activity cards with a bounded reason when the run failed/aborted, produced no assistant text, or involved external/side-effectful tools. Incomplete fast local discovery starts (`read`, `grep`, `glob`, `ls`) are debug-only after a successful text-producing run so stale SDK start events do not create red post-answer cards; maintainer debug for the same gap remains in **#52** (`PI_CURSOR_SDK_EVENT_DEBUG=1`).
|
|
805
|
-
- **Hard SDK crash:** pi exited with an uncaught Cursor SDK `ConnectError` or `WriteIterableClosedError` instead of showing a normal run error — capture the stack/session tail as a process-guard regression, not #40 text echo.
|
|
806
|
-
|
|
807
|
-
Shell correlation accepts legacy names (`shell`, `bash`, `run_terminal_cmd`) with different IDs only when exactly one pending shell has identical arguments; exact IDs take precedence. This is compatibility handling, not evidence that SDK 1.0.37 emits alias-changing callback pairs. Its public shell payload uses `type: "shell"`; retained SDK 1.0.36 installed-accumulator evidence shows `onStep` preserving that completed ToolCall without adding a step ID. Assistant text or stdout progress alone does not establish completion; unmatched shell starts still remain visible and debug capture is unchanged.
|
|
808
|
-
|
|
809
|
-
Capture `pi --version`, extension version, model, flags, the exact prompt, and a redacted session dir before filing bugs.
|
|
810
|
-
|
|
811
|
-
### Cursor native tool cards conflict with another extension
|
|
812
|
-
|
|
813
|
-
Cursor native replay is a display enhancement for TUI sessions and structured JSON/RPC consumers. It replays recorded Cursor SDK activity without re-running tools, and print mode remains text-first. See [Cursor native tool replay](docs/cursor-native-tool-replay.md) for conflict behavior and opt-out flags.
|
|
814
|
-
|
|
815
|
-
## Automatic npm releases (maintainers)
|
|
816
|
-
|
|
817
|
-
Follow the [shared release procedure](https://github.com/fitchmultz/.github#automatic-npm-releases): merge a reviewed PR into `main` with an intentional `package.json` version bump and a matching versioned `CHANGELOG.md` section. Automation never bumps versions, overwrites releases, or republishes an existing version. Once configured and enabled, it runs the existing offline compatibility and native macOS/Windows jobs, qualifies one candidate tarball, then waits for `fitchmultz` approval in the `npm` environment.
|
|
818
|
-
|
|
819
|
-
Approve only after checking the exact source commit, version, downloaded candidate tarball and summary against the [release review gate](AGENTS.md#release-review-gate-maintainer) and [cost-conscious verification policy](#maintainer-cost-conscious-verification). Complete the exact-release-diff deep review with zero findings, the documented pre-release catalog check, and any genuinely necessary changed-behavior proof. Approval attests genuine satisfaction of existing requirements; it does not create proof. Authenticated checks remain outside CI; automated Cursor PR reviews remain unchanged, and no routine paid Cloud campaigns or paid retries are added. Automated publication disables npm hooks to publish the checked bytes; existing manual publisher instructions remain valid.
|
|
820
|
-
|
|
821
|
-
Failed/unpublished candidates can retry daily at 12:17 UTC or via manual dispatch of `npm release` on `main` only while the current source still owns the same version, tag, draft, and candidate assets. Inspect their exact source/run identities first: an authentication repair alone does not authorize publishing an old candidate after `main` advances. When source advances beyond a reserved candidate, use the next unused stable version and fresh qualification; never move its tag, overwrite its draft/assets, or relabel old proof. The [0.5.1 changelog](CHANGELOG.md#051-unpublished-source-history) is unpublished source history carried into 0.5.2, not a successful publication record. Set repository variable `NPM_RELEASE_ENABLED` to anything other than `true` to stop new release plans; cancel pending runs separately when needed. Workflow validation is not evidence of a completed real OIDC publication.
|
|
822
|
-
|
|
823
|
-
Publication records are independent: on 2026-10-07, npm listed 0.5.2 as published and `latest`, while GitHub's `v0.5.2` release remained a draft bound to source `9820ae7`. Preserve that tag, draft, and candidate assets unchanged. The 0.5.3 source uses a new version and candidate; its preparation is not proof of npm or GitHub publication.
|
|
824
|
-
|
|
825
|
-
## Development
|
|
826
|
-
|
|
827
|
-
Required qualification targets are the latest stable official Pi and latest maintained `fitchmultz/pi` main, with optional wildcard Pi/TypeBox host peers and exact Cursor SDK **1.0.37**. CI resolves the official version/fork commit once and retains exact SDK/CLI provenance. Types, tests and package checks use each selected host's consistent dependency graph; the locked development Pi **1.0.4** dependencies are reproducible snapshots, not qualification targets. After `npm ci --ignore-scripts`, run `node scripts/ci-compatibility.mjs --automation /path/to/automation` in an empty HOME/agent profile for credential-free latest qualification. Native macOS/Windows checks select the same resolved latest official graph. This builds the manifest entry, runs existing type/unit/package checks, and tests the compiled provider's registration plus production prompt shaping against native Pi transcript/tool transitions. Replay arguments must match their JSON stream deltas. A second native contract runs the registered Cursor provider with only its external SDK transport/storage substituted: real loopback bridge execution, display-only replay, persisted usage, incremental sends, tree navigation, compaction, request-boundary steering, abort and reload/disposal. Tests use no live Cursor service.
|
|
828
|
-
|
|
829
|
-
TypeScript 7 builds and checks package types. Build and typecheck commands invoke `node_modules/typescript/bin/tsc` explicitly to avoid npm's shared `tsc` shim selecting a different compiler. `@typescript/typescript6` is dev-only for AST architecture and installed-SDK contract tests because TypeScript 7 does not expose a stable compiler API. Vitest 5 runs with `clearMocks: true` by default.
|
|
830
|
-
|
|
831
|
-
Pull-request CI runs that suite once per selected host: the latest stable official Pi and a source-built revision of the latest maintained fork `main`, each using its own consistent dependency graph and the version/commit resolved once for the run. It checks both npm and Git installations against both hosts without starting a Cursor model turn. The selected official version and fork commit are printed in the check log. Separate macOS and Windows jobs install with lifecycle scripts, load `node-pty`, and run the platform-build test, typecheck, and pack checks on Node 24.
|
|
832
|
-
|
|
833
|
-
For authorized uncommitted repairs, qualify an isolated immutable working-tree snapshot without committing:
|
|
834
|
-
|
|
835
|
-
```bash
|
|
836
|
-
node scripts/ci-compatibility.mjs --working-tree --official-only --versions 0.87.1,0.99.1,1.0.3
|
|
837
|
-
```
|
|
838
|
-
|
|
839
|
-
This builds and packs the snapshot, checks package loading, and exercises actual official native provider/session flows. The default invocation still requires a clean checkout and includes the maintained fork. `--help` documents selection and exit codes.
|
|
840
|
-
|
|
841
|
-
This manual snapshot mode retains explicit older-host qualification for the advertised floor; it is separate from CI's once-resolved latest-only targets. Do not combine manual selection flags with `--automation`.
|
|
842
|
-
|
|
843
|
-
This is offline compatibility proof, not Cursor authentication, desktop/cloud execution, visual, or all-platform live proof. Add only necessary changed-behavior live evidence under the [cost-conscious verification policy](#maintainer-cost-conscious-verification); the comprehensive paid matrix is optional, and paid Cloud testing is restricted to explicitly Cursor Cloud-focused PRs/issues. Older advertised Pi/Node floors require their own offline compatibility evidence.
|
|
844
|
-
|
|
845
|
-
Run checks:
|
|
846
|
-
|
|
847
|
-
```bash
|
|
848
|
-
npm test
|
|
849
|
-
npm run typecheck
|
|
850
|
-
```
|
|
851
|
-
|
|
852
|
-
Check the reviewable Cursor fallback catalog against the authenticated live catalog before releases:
|
|
853
|
-
|
|
854
|
-
```bash
|
|
855
|
-
CURSOR_API_KEY="your-key" npm run check:cursor-snapshots
|
|
856
|
-
```
|
|
857
|
-
|
|
858
|
-
Refresh it after Cursor model changes:
|
|
859
|
-
|
|
860
|
-
```bash
|
|
861
|
-
CURSOR_API_KEY="your-key" npm run refresh:cursor-snapshots -- --write
|
|
862
|
-
```
|
|
863
|
-
|
|
864
|
-
Refresh the bundled default/non-Max context-window snapshot only when checkpoint-derived context windows have been collected from live local runs:
|
|
865
|
-
|
|
866
|
-
```bash
|
|
867
|
-
CURSOR_API_KEY="your-key" npm run refresh:cursor-snapshots -- --write \
|
|
868
|
-
--context-windows ~/.pi/agent/cursor-sdk-context-windows.json
|
|
869
|
-
```
|
|
870
|
-
|
|
871
|
-
The check and refresh modes fetch and sort the same sanitized live catalog. Check mode byte-compares the generated fallback without writing; generated provenance records the installed `@cursor/sdk` version and model count. Both modes print public model metadata only and scrub known auth material from SDK errors. Do not run them with shell tracing that would echo API keys.
|
|
115
|
+
| Problem | Action |
|
|
116
|
+
| --- | --- |
|
|
117
|
+
| Models appear, but a run fails | Run `/login` with an API key for Cursor SDK. Run `/cursor-refresh-models`. |
|
|
118
|
+
| First reply is slow | Check configured Cursor MCP servers. Read [settings and connection limits](docs/reference.md#first-cursor-message-is-slow-10-seconds). |
|
|
119
|
+
| Streams fail behind a VPN or proxy | Run `/cursor-http on`. This changes the local SDK transport only. |
|
|
120
|
+
| Fallback catalog remains with a saved key | Read the [startup refresh limit](docs/reference.md#model-catalog-cache) for affected Pi versions. |
|
|
872
121
|
|
|
873
|
-
|
|
122
|
+
See [Troubleshooting](docs/reference.md#troubleshooting) for other problems. [Report a bug](https://github.com/fitchmultz/pi-cursor-sdk/issues) with Pi/extension versions, model, flags, exact prompt, and a redacted session.
|
|
874
123
|
|
|
875
|
-
|
|
876
|
-
npm install
|
|
877
|
-
CURSOR_API_KEY="your-key" pi --approve -e . --model cursor/grok-4.6
|
|
878
|
-
```
|
|
124
|
+
Debug artifacts can contain secrets. Remove secrets before you share them.
|
|
879
125
|
|
|
880
|
-
|
|
126
|
+
## Reference and development
|
|
881
127
|
|
|
882
|
-
|
|
128
|
+
The [full reference](docs/reference.md) contains detailed configuration and limits. [Development](docs/development.md) covers checks, model snapshots, and release procedures. The [model UX spec](docs/cursor-model-ux-spec.md) contains maintainer design notes. The [Changelog](CHANGELOG.md) records version history.
|
|
883
129
|
|
|
884
130
|
## License
|
|
885
131
|
|
|
886
|
-
MIT
|
|
132
|
+
[MIT](LICENSE) · Mitch Fultz
|