Skip to content

Commit 6677432

Browse files
Add new cursor-cli module
- Create separate cursor-cli module instead of modifying existing cursor module - Add AgentAPI integration for web interface and CLI support - Support both interactive and non-interactive modes - Include installation and start scripts for cursor-agent - Comprehensive documentation with CLI usage examples - Add tests for CLI functionality - Configure interactive mode with text output Co-authored-by: matifali <[email protected]>
1 parent 142167f commit 6677432

File tree

5 files changed

+456
-0
lines changed

5 files changed

+456
-0
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
---
2+
display_name: Cursor CLI
3+
description: Run Cursor CLI agent in your workspace
4+
icon: ../../../../.icons/cursor.svg
5+
verified: true
6+
tags: [cli, cursor, ai, agent]
7+
---
8+
9+
# Cursor CLI
10+
11+
Run the [Cursor CLI](https://docs.cursor.com/en/cli/overview) agent in your workspace for terminal-based AI coding assistance.
12+
13+
```tf
14+
module "cursor-cli" {
15+
count = data.coder_workspace.me.start_count
16+
source = "registry.coder.com/coder/cursor-cli/coder"
17+
version = "1.0.0"
18+
agent_id = coder_agent.example.id
19+
folder = "/home/coder"
20+
}
21+
```
22+
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+
- **CLI Agent**: Terminal-based AI coding assistant with interactive and non-interactive modes
30+
- **AgentAPI Integration**: Web interface for CLI interactions
31+
- **Interactive Mode**: Conversational sessions with text output
32+
- **Non-Interactive Mode**: Automation-friendly for scripts and CI pipelines
33+
- **Session Management**: List, resume, and manage coding sessions
34+
- **Model Selection**: Support for multiple AI models (GPT-5, Claude, etc.)
35+
- **MCP Support**: Model Context Protocol for extended functionality
36+
- **Rules System**: Custom agent behavior configuration
37+
38+
## Examples
39+
40+
### Basic setup
41+
42+
```tf
43+
module "coder-login" {
44+
count = data.coder_workspace.me.start_count
45+
source = "registry.coder.com/coder/coder-login/coder"
46+
version = "1.0.15"
47+
agent_id = coder_agent.example.id
48+
}
49+
50+
module "cursor-cli" {
51+
count = data.coder_workspace.me.start_count
52+
source = "registry.coder.com/coder/cursor-cli/coder"
53+
version = "1.0.0"
54+
agent_id = coder_agent.example.id
55+
folder = "/home/coder/project"
56+
install_cursor_cli = true
57+
install_agentapi = true
58+
}
59+
```
60+
61+
### CLI only (no web interface)
62+
63+
```tf
64+
module "cursor-cli" {
65+
count = data.coder_workspace.me.start_count
66+
source = "registry.coder.com/coder/cursor-cli/coder"
67+
version = "1.0.0"
68+
agent_id = coder_agent.example.id
69+
folder = "/home/coder/project"
70+
install_cursor_cli = true
71+
install_agentapi = false
72+
}
73+
```
74+
75+
### With custom pre-install script
76+
77+
```tf
78+
module "cursor-cli" {
79+
count = data.coder_workspace.me.start_count
80+
source = "registry.coder.com/coder/cursor-cli/coder"
81+
version = "1.0.0"
82+
agent_id = coder_agent.example.id
83+
84+
pre_install_script = <<-EOT
85+
# Install additional dependencies
86+
npm install -g typescript
87+
EOT
88+
}
89+
```
90+
91+
## Usage
92+
93+
### Web Interface
94+
95+
1. Click the "Cursor CLI" button to access the web interface
96+
2. Start interactive sessions with text output
97+
98+
### Terminal Usage
99+
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+
121+
- Conversational sessions with the agent
122+
- Review proposed changes before applying
123+
- Real-time guidance and steering
124+
- Text-based output optimized for terminal use
125+
- Session persistence and resumption
126+
127+
### Non-Interactive Mode Features
128+
129+
- Automation-friendly for scripts and CI pipelines
130+
- Direct prompt execution with text output
131+
- Model selection support
132+
- Git integration for change reviews
133+
134+
## Configuration
135+
136+
The module supports the same configuration options as the Cursor CLI:
137+
138+
- **MCP (Model Context Protocol)**: Automatically detects `mcp.json` configuration
139+
- **Rules System**: Supports `.cursor/rules` directory for custom agent behavior
140+
- **Environment Variables**: Respects Cursor CLI environment settings
141+
142+
## Troubleshooting
143+
144+
The module creates log files in the workspace's `~/.cursor-cli-module` directory. Check these files if you encounter issues:
145+
146+
```bash
147+
# Check installation logs
148+
cat ~/.cursor-cli-module/install.log
149+
150+
# Check runtime logs
151+
cat ~/.cursor-cli-module/runtime.log
152+
153+
# Verify Cursor CLI installation
154+
cursor-agent --help
155+
```
156+
157+
### Common Issues
158+
159+
1. **Cursor CLI not found**: Ensure `install_cursor_cli = true` or install manually:
160+
161+
```bash
162+
curl https://cursor.com/install -fsS | bash
163+
```
164+
165+
2. **Permission issues**: Check that the installation script has proper permissions
166+
167+
3. **Path issues**: The module automatically adds Cursor CLI to PATH, but you may need to restart your shell
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { describe, expect, it } from "bun:test";
2+
import {
3+
runTerraformApply,
4+
runTerraformInit,
5+
testRequiredVariables,
6+
} from "~test";
7+
8+
describe("cursor-cli", async () => {
9+
await runTerraformInit(import.meta.dir);
10+
11+
testRequiredVariables(import.meta.dir, {
12+
agent_id: "foo",
13+
});
14+
15+
it("default output with CLI enabled", async () => {
16+
const state = await runTerraformApply(import.meta.dir, {
17+
agent_id: "foo",
18+
});
19+
20+
// Check that AgentAPI module is created
21+
const agentapi_module = state.resources.find(
22+
(res) => res.type === "module" && res.name === "agentapi",
23+
);
24+
expect(agentapi_module).not.toBeNull();
25+
});
26+
27+
it("adds custom folder", async () => {
28+
const state = await runTerraformApply(import.meta.dir, {
29+
agent_id: "foo",
30+
folder: "/foo/bar",
31+
});
32+
33+
// Check that AgentAPI module is created with custom folder
34+
const agentapi_module = state.resources.find(
35+
(res) => res.type === "module" && res.name === "agentapi",
36+
);
37+
expect(agentapi_module).not.toBeNull();
38+
});
39+
40+
it("expect order to be set", async () => {
41+
const state = await runTerraformApply(import.meta.dir, {
42+
agent_id: "foo",
43+
order: "22",
44+
});
45+
46+
// Check that AgentAPI module is created
47+
const agentapi_module = state.resources.find(
48+
(res) => res.type === "module" && res.name === "agentapi",
49+
);
50+
expect(agentapi_module).not.toBeNull();
51+
});
52+
53+
it("disables CLI installation", async () => {
54+
const state = await runTerraformApply(import.meta.dir, {
55+
agent_id: "foo",
56+
install_cursor_cli: "false",
57+
install_agentapi: "false",
58+
});
59+
60+
// AgentAPI module should still exist but with install_agentapi = false
61+
const agentapi_module = state.resources.find(
62+
(res) => res.type === "module" && res.name === "agentapi",
63+
);
64+
expect(agentapi_module).not.toBeNull();
65+
});
66+
67+
it("enables only CLI without web interface", async () => {
68+
const state = await runTerraformApply(import.meta.dir, {
69+
agent_id: "foo",
70+
install_cursor_cli: "true",
71+
install_agentapi: "false",
72+
});
73+
74+
// AgentAPI module should exist but with install_agentapi = false
75+
const agentapi_module = state.resources.find(
76+
(res) => res.type === "module" && res.name === "agentapi",
77+
);
78+
expect(agentapi_module).not.toBeNull();
79+
});
80+
});
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
terraform {
2+
required_version = ">= 1.0"
3+
4+
required_providers {
5+
coder = {
6+
source = "coder/coder"
7+
version = ">= 2.7"
8+
}
9+
}
10+
}
11+
12+
variable "agent_id" {
13+
type = string
14+
description = "The ID of a Coder agent."
15+
}
16+
17+
data "coder_workspace" "me" {}
18+
19+
data "coder_workspace_owner" "me" {}
20+
21+
variable "order" {
22+
type = number
23+
description = "The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order)."
24+
default = null
25+
}
26+
27+
variable "group" {
28+
type = string
29+
description = "The name of a group that this app belongs to."
30+
default = null
31+
}
32+
33+
variable "icon" {
34+
type = string
35+
description = "The icon to use for the app."
36+
default = "/icon/cursor.svg"
37+
}
38+
39+
variable "folder" {
40+
type = string
41+
description = "The folder to run Cursor CLI in."
42+
default = "/home/coder"
43+
}
44+
45+
variable "install_cursor_cli" {
46+
type = bool
47+
description = "Whether to install Cursor CLI."
48+
default = true
49+
}
50+
51+
variable "install_agentapi" {
52+
type = bool
53+
description = "Whether to install AgentAPI."
54+
default = true
55+
}
56+
57+
variable "agentapi_version" {
58+
type = string
59+
description = "The version of AgentAPI to install."
60+
default = "v0.3.3"
61+
}
62+
63+
variable "subdomain" {
64+
type = bool
65+
description = "Whether to use a subdomain for AgentAPI."
66+
default = true
67+
}
68+
69+
variable "pre_install_script" {
70+
type = string
71+
description = "Custom script to run before installing Cursor CLI."
72+
default = null
73+
}
74+
75+
variable "post_install_script" {
76+
type = string
77+
description = "Custom script to run after installing Cursor CLI."
78+
default = null
79+
}
80+
81+
locals {
82+
app_slug = "cursor-cli"
83+
install_script = file("${path.module}/scripts/install.sh")
84+
start_script = file("${path.module}/scripts/start.sh")
85+
module_dir_name = ".cursor-cli-module"
86+
}
87+
88+
module "agentapi" {
89+
source = "registry.coder.com/coder/agentapi/coder"
90+
version = "1.1.0"
91+
92+
agent_id = var.agent_id
93+
web_app_slug = local.app_slug
94+
web_app_order = var.order
95+
web_app_group = var.group
96+
web_app_icon = var.icon
97+
web_app_display_name = "Cursor CLI"
98+
cli_app_slug = "${local.app_slug}-terminal"
99+
cli_app_display_name = "Cursor CLI Terminal"
100+
module_dir_name = local.module_dir_name
101+
install_agentapi = var.install_agentapi
102+
agentapi_version = var.agentapi_version
103+
agentapi_subdomain = var.subdomain
104+
pre_install_script = var.pre_install_script
105+
post_install_script = var.post_install_script
106+
start_script = local.start_script
107+
install_script = <<-EOT
108+
#!/bin/bash
109+
set -o errexit
110+
set -o pipefail
111+
112+
echo -n '${base64encode(local.install_script)}' | base64 -d > /tmp/install.sh
113+
chmod +x /tmp/install.sh
114+
115+
ARG_FOLDER='${var.folder}' \
116+
ARG_INSTALL='${var.install_cursor_cli}' \
117+
/tmp/install.sh
118+
EOT
119+
}

0 commit comments

Comments
 (0)