Skip to content

Commit 798cb1d

Browse files
Add Cursor CLI support to cursor module
- Add AgentAPI integration similar to goose module - Support both interactive and non-interactive modes - Include installation and start scripts for cursor-agent - Update README with comprehensive CLI usage examples - Add tests for new CLI functionality - Maintain backward compatibility with desktop app - Configure interactive mode with text output Co-authored-by: matifali <10648092+matifali@users.noreply.github.com>
1 parent 74c8698 commit 798cb1d

File tree

5 files changed

+366
-60
lines changed

5 files changed

+366
-60
lines changed
Lines changed: 138 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,163 @@
11
---
2-
display_name: Cursor IDE
3-
description: Add a one-click button to launch Cursor IDE
2+
display_name: Cursor
3+
description: Run Cursor IDE and CLI in your workspace
44
icon: ../../../../.icons/cursor.svg
55
verified: true
6-
tags: [ide, cursor, ai]
6+
tags: [ide, cursor, ai, cli, agent]
77
---
88

9-
# Cursor IDE
9+
# Cursor
1010

11-
Add a button to open any workspace with a single click in Cursor IDE.
12-
13-
Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder).
11+
Run [Cursor IDE](https://cursor.com) and [Cursor CLI](https://docs.cursor.com/en/cli/overview) in your workspace. Provides both desktop IDE integration and terminal-based AI coding assistance.
1412

1513
```tf
1614
module "cursor" {
1715
count = data.coder_workspace.me.start_count
1816
source = "registry.coder.com/coder/cursor/coder"
19-
version = "1.2.1"
17+
version = "2.0.0"
2018
agent_id = coder_agent.example.id
19+
folder = "/home/coder"
2120
}
2221
```
2322

23+
## Prerequisites
24+
25+
- You must add the [Coder Login](https://registry.coder.com/modules/coder-login) module to your template
26+
27+
## Features
28+
29+
- **Desktop IDE**: One-click button to launch Cursor IDE (uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder))
30+
- **CLI Agent**: Terminal-based AI coding assistant with interactive and non-interactive modes
31+
- **AgentAPI Integration**: Web interface for CLI interactions
32+
- **Interactive Mode**: Conversational sessions with text output
33+
- **Non-Interactive Mode**: Automation-friendly for scripts and CI pipelines
34+
2435
## Examples
2536

26-
### Open in a specific directory
37+
### Basic setup with CLI enabled
38+
39+
```tf
40+
module "coder-login" {
41+
count = data.coder_workspace.me.start_count
42+
source = "registry.coder.com/coder/coder-login/coder"
43+
version = "1.0.15"
44+
agent_id = coder_agent.example.id
45+
}
46+
47+
module "cursor" {
48+
count = data.coder_workspace.me.start_count
49+
source = "registry.coder.com/coder/cursor/coder"
50+
version = "2.0.0"
51+
agent_id = coder_agent.example.id
52+
folder = "/home/coder/project"
53+
install_cursor_cli = true
54+
install_agentapi = true
55+
}
56+
```
57+
58+
### Desktop IDE only (legacy mode)
59+
60+
```tf
61+
module "cursor" {
62+
count = data.coder_workspace.me.start_count
63+
source = "registry.coder.com/coder/cursor/coder"
64+
version = "2.0.0"
65+
agent_id = coder_agent.example.id
66+
folder = "/home/coder/project"
67+
install_cursor_cli = false
68+
install_agentapi = false
69+
}
70+
```
71+
72+
### With custom pre-install script
2773

2874
```tf
2975
module "cursor" {
3076
count = data.coder_workspace.me.start_count
3177
source = "registry.coder.com/coder/cursor/coder"
32-
version = "1.2.1"
78+
version = "2.0.0"
3379
agent_id = coder_agent.example.id
34-
folder = "/home/coder/project"
80+
81+
pre_install_script = <<-EOT
82+
# Install additional dependencies
83+
npm install -g typescript
84+
EOT
3585
}
3686
```
87+
88+
## Usage
89+
90+
### Desktop IDE
91+
Click the "Cursor Desktop" button in your workspace to launch Cursor IDE.
92+
93+
### CLI Agent
94+
95+
#### Web Interface
96+
1. Click the "Cursor" button to access the web interface
97+
2. Start interactive sessions with text output
98+
99+
#### Terminal Usage
100+
```bash
101+
# Interactive mode (default)
102+
cursor-agent
103+
104+
# Interactive mode with initial prompt
105+
cursor-agent "refactor the auth module to use JWT tokens"
106+
107+
# Non-interactive mode with text output
108+
cursor-agent -p "find and fix performance issues" --output-format text
109+
110+
# Use specific model
111+
cursor-agent -p "add error handling" --model "gpt-5"
112+
113+
# Session management
114+
cursor-agent ls # List all previous chats
115+
cursor-agent resume # Resume latest conversation
116+
cursor-agent --resume="chat-id" # Resume specific conversation
117+
```
118+
119+
#### Interactive Mode Features
120+
- Conversational sessions with the agent
121+
- Review proposed changes before applying
122+
- Real-time guidance and steering
123+
- Text-based output optimized for terminal use
124+
- Session persistence and resumption
125+
126+
#### Non-Interactive Mode Features
127+
- Automation-friendly for scripts and CI pipelines
128+
- Direct prompt execution with text output
129+
- Model selection support
130+
- Git integration for change reviews
131+
132+
## Configuration
133+
134+
The module supports the same configuration options as the Cursor CLI:
135+
- **MCP (Model Context Protocol)**: Automatically detects `mcp.json` configuration
136+
- **Rules System**: Supports `.cursor/rules` directory for custom agent behavior
137+
- **Environment Variables**: Respects Cursor CLI environment settings
138+
139+
## Troubleshooting
140+
141+
The module creates log files in the workspace's `~/.cursor-module` directory. Check these files if you encounter issues:
142+
143+
```bash
144+
# Check installation logs
145+
cat ~/.cursor-module/install.log
146+
147+
# Check runtime logs
148+
cat ~/.cursor-module/runtime.log
149+
150+
# Verify Cursor CLI installation
151+
cursor-agent --help
152+
```
153+
154+
### Common Issues
155+
156+
1. **Cursor CLI not found**: Ensure `install_cursor_cli = true` or install manually:
157+
```bash
158+
curl https://cursor.com/install -fsS | bash
159+
```
160+
161+
2. **Permission issues**: Check that the installation script has proper permissions
162+
163+
3. **Path issues**: The module automatically adds Cursor CLI to PATH, but you may need to restart your shell

registry/coder/modules/cursor/main.test.ts

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,37 @@ describe("cursor", async () => {
1212
agent_id: "foo",
1313
});
1414

15-
it("default output", async () => {
15+
it("default output with CLI enabled", async () => {
1616
const state = await runTerraformApply(import.meta.dir, {
1717
agent_id: "foo",
1818
});
19-
expect(state.outputs.cursor_url.value).toBe(
20-
"cursor://coder.coder-remote/open?owner=default&workspace=default&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
19+
20+
// Check desktop app output
21+
expect(state.outputs.cursor_desktop_url.value).toBe(
22+
"cursor://coder.coder-remote/open?owner=default&workspace=default&folder=/home/coder&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
2123
);
2224

23-
const coder_app = state.resources.find(
24-
(res) => res.type === "coder_app" && res.name === "cursor",
25+
// Check that AgentAPI module is created
26+
const agentapi_module = state.resources.find(
27+
(res) => res.type === "module" && res.name === "agentapi",
2528
);
29+
expect(agentapi_module).not.toBeNull();
2630

31+
// Check desktop app resource
32+
const coder_app = state.resources.find(
33+
(res) => res.type === "coder_app" && res.name === "cursor_desktop",
34+
);
2735
expect(coder_app).not.toBeNull();
2836
expect(coder_app?.instances.length).toBe(1);
2937
expect(coder_app?.instances[0].attributes.order).toBeNull();
3038
});
3139

32-
it("adds folder", async () => {
40+
it("adds custom folder", async () => {
3341
const state = await runTerraformApply(import.meta.dir, {
3442
agent_id: "foo",
3543
folder: "/foo/bar",
3644
});
37-
expect(state.outputs.cursor_url.value).toBe(
45+
expect(state.outputs.cursor_desktop_url.value).toBe(
3846
"cursor://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
3947
);
4048
});
@@ -45,44 +53,53 @@ describe("cursor", async () => {
4553
folder: "/foo/bar",
4654
open_recent: "true",
4755
});
48-
expect(state.outputs.cursor_url.value).toBe(
56+
expect(state.outputs.cursor_desktop_url.value).toBe(
4957
"cursor://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
5058
);
5159
});
5260

53-
it("adds folder but not open_recent", async () => {
61+
it("adds open_recent with default folder", async () => {
5462
const state = await runTerraformApply(import.meta.dir, {
5563
agent_id: "foo",
56-
folder: "/foo/bar",
57-
openRecent: "false",
64+
open_recent: "true",
5865
});
59-
expect(state.outputs.cursor_url.value).toBe(
60-
"cursor://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
66+
expect(state.outputs.cursor_desktop_url.value).toBe(
67+
"cursor://coder.coder-remote/open?owner=default&workspace=default&folder=/home/coder&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
6168
);
6269
});
6370

64-
it("adds open_recent", async () => {
71+
it("expect order to be set", async () => {
6572
const state = await runTerraformApply(import.meta.dir, {
6673
agent_id: "foo",
67-
open_recent: "true",
74+
order: "22",
6875
});
69-
expect(state.outputs.cursor_url.value).toBe(
70-
"cursor://coder.coder-remote/open?owner=default&workspace=default&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
76+
77+
const coder_app = state.resources.find(
78+
(res) => res.type === "coder_app" && res.name === "cursor_desktop",
7179
);
80+
81+
expect(coder_app).not.toBeNull();
82+
expect(coder_app?.instances.length).toBe(1);
83+
expect(coder_app?.instances[0].attributes.order).toBe(23); // order + 1 for desktop app
7284
});
7385

74-
it("expect order to be set", async () => {
86+
it("disables CLI installation", async () => {
7587
const state = await runTerraformApply(import.meta.dir, {
7688
agent_id: "foo",
77-
order: "22",
89+
install_cursor_cli: "false",
90+
install_agentapi: "false",
7891
});
7992

93+
// Should still have desktop app
8094
const coder_app = state.resources.find(
81-
(res) => res.type === "coder_app" && res.name === "cursor",
95+
(res) => res.type === "coder_app" && res.name === "cursor_desktop",
8296
);
83-
8497
expect(coder_app).not.toBeNull();
85-
expect(coder_app?.instances.length).toBe(1);
86-
expect(coder_app?.instances[0].attributes.order).toBe(22);
98+
99+
// AgentAPI module should still exist but with install_agentapi = false
100+
const agentapi_module = state.resources.find(
101+
(res) => res.type === "module" && res.name === "agentapi",
102+
);
103+
expect(agentapi_module).not.toBeNull();
87104
});
88105
});

0 commit comments

Comments
 (0)