@rama_nigg/open-cursor 2.3.1 → 2.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -241
- package/dist/cli/discover.js +0 -15
- package/dist/cli/opencode-cursor.js +44 -19
- package/dist/index.js +70 -85
- package/dist/plugin-entry.js +81 -86
- package/package.json +7 -2
- package/src/cli/opencode-cursor.ts +45 -4
- package/src/plugin-toggle.ts +9 -1
package/README.md
CHANGED
|
@@ -5,13 +5,24 @@
|
|
|
5
5
|
<img src="https://img.shields.io/badge/macOS-000000?style=for-the-badge&logo=apple&logoColor=white" alt="macOS" />
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
|
-
No prompt limits. No broken streams. Full thinking + tool support in
|
|
8
|
+
No prompt limits. No broken streams. Full thinking + tool support in OpenCode. Your Cursor subscription, properly integrated.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
Required: [OpenCode](https://opencode.ai/) + [cursor-agent](https://cursor.com/) (`curl -fsSL https://cursor.com/install | bash && cursor-agent login`)
|
|
13
|
+
Optional: [Bun](https://bun.sh/) (Options B-F), [Go 1.21+](https://go.dev/) (Option D)
|
|
9
14
|
|
|
10
15
|
## Installation
|
|
11
16
|
|
|
12
|
-
|
|
17
|
+
### Option A — One-line installer
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
curl -fsSL https://raw.githubusercontent.com/Nomadcxx/opencode-cursor/main/install.sh | bash
|
|
21
|
+
```
|
|
13
22
|
|
|
14
|
-
|
|
23
|
+
### Option B — Add to opencode.json
|
|
24
|
+
|
|
25
|
+
Add to `~/.config/opencode/opencode.json`:
|
|
15
26
|
|
|
16
27
|
```json
|
|
17
28
|
{
|
|
@@ -21,45 +32,57 @@ The simplest approach—just add the npm package to your OpenCode config:
|
|
|
21
32
|
"name": "Cursor ACP",
|
|
22
33
|
"npm": "@ai-sdk/openai-compatible",
|
|
23
34
|
"models": {
|
|
24
|
-
"cursor-acp/
|
|
25
|
-
"cursor-acp/
|
|
26
|
-
"cursor-acp/
|
|
27
|
-
"cursor-acp/
|
|
35
|
+
"cursor-acp/auto": { "name": "Auto" },
|
|
36
|
+
"cursor-acp/composer-1.5": { "name": "Composer 1.5" },
|
|
37
|
+
"cursor-acp/composer-1": { "name": "Composer 1" },
|
|
38
|
+
"cursor-acp/gpt-5.3-codex": { "name": "GPT-5.3 Codex" },
|
|
39
|
+
"cursor-acp/gpt-5.3-codex-low": { "name": "GPT-5.3 Codex Low" },
|
|
40
|
+
"cursor-acp/gpt-5.3-codex-high": { "name": "GPT-5.3 Codex High" },
|
|
41
|
+
"cursor-acp/gpt-5.3-codex-xhigh": { "name": "GPT-5.3 Codex Extra High" },
|
|
42
|
+
"cursor-acp/gpt-5.3-codex-fast": { "name": "GPT-5.3 Codex Fast" },
|
|
43
|
+
"cursor-acp/gpt-5.3-codex-low-fast": { "name": "GPT-5.3 Codex Low Fast" },
|
|
44
|
+
"cursor-acp/gpt-5.3-codex-high-fast": { "name": "GPT-5.3 Codex High Fast" },
|
|
45
|
+
"cursor-acp/gpt-5.3-codex-xhigh-fast": { "name": "GPT-5.3 Codex Extra High Fast" },
|
|
46
|
+
"cursor-acp/gpt-5.2": { "name": "GPT-5.2" },
|
|
47
|
+
"cursor-acp/gpt-5.2-codex": { "name": "GPT-5.2 Codex" },
|
|
48
|
+
"cursor-acp/gpt-5.2-codex-high": { "name": "GPT-5.2 Codex High" },
|
|
49
|
+
"cursor-acp/gpt-5.2-codex-low": { "name": "GPT-5.2 Codex Low" },
|
|
50
|
+
"cursor-acp/gpt-5.2-codex-xhigh": { "name": "GPT-5.2 Codex Extra High" },
|
|
51
|
+
"cursor-acp/gpt-5.2-codex-fast": { "name": "GPT-5.2 Codex Fast" },
|
|
52
|
+
"cursor-acp/gpt-5.2-codex-high-fast": { "name": "GPT-5.2 Codex High Fast" },
|
|
53
|
+
"cursor-acp/gpt-5.2-codex-low-fast": { "name": "GPT-5.2 Codex Low Fast" },
|
|
54
|
+
"cursor-acp/gpt-5.2-codex-xhigh-fast": { "name": "GPT-5.2 Codex Extra High Fast" },
|
|
55
|
+
"cursor-acp/gpt-5.1-codex-max": { "name": "GPT-5.1 Codex Max" },
|
|
56
|
+
"cursor-acp/gpt-5.1-codex-max-high": { "name": "GPT-5.1 Codex Max High" },
|
|
57
|
+
"cursor-acp/opus-4.6-thinking": { "name": "Claude 4.6 Opus (Thinking)" },
|
|
58
|
+
"cursor-acp/sonnet-4.5-thinking": { "name": "Claude 4.5 Sonnet (Thinking)" },
|
|
59
|
+
"cursor-acp/gpt-5.2-high": { "name": "GPT-5.2 High" },
|
|
60
|
+
"cursor-acp/opus-4.6": { "name": "Claude 4.6 Opus" },
|
|
61
|
+
"cursor-acp/opus-4.5": { "name": "Claude 4.5 Opus" },
|
|
62
|
+
"cursor-acp/opus-4.5-thinking": { "name": "Claude 4.5 Opus (Thinking)" },
|
|
63
|
+
"cursor-acp/sonnet-4.5": { "name": "Claude 4.5 Sonnet" },
|
|
64
|
+
"cursor-acp/gpt-5.1-high": { "name": "GPT-5.1 High" },
|
|
65
|
+
"cursor-acp/gemini-3-pro": { "name": "Gemini 3 Pro" },
|
|
66
|
+
"cursor-acp/gemini-3-flash": { "name": "Gemini 3 Flash" },
|
|
67
|
+
"cursor-acp/grok": { "name": "Grok" }
|
|
28
68
|
}
|
|
29
69
|
}
|
|
30
70
|
}
|
|
31
71
|
}
|
|
32
72
|
```
|
|
33
73
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
**Prerequisites:** Only OpenCode required. OpenCode's Bun runtime resolves the npm package automatically.
|
|
37
|
-
|
|
38
|
-
**Option B — One-line installer (curl)**
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
curl -fsSL https://raw.githubusercontent.com/Nomadcxx/opencode-cursor/main/install.sh | bash
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
This automated installer detects your environment and chooses the best installation method.
|
|
74
|
+
> Update models anytime: `cursor-agent models`
|
|
45
75
|
|
|
46
|
-
|
|
76
|
+
### Option C — npm global + CLI
|
|
47
77
|
|
|
48
78
|
```bash
|
|
49
79
|
npm install -g @rama_nigg/open-cursor
|
|
50
80
|
open-cursor install
|
|
51
81
|
```
|
|
52
82
|
|
|
53
|
-
Upgrade
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
npm update -g @rama_nigg/open-cursor
|
|
57
|
-
open-cursor install
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
**Option D — Go TUI installer**
|
|
83
|
+
Upgrade: `npm update -g @rama_nigg/open-cursor`
|
|
61
84
|
|
|
62
|
-
|
|
85
|
+
### Option D — Go TUI installer
|
|
63
86
|
|
|
64
87
|
```bash
|
|
65
88
|
git clone https://github.com/Nomadcxx/opencode-cursor.git
|
|
@@ -67,148 +90,30 @@ cd opencode-cursor
|
|
|
67
90
|
go build -o ./installer ./cmd/installer && ./installer
|
|
68
91
|
```
|
|
69
92
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
Paste this into any LLM agent (Claude Code, OpenCode, Cursor, etc.):
|
|
93
|
+
### Option E — LLM paste
|
|
73
94
|
|
|
74
95
|
```
|
|
75
|
-
Install
|
|
76
|
-
|
|
77
|
-
1. Edit your opencode.json config file (usually at ~/.config/opencode/opencode.json)
|
|
78
|
-
2. Add "@rama_nigg/open-cursor@latest" to the plugin array
|
|
79
|
-
3. Add the cursor-acp provider configuration with models
|
|
80
|
-
4. Restart OpenCode
|
|
81
|
-
|
|
82
|
-
Example configuration:
|
|
83
|
-
{
|
|
84
|
-
"plugin": ["@rama_nigg/open-cursor@latest"],
|
|
85
|
-
"provider": {
|
|
86
|
-
"cursor-acp": {
|
|
87
|
-
"name": "Cursor ACP",
|
|
88
|
-
"npm": "@ai-sdk/openai-compatible",
|
|
89
|
-
"models": {
|
|
90
|
-
"cursor-acp/claude-sonnet": { "name": "Claude Sonnet" }
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
5. Authenticate: cursor-agent login
|
|
97
|
-
6. Verify: opencode models | grep cursor-acp
|
|
96
|
+
Install open-cursor for OpenCode: edit ~/.config/opencode/opencode.json, add "@rama_nigg/open-cursor@latest" to "plugin", add a "cursor-acp" provider with npm "@ai-sdk/openai-compatible" and models from `cursor-agent models` prefixed with "cursor-acp/". Auth: `cursor-agent login`. Verify: `opencode models | grep cursor-acp`.
|
|
98
97
|
```
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
For developers and contributors who want full control:
|
|
99
|
+
### Option F — Manual (from source)
|
|
103
100
|
|
|
104
101
|
```bash
|
|
105
|
-
git clone https://github.com/Nomadcxx/opencode-cursor.git
|
|
106
|
-
cd opencode-cursor
|
|
102
|
+
git clone https://github.com/Nomadcxx/opencode-cursor.git && cd opencode-cursor
|
|
107
103
|
bun install && bun run build
|
|
108
|
-
mkdir -p ~/.config/opencode/plugin
|
|
109
104
|
ln -sf $(pwd)/dist/plugin-entry.js ~/.config/opencode/plugin/cursor-acp.js
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
The automated installers handle configuration automatically. For manual installs, run the sync script to populate models:
|
|
113
|
-
|
|
114
|
-
```bash
|
|
115
105
|
./scripts/sync-models.sh
|
|
116
106
|
```
|
|
117
107
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```json
|
|
121
|
-
{
|
|
122
|
-
"plugin": ["cursor-acp"],
|
|
123
|
-
"provider": {
|
|
124
|
-
"cursor-acp": {
|
|
125
|
-
"name": "Cursor",
|
|
126
|
-
"npm": "@ai-sdk/openai-compatible",
|
|
127
|
-
"options": { "baseURL": "http://127.0.0.1:32124/v1" },
|
|
128
|
-
"models": {
|
|
129
|
-
"auto": { "name": "Auto" },
|
|
130
|
-
"composer-1.5": { "name": "Composer 1.5" },
|
|
131
|
-
"composer-1": { "name": "Composer 1" },
|
|
132
|
-
"gpt-5.3-codex": { "name": "GPT-5.3 Codex" },
|
|
133
|
-
"gpt-5.3-codex-low": { "name": "GPT-5.3 Codex Low" },
|
|
134
|
-
"gpt-5.3-codex-high": { "name": "GPT-5.3 Codex High" },
|
|
135
|
-
"gpt-5.3-codex-xhigh": { "name": "GPT-5.3 Codex Extra High" },
|
|
136
|
-
"gpt-5.3-codex-fast": { "name": "GPT-5.3 Codex Fast" },
|
|
137
|
-
"gpt-5.3-codex-low-fast": { "name": "GPT-5.3 Codex Low Fast" },
|
|
138
|
-
"gpt-5.3-codex-high-fast": { "name": "GPT-5.3 Codex High Fast" },
|
|
139
|
-
"gpt-5.3-codex-xhigh-fast": { "name": "GPT-5.3 Codex Extra High Fast" },
|
|
140
|
-
"gpt-5.2": { "name": "GPT-5.2" },
|
|
141
|
-
"gpt-5.2-codex": { "name": "GPT-5.2 Codex" },
|
|
142
|
-
"gpt-5.2-codex-high": { "name": "GPT-5.2 Codex High" },
|
|
143
|
-
"gpt-5.2-codex-low": { "name": "GPT-5.2 Codex Low" },
|
|
144
|
-
"gpt-5.2-codex-xhigh": { "name": "GPT-5.2 Codex Extra High" },
|
|
145
|
-
"gpt-5.2-codex-fast": { "name": "GPT-5.2 Codex Fast" },
|
|
146
|
-
"gpt-5.2-codex-high-fast": { "name": "GPT-5.2 Codex High Fast" },
|
|
147
|
-
"gpt-5.2-codex-low-fast": { "name": "GPT-5.2 Codex Low Fast" },
|
|
148
|
-
"gpt-5.2-codex-xhigh-fast": { "name": "GPT-5.2 Codex Extra High Fast" },
|
|
149
|
-
"gpt-5.1-codex-max": { "name": "GPT-5.1 Codex Max" },
|
|
150
|
-
"gpt-5.1-codex-max-high": { "name": "GPT-5.1 Codex Max High" },
|
|
151
|
-
"opus-4.6-thinking": { "name": "Claude 4.6 Opus (Thinking)" },
|
|
152
|
-
"sonnet-4.5-thinking": { "name": "Claude 4.5 Sonnet (Thinking)" },
|
|
153
|
-
"gpt-5.2-high": { "name": "GPT-5.2 High" },
|
|
154
|
-
"opus-4.6": { "name": "Claude 4.6 Opus" },
|
|
155
|
-
"opus-4.5": { "name": "Claude 4.5 Opus" },
|
|
156
|
-
"opus-4.5-thinking": { "name": "Claude 4.5 Opus (Thinking)" },
|
|
157
|
-
"sonnet-4.5": { "name": "Claude 4.5 Sonnet" },
|
|
158
|
-
"gpt-5.1-high": { "name": "GPT-5.1 High" },
|
|
159
|
-
"gemini-3-pro": { "name": "Gemini 3 Pro" },
|
|
160
|
-
"gemini-3-flash": { "name": "Gemini 3 Flash" },
|
|
161
|
-
"grok": { "name": "Grok" }
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### Plugin Configuration Reference
|
|
169
|
-
|
|
170
|
-
Depending on your installation method, use the appropriate plugin identifier:
|
|
171
|
-
|
|
172
|
-
**npm package (recommended for production):**
|
|
173
|
-
```json
|
|
174
|
-
"plugin": ["@rama_nigg/open-cursor@latest"]
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
**Local build (for development):**
|
|
178
|
-
```json
|
|
179
|
-
"plugin": ["cursor-acp"]
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
Both approaches work—the npm package is resolved automatically by OpenCode's Bun runtime, while the local build requires the symlink setup shown in Option F above.
|
|
108
|
+
Add `"cursor-acp"` to the `plugin` array and reuse the provider block from Option B.
|
|
183
109
|
|
|
184
110
|
## Authentication
|
|
185
111
|
|
|
186
|
-
### Option 1: Via OpenCode (Recommended)
|
|
187
|
-
|
|
188
|
-
```bash
|
|
189
|
-
opencode auth login
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
Then follow the prompts:
|
|
193
|
-
|
|
194
|
-
1. Select **"Other"** from the provider list
|
|
195
|
-
2. Enter provider id: **cursor-acp**
|
|
196
|
-
3. Browser will open automatically - click "Continue with Cursor"
|
|
197
|
-
4. Return to terminal when you see "Login successful"
|
|
198
|
-
|
|
199
|
-
### Option 2: Direct (CLI only)
|
|
200
|
-
|
|
201
112
|
```bash
|
|
202
|
-
cursor-
|
|
113
|
+
opencode auth login # provider id: cursor-acp
|
|
114
|
+
cursor-agent login # direct
|
|
203
115
|
```
|
|
204
116
|
|
|
205
|
-
Then open the URL shown in your browser and complete authentication.
|
|
206
|
-
|
|
207
|
-
Credential file locations:
|
|
208
|
-
|
|
209
|
-
- macOS: `~/.cursor/cli-config.json` (current) or `~/.cursor/auth.json` (legacy)
|
|
210
|
-
- Linux: `~/.config/cursor/cli-config.json` or `~/.config/cursor/auth.json` (or `$XDG_CONFIG_HOME/cursor/`)
|
|
211
|
-
|
|
212
117
|
## Usage
|
|
213
118
|
|
|
214
119
|
```bash
|
|
@@ -221,7 +126,7 @@ opencode run "your prompt" --model cursor-acp/sonnet-4.5
|
|
|
221
126
|
```mermaid
|
|
222
127
|
flowchart TB
|
|
223
128
|
OC["OpenCode"] --> SDK["@ai-sdk/openai-compatible"]
|
|
224
|
-
SDK -->|"POST /v1/chat/completions"| PROXY["cursor
|
|
129
|
+
SDK -->|"POST /v1/chat/completions"| PROXY["open-cursor proxy :32124"]
|
|
225
130
|
PROXY -->|"spawn per request"| AGENT["cursor-agent --output-format stream-json"]
|
|
226
131
|
AGENT -->|"HTTPS"| CURSOR["Cursor API"]
|
|
227
132
|
CURSOR --> AGENT
|
|
@@ -238,101 +143,32 @@ flowchart TB
|
|
|
238
143
|
SDK -->|"TOOL_RESULT prompt block"| AGENT
|
|
239
144
|
```
|
|
240
145
|
|
|
241
|
-
Default mode
|
|
242
|
-
Legacy execution mode (`proxy-exec`) is still available for local/SDK/MCP execution through the internal router.
|
|
243
|
-
|
|
244
|
-
Detailed architecture: [docs/architecture/runtime-tool-loop.md](docs/architecture/runtime-tool-loop.md).
|
|
146
|
+
Default mode: `CURSOR_ACP_TOOL_LOOP_MODE=opencode`. Legacy `proxy-exec` still available. Details: [docs/architecture/runtime-tool-loop.md](docs/architecture/runtime-tool-loop.md).
|
|
245
147
|
|
|
246
148
|
## Alternatives
|
|
247
149
|
|
|
248
|
-
| |
|
|
249
|
-
| ----------------- |
|
|
150
|
+
| | open-cursor | [yet-another-opencode-cursor-auth](https://github.com/Yukaii/yet-another-opencode-cursor-auth) | [opencode-cursor-auth](https://github.com/POSO-PocketSolutions/opencode-cursor-auth) | [cursor-opencode-auth](https://github.com/R44VC0RP/cursor-opencode-auth) |
|
|
151
|
+
| ----------------- | :------------------------: | :--------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------: | :----------------------------------------------------------------------: |
|
|
250
152
|
| **Architecture** | HTTP proxy via cursor-agent | Direct Connect-RPC | HTTP proxy via cursor-agent | Direct Connect-RPC/protobuf |
|
|
251
|
-
| **Platform** |
|
|
252
|
-
| **Max Prompt** |
|
|
253
|
-
| **Streaming** |
|
|
254
|
-
| **Error Parsing** |
|
|
255
|
-
| **Installer** |
|
|
256
|
-
| **OAuth Flow** |
|
|
257
|
-
| **Tool Calling** | ✓ OpenCode-owned loop
|
|
258
|
-
| **Stability** | Stable (uses official CLI)
|
|
259
|
-
| **Dependencies** |
|
|
260
|
-
| **Port** |
|
|
261
|
-
|
|
262
|
-
## Prerequisites
|
|
263
|
-
|
|
264
|
-
**For Option A (npm-direct):** Only [OpenCode](https://opencode.ai/) required.
|
|
265
|
-
|
|
266
|
-
**For Options B-F:**
|
|
267
|
-
- [Bun](https://bun.sh/)
|
|
268
|
-
- [cursor-agent](https://cursor.com/) - `curl -fsSL https://cursor.com/install | bash`
|
|
269
|
-
|
|
270
|
-
**Option B (one-line install):** If Go is installed, the script runs the TUI installer; otherwise it performs a shell-only install (OpenCode + cursor-agent required). For syncing models without the TUI, install [jq](https://jq.org/) or run `./scripts/sync-models.sh` after install.
|
|
271
|
-
|
|
272
|
-
**Option D (TUI installer):** Go 1.21+ required to build the installer.
|
|
273
|
-
|
|
274
|
-
## Features
|
|
275
|
-
|
|
276
|
-
- HTTP proxy (avoids E2BIG errors)
|
|
277
|
-
- Streaming responses with thinking and tool call support
|
|
278
|
-
- OAuth authentication
|
|
279
|
-
- Error parsing (quota/auth/network)
|
|
280
|
-
|
|
281
|
-
## Development
|
|
282
|
-
|
|
283
|
-
Build and run tests locally:
|
|
284
|
-
|
|
285
|
-
```bash
|
|
286
|
-
bun install
|
|
287
|
-
bun run build
|
|
288
|
-
bun run test:ci:unit
|
|
289
|
-
bun run test:ci:integration
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
CI runs split suites in `.github/workflows/ci.yml`:
|
|
293
|
-
|
|
294
|
-
- `unit` job: `bun run test:ci:unit`
|
|
295
|
-
- `integration` job: `bun run test:ci:integration`
|
|
296
|
-
|
|
297
|
-
Integration CI pins OpenCode-owned loop mode to deterministic settings:
|
|
298
|
-
|
|
299
|
-
- `CURSOR_ACP_TOOL_LOOP_MODE=opencode`
|
|
300
|
-
- `CURSOR_ACP_PROVIDER_BOUNDARY=v1`
|
|
301
|
-
- `CURSOR_ACP_PROVIDER_BOUNDARY_AUTOFALLBACK=false`
|
|
302
|
-
- `CURSOR_ACP_TOOL_LOOP_MAX_REPEAT=3`
|
|
303
|
-
- `CURSOR_ACP_ENABLE_OPENCODE_TOOLS=true`
|
|
304
|
-
- `CURSOR_ACP_FORWARD_TOOL_CALLS=false`
|
|
305
|
-
- `CURSOR_ACP_EMIT_TOOL_UPDATES=false`
|
|
153
|
+
| **Platform** | Linux, macOS | Linux, macOS | Linux, macOS | macOS only (Keychain) |
|
|
154
|
+
| **Max Prompt** | Unlimited (HTTP body) | Unknown | ~128KB (ARG_MAX) | Unknown |
|
|
155
|
+
| **Streaming** | ✓ SSE | ✓ SSE | Undocumented | ✓ |
|
|
156
|
+
| **Error Parsing** | ✓ (quota/auth/model) | ✗ | ✗ | Debug logging |
|
|
157
|
+
| **Installer** | ✓ TUI + one-liner | ✗ | ✗ | ✗ |
|
|
158
|
+
| **OAuth Flow** | ✓ OpenCode integration | ✓ Native | Browser login | Keychain |
|
|
159
|
+
| **Tool Calling** | ✓ OpenCode-owned loop + proxy-exec | ✓ Native | ✓ Experimental | ✗ |
|
|
160
|
+
| **Stability** | Stable (uses official CLI) | Experimental | Stable | Experimental |
|
|
161
|
+
| **Dependencies** | bun, cursor-agent | npm | bun, cursor-agent | Node.js 18+ |
|
|
162
|
+
| **Port** | 32124 | 18741 | 32123 | 4141 |
|
|
306
163
|
|
|
307
164
|
## Troubleshooting
|
|
308
165
|
|
|
309
|
-
|
|
166
|
+
- `fetch() URL is invalid` → `opencode auth login`
|
|
167
|
+
- Model not responding → `cursor-agent login`
|
|
168
|
+
- Quota exceeded → [cursor.com/settings](https://cursor.com/settings)
|
|
169
|
+
- Auth failed → `CURSOR_ACP_LOG_LEVEL=debug opencode auth login cursor-acp`
|
|
310
170
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
**Quota exceeded** - Check [cursor.com/settings](https://cursor.com/settings)
|
|
314
|
-
|
|
315
|
-
**Authentication failed or incomplete** - Enable debug logging to diagnose:
|
|
316
|
-
```bash
|
|
317
|
-
CURSOR_ACP_LOG_LEVEL=debug opencode auth login cursor-acp
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
Common causes:
|
|
321
|
-
- Browser didn't open automatically - manually open the URL shown in the terminal
|
|
322
|
-
- Auth file not created - ensure `cursor-agent login` works directly first
|
|
323
|
-
- Timeout - authentication must complete within 5 minutes
|
|
324
|
-
|
|
325
|
-
### Debug Logging
|
|
326
|
-
|
|
327
|
-
Enable verbose logs:
|
|
328
|
-
```bash
|
|
329
|
-
CURSOR_ACP_LOG_LEVEL=debug opencode run "your prompt" --model cursor-acp/auto
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
Disable log output entirely:
|
|
333
|
-
```bash
|
|
334
|
-
CURSOR_ACP_LOG_SILENT=true opencode run "your prompt"
|
|
335
|
-
```
|
|
171
|
+
Debug logging: `CURSOR_ACP_LOG_LEVEL=debug opencode run "your prompt" --model cursor-acp/auto`
|
|
336
172
|
|
|
337
173
|
## License
|
|
338
174
|
|
package/dist/cli/discover.js
CHANGED
|
@@ -1,21 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
5
3
|
var __defProp = Object.defineProperty;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
9
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
10
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
11
|
-
for (let key of __getOwnPropNames(mod))
|
|
12
|
-
if (!__hasOwnProp.call(to, key))
|
|
13
|
-
__defProp(to, key, {
|
|
14
|
-
get: () => mod[key],
|
|
15
|
-
enumerable: true
|
|
16
|
-
});
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
4
|
var __export = (target, all) => {
|
|
20
5
|
for (var name in all)
|
|
21
6
|
__defProp(target, name, {
|
|
@@ -1,21 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
5
3
|
var __defProp = Object.defineProperty;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
9
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
10
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
11
|
-
for (let key of __getOwnPropNames(mod))
|
|
12
|
-
if (!__hasOwnProp.call(to, key))
|
|
13
|
-
__defProp(to, key, {
|
|
14
|
-
get: () => mod[key],
|
|
15
|
-
enumerable: true
|
|
16
|
-
});
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
4
|
var __export = (target, all) => {
|
|
20
5
|
for (var name in all)
|
|
21
6
|
__defProp(target, name, {
|
|
@@ -236,9 +221,24 @@ function checkOpenCode() {
|
|
|
236
221
|
};
|
|
237
222
|
}
|
|
238
223
|
}
|
|
239
|
-
function
|
|
224
|
+
function isNpmDirectInstalled(config) {
|
|
225
|
+
if (!config || typeof config !== "object")
|
|
226
|
+
return false;
|
|
227
|
+
const plugins = config.plugin;
|
|
228
|
+
if (!Array.isArray(plugins))
|
|
229
|
+
return false;
|
|
230
|
+
return plugins.some((p) => typeof p === "string" && p.startsWith(NPM_PACKAGE_PREFIX));
|
|
231
|
+
}
|
|
232
|
+
function checkPluginFile(pluginPath, config) {
|
|
240
233
|
try {
|
|
241
234
|
if (!existsSync(pluginPath)) {
|
|
235
|
+
if (isNpmDirectInstalled(config)) {
|
|
236
|
+
return {
|
|
237
|
+
name: "Plugin file",
|
|
238
|
+
passed: true,
|
|
239
|
+
message: "Installed via npm package (no symlink needed)"
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
242
|
return {
|
|
243
243
|
name: "Plugin file",
|
|
244
244
|
passed: false,
|
|
@@ -308,17 +308,24 @@ function checkAiSdk(opencodeDir) {
|
|
|
308
308
|
}
|
|
309
309
|
function runDoctorChecks(configPath, pluginPath) {
|
|
310
310
|
const opencodeDir = dirname(configPath);
|
|
311
|
+
let config;
|
|
312
|
+
try {
|
|
313
|
+
config = readConfig(configPath);
|
|
314
|
+
} catch {
|
|
315
|
+
config = undefined;
|
|
316
|
+
}
|
|
311
317
|
return [
|
|
312
318
|
checkBun(),
|
|
313
319
|
checkCursorAgent(),
|
|
314
320
|
checkCursorAgentLogin(),
|
|
315
321
|
checkOpenCode(),
|
|
316
|
-
checkPluginFile(pluginPath),
|
|
322
|
+
checkPluginFile(pluginPath, config),
|
|
317
323
|
checkProviderConfig(configPath),
|
|
318
324
|
checkAiSdk(opencodeDir)
|
|
319
325
|
];
|
|
320
326
|
}
|
|
321
327
|
var PROVIDER_ID = "cursor-acp";
|
|
328
|
+
var NPM_PACKAGE_PREFIX = "@rama_nigg/open-cursor";
|
|
322
329
|
var DEFAULT_BASE_URL = "http://127.0.0.1:32124/v1";
|
|
323
330
|
function printHelp() {
|
|
324
331
|
const binName = basename(process.argv[1] || "open-cursor");
|
|
@@ -527,13 +534,20 @@ function commandSyncModels(options) {
|
|
|
527
534
|
console.log(`Models synced: ${models.length}`);
|
|
528
535
|
console.log(`Config path: ${configPath}`);
|
|
529
536
|
}
|
|
537
|
+
var NPM_PACKAGE = "@rama_nigg/open-cursor";
|
|
530
538
|
function commandUninstall(options) {
|
|
531
539
|
const { configPath, pluginPath } = resolvePaths(options);
|
|
532
540
|
rmSync(pluginPath, { force: true });
|
|
533
541
|
if (existsSync(configPath)) {
|
|
534
542
|
const config = readConfig(configPath);
|
|
535
543
|
if (Array.isArray(config.plugin)) {
|
|
536
|
-
config.plugin = config.plugin.filter((name) =>
|
|
544
|
+
config.plugin = config.plugin.filter((name) => {
|
|
545
|
+
if (name === PROVIDER_ID)
|
|
546
|
+
return false;
|
|
547
|
+
if (typeof name === "string" && name.startsWith(NPM_PACKAGE))
|
|
548
|
+
return false;
|
|
549
|
+
return true;
|
|
550
|
+
});
|
|
537
551
|
}
|
|
538
552
|
if (config.provider && typeof config.provider === "object") {
|
|
539
553
|
delete config.provider[PROVIDER_ID];
|
|
@@ -565,22 +579,32 @@ function getStatusResult(configPath, pluginPath) {
|
|
|
565
579
|
pluginTarget = undefined;
|
|
566
580
|
}
|
|
567
581
|
}
|
|
582
|
+
let config;
|
|
568
583
|
let providerEnabled = false;
|
|
569
584
|
let baseUrl = "http://127.0.0.1:32124/v1";
|
|
570
585
|
let modelCount = 0;
|
|
571
586
|
if (existsSync(configPath)) {
|
|
572
|
-
|
|
587
|
+
config = readConfig(configPath);
|
|
573
588
|
const provider = config.provider?.["cursor-acp"];
|
|
574
589
|
providerEnabled = !!provider;
|
|
575
590
|
if (provider?.options?.baseURL) {
|
|
576
591
|
baseUrl = provider.options.baseURL;
|
|
577
592
|
}
|
|
578
593
|
modelCount = Object.keys(provider?.models || {}).length;
|
|
594
|
+
} else {
|
|
595
|
+
config = undefined;
|
|
579
596
|
}
|
|
580
597
|
const opencodeDir = dirname(configPath);
|
|
581
598
|
const sdkPath = join(opencodeDir, "node_modules", "@ai-sdk", "openai-compatible");
|
|
582
599
|
const aiSdkInstalled = existsSync(sdkPath);
|
|
600
|
+
let installMethod = "none";
|
|
601
|
+
if (pluginType !== "missing") {
|
|
602
|
+
installMethod = "symlink";
|
|
603
|
+
} else if (isNpmDirectInstalled(config)) {
|
|
604
|
+
installMethod = "npm-direct";
|
|
605
|
+
}
|
|
583
606
|
return {
|
|
607
|
+
installMethod,
|
|
584
608
|
plugin: {
|
|
585
609
|
path: pluginPath,
|
|
586
610
|
type: pluginType,
|
|
@@ -615,6 +639,7 @@ function commandStatus(options) {
|
|
|
615
639
|
} else {
|
|
616
640
|
console.log(` Type: missing`);
|
|
617
641
|
}
|
|
642
|
+
console.log(` Install method: ${result.installMethod}`);
|
|
618
643
|
console.log("");
|
|
619
644
|
console.log("Provider");
|
|
620
645
|
console.log(` Config: ${result.provider.configPath}`);
|