Skip to content

feat(cursor-cli): add Cursor CLI module #309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 51 commits into from
Aug 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
a8d9b71
feat(cursor-cli): add Cursor Agent CLI module (interactive default, M…
matifali Aug 8, 2025
7483c77
feat(cursor-cli): add project MCP and rules support; non-interactive …
matifali Aug 8, 2025
a3aa1cf
chore(cursor-cli): remove Bun test; terraform tests only
matifali Aug 8, 2025
a075139
refactor(cursor-cli): drop extra_args, binary_name, base_command, add…
matifali Aug 8, 2025
2a65de4
chore: format cursor-cli module and tests
matifali Aug 8, 2025
5e3f555
feat(cursor-cli): configure Coder MCP status slug in module; docs cle…
matifali Aug 8, 2025
6f46bc9
chore(cursor-cli): move env to coder_env; update scripts
matifali Aug 8, 2025
ce902f6
wip
matifali Aug 8, 2025
df31818
docs(cursor-cli): enhance README with examples for MCP configuration …
matifali Aug 8, 2025
d8b9b2a
feat(cursor-cli): add pre-install and post-install script support
matifali Aug 8, 2025
079ff1f
feat(cursor-cli): add ai_prompt variable
matifali Aug 8, 2025
496efad
feat(cursor-cli): add output for app ID in main.tf
matifali Aug 8, 2025
538d08b
feat(cursor-cli): update script execution to include folder variable …
matifali Aug 8, 2025
0a87206
refactor(cursor-cli): comment out unused arguments in start.sh script
matifali Aug 8, 2025
8b6b659
refactor(cursor-cli): restore previously commented arguments in start…
matifali Aug 8, 2025
4edcb00
refactor(cursor-cli): remove output_format variable and related scrip…
matifali Aug 8, 2025
414b5f2
revert(claude-code): restore main.test.ts to origin/main state
matifali Aug 9, 2025
f525189
refactor(cursor-cli): remove non-interactive flags from main.test.ts
matifali Aug 9, 2025
fcd9f3a
refactor
matifali Aug 9, 2025
058cd8e
fixup!
matifali Aug 9, 2025
8d3e5d6
fixup!
matifali Aug 9, 2025
be5c394
wip
matifali Aug 11, 2025
7391082
Update registry/coder-labs/modules/cursor-cli/README.md
matifali Aug 12, 2025
ee1bd53
Merge branch 'main' into feat/cursor-cli-from-main
DevelopmentCats Aug 12, 2025
62a0a9c
feat: add support for agentapi
35C4n0r Aug 13, 2025
2107f93
feat: add tests
35C4n0r Aug 13, 2025
1a38b7e
feat: update readme
35C4n0r Aug 13, 2025
d9e49f5
feat: update readme
35C4n0r Aug 13, 2025
a8328f4
feat: update app slug
35C4n0r Aug 13, 2025
3fdae36
feat: remove app and cli
35C4n0r Aug 14, 2025
5da3721
feat: update readme
35C4n0r Aug 14, 2025
3a4fc36
feat: fix typo
35C4n0r Aug 14, 2025
d1f518a
feat: update mcp_json to mcp
35C4n0r Aug 14, 2025
2322298
feat: update tests
35C4n0r Aug 14, 2025
805b385
Merge branch 'main' into feat/cursor-cli-from-main
DevelopmentCats Aug 14, 2025
10a96aa
Update registry/coder-labs/modules/cursor-cli/scripts/start.sh
35C4n0r Aug 14, 2025
f480d74
Update registry/coder-labs/modules/cursor-cli/scripts/start.sh
35C4n0r Aug 14, 2025
528b823
Update registry/coder-labs/modules/cursor-cli/testdata/cursor-cli-moc…
35C4n0r Aug 14, 2025
c336e44
chore: update mock
35C4n0r Aug 14, 2025
b99023b
chore: remove comments
35C4n0r Aug 14, 2025
a844fbb
feat: update prompt and README.md
35C4n0r Aug 15, 2025
f1bca89
feat: update test
35C4n0r Aug 16, 2025
d673f3a
feat: bun fmt
35C4n0r Aug 16, 2025
dfc007d
feat: bump agentapi version
35C4n0r Aug 18, 2025
037c223
feat: bump agentapi version
35C4n0r Aug 18, 2025
6748088
Update main.tf
35C4n0r Aug 18, 2025
7db6161
feat: add agent type
35C4n0r Aug 18, 2025
bfe56f3
Merge branch 'main' into feat/cursor-cli-from-main
DevelopmentCats Aug 18, 2025
77709d1
fix: documentation
35C4n0r Aug 18, 2025
71a1f3d
fix: update documentation
35C4n0r Aug 18, 2025
522f095
bun fmt
35C4n0r Aug 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions registry/coder-labs/modules/cursor-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
display_name: Cursor CLI
icon: ../../../../.icons/cursor.svg
description: Run Cursor CLI agent in your workspace (no AgentAPI)
verified: true
tags: [agent, cursor, ai, cli]
---

# Cursor CLI

Run the Cursor Coding Agent in your workspace using the Cursor CLI directly.

A full example with MCP, rules, and pre/post install scripts:

```tf

data "coder_parameter" "ai_prompt" {
type = "string"
name = "AI Prompt"
default = ""
description = "Build a Minesweeper in Python."
mutable = true
}

module "coder-login" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/coder-login/coder"
version = "1.0.31"
agent_id = coder_agent.main.id
}

module "cursor_cli" {
source = "registry.coder.com/coder-labs/cursor-cli/coder"
version = "0.1.0"
agent_id = coder_agent.example.id
folder = "/home/coder/project"

# Optional
install_cursor_cli = true
force = true
model = "gpt-5"
ai_prompt = data.coder_parameter.ai_prompt.value

# Minimal MCP server (writes `folder/.cursor/mcp.json`):
mcp = jsonencode({
mcpServers = {
playwright = {
command = "npx"
args = ["-y", "@playwright/mcp@latest", "--headless", "--isolated", "--no-sandbox"]
}
desktop-commander = {
command = "npx"
args = ["-y", "@wonderwhy-er/desktop-commander"]
}
}
})

# Use a pre_install_script to install the CLI
pre_install_script = <<-EOT
#!/usr/bin/env bash
set -euo pipefail
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
EOT

# Use post_install_script to wait for the repo to be ready
post_install_script = <<-EOT
#!/usr/bin/env bash
set -euo pipefail
TARGET="$${FOLDER}/.git/config"
echo "[cursor-cli] waiting for $${TARGET}..."
for i in $(seq 1 600); do
[ -f "$TARGET" ] && { echo "ready"; exit 0; }
sleep 1
done
echo "timeout waiting for $${TARGET}" >&2
EOT

# Provide a map of file name to content; files are written to `folder/.cursor/rules/<name>`.
rules_files = {
"python.mdc" = <<-EOT
---
description: RPC Service boilerplate
globs:
alwaysApply: false
---

- Use our internal RPC pattern when defining services
- Always use snake_case for service names.

@service-template.ts
EOT

"frontend.mdc" = <<-EOT
---
description: RPC Service boilerplate
globs:
alwaysApply: false
---

- Use our internal RPC pattern when defining services
- Always use snake_case for service names.

@service-template.ts
EOT
}
}
```

> [!NOTE]
> A `.cursor` directory will be created in the specified `folder`, containing the MCP configuration, rules.
> To use this module with tasks, please pass the API Key obtained from Cursor to the `api_key` variable. To obtain the api key follow the instructions [here](https://docs.cursor.com/en/cli/reference/authentication#step-1%3A-generate-an-api-key)

## References

- See Cursor CLI docs: `https://docs.cursor.com/en/cli/overview`
- For MCP project config, see `https://docs.cursor.com/en/context/mcp#using-mcp-json`. This module writes your `mcp_json` into `folder/.cursor/mcp.json`.
- For Rules, see `https://docs.cursor.com/en/context/rules#project-rules`. Provide `rules_files` (map of file name to content) to populate `folder/.cursor/rules/`.

## Troubleshooting

- Ensure the CLI is installed (enable `install_cursor_cli = true` or preinstall it in your image)
- Logs are written to `~/.cursor-cli-module/`
152 changes: 152 additions & 0 deletions registry/coder-labs/modules/cursor-cli/cursor-cli.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
run "test_cursor_cli_basic" {
command = plan

variables {
agent_id = "test-agent-123"
folder = "/home/coder/projects"
}

assert {
condition = coder_env.status_slug.name == "CODER_MCP_APP_STATUS_SLUG"
error_message = "Status slug environment variable should be set correctly"
}

assert {
condition = coder_env.status_slug.value == "cursorcli"
error_message = "Status slug value should be 'cursorcli'"
}

assert {
condition = var.folder == "/home/coder/projects"
error_message = "Folder variable should be set correctly"
}

assert {
condition = var.agent_id == "test-agent-123"
error_message = "Agent ID variable should be set correctly"
}
}

run "test_cursor_cli_with_api_key" {
command = plan

variables {
agent_id = "test-agent-456"
folder = "/home/coder/workspace"
api_key = "test-api-key-123"
}

assert {
condition = coder_env.cursor_api_key[0].name == "CURSOR_API_KEY"
error_message = "Cursor API key environment variable should be set correctly"
}

assert {
condition = coder_env.cursor_api_key[0].value == "test-api-key-123"
error_message = "Cursor API key value should match the input"
}
}

run "test_cursor_cli_with_custom_options" {
command = plan

variables {
agent_id = "test-agent-789"
folder = "/home/coder/custom"
order = 5
group = "development"
icon = "/icon/custom.svg"
model = "sonnet-4"
ai_prompt = "Help me write better code"
force = false
install_cursor_cli = false
install_agentapi = false
}

assert {
condition = var.order == 5
error_message = "Order variable should be set to 5"
}

assert {
condition = var.group == "development"
error_message = "Group variable should be set to 'development'"
}

assert {
condition = var.icon == "/icon/custom.svg"
error_message = "Icon variable should be set to custom icon"
}

assert {
condition = var.model == "sonnet-4"
error_message = "Model variable should be set to 'sonnet-4'"
}

assert {
condition = var.ai_prompt == "Help me write better code"
error_message = "AI prompt variable should be set correctly"
}

assert {
condition = var.force == false
error_message = "Force variable should be set to false"
}
}

run "test_cursor_cli_with_mcp_and_rules" {
command = plan

variables {
agent_id = "test-agent-mcp"
folder = "/home/coder/mcp-test"
mcp = jsonencode({
mcpServers = {
test = {
command = "test-server"
args = ["--config", "test.json"]
}
}
})
rules_files = {
"general.md" = "# General coding rules\n- Write clean code\n- Add comments"
"security.md" = "# Security rules\n- Never commit secrets\n- Validate inputs"
}
}

assert {
condition = var.mcp != null
error_message = "MCP configuration should be provided"
}

assert {
condition = var.rules_files != null
error_message = "Rules files should be provided"
}

assert {
condition = length(var.rules_files) == 2
error_message = "Should have 2 rules files"
}
}

run "test_cursor_cli_with_scripts" {
command = plan

variables {
agent_id = "test-agent-scripts"
folder = "/home/coder/scripts"
pre_install_script = "echo 'Pre-install script'"
post_install_script = "echo 'Post-install script'"
}

assert {
condition = var.pre_install_script == "echo 'Pre-install script'"
error_message = "Pre-install script should be set correctly"
}

assert {
condition = var.post_install_script == "echo 'Post-install script'"
error_message = "Post-install script should be set correctly"
}
}
Loading