-
Notifications
You must be signed in to change notification settings - Fork 49
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
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 7483c77
feat(cursor-cli): add project MCP and rules support; non-interactive …
matifali a3aa1cf
chore(cursor-cli): remove Bun test; terraform tests only
matifali a075139
refactor(cursor-cli): drop extra_args, binary_name, base_command, add…
matifali 2a65de4
chore: format cursor-cli module and tests
matifali 5e3f555
feat(cursor-cli): configure Coder MCP status slug in module; docs cle…
matifali 6f46bc9
chore(cursor-cli): move env to coder_env; update scripts
matifali ce902f6
wip
matifali df31818
docs(cursor-cli): enhance README with examples for MCP configuration …
matifali d8b9b2a
feat(cursor-cli): add pre-install and post-install script support
matifali 079ff1f
feat(cursor-cli): add ai_prompt variable
matifali 496efad
feat(cursor-cli): add output for app ID in main.tf
matifali 538d08b
feat(cursor-cli): update script execution to include folder variable …
matifali 0a87206
refactor(cursor-cli): comment out unused arguments in start.sh script
matifali 8b6b659
refactor(cursor-cli): restore previously commented arguments in start…
matifali 4edcb00
refactor(cursor-cli): remove output_format variable and related scrip…
matifali 414b5f2
revert(claude-code): restore main.test.ts to origin/main state
matifali f525189
refactor(cursor-cli): remove non-interactive flags from main.test.ts
matifali fcd9f3a
refactor
matifali 058cd8e
fixup!
matifali 8d3e5d6
fixup!
matifali be5c394
wip
matifali 7391082
Update registry/coder-labs/modules/cursor-cli/README.md
matifali ee1bd53
Merge branch 'main' into feat/cursor-cli-from-main
DevelopmentCats 62a0a9c
feat: add support for agentapi
35C4n0r 2107f93
feat: add tests
35C4n0r 1a38b7e
feat: update readme
35C4n0r d9e49f5
feat: update readme
35C4n0r a8328f4
feat: update app slug
35C4n0r 3fdae36
feat: remove app and cli
35C4n0r 5da3721
feat: update readme
35C4n0r 3a4fc36
feat: fix typo
35C4n0r d1f518a
feat: update mcp_json to mcp
35C4n0r 2322298
feat: update tests
35C4n0r 805b385
Merge branch 'main' into feat/cursor-cli-from-main
DevelopmentCats 10a96aa
Update registry/coder-labs/modules/cursor-cli/scripts/start.sh
35C4n0r f480d74
Update registry/coder-labs/modules/cursor-cli/scripts/start.sh
35C4n0r 528b823
Update registry/coder-labs/modules/cursor-cli/testdata/cursor-cli-moc…
35C4n0r c336e44
chore: update mock
35C4n0r b99023b
chore: remove comments
35C4n0r a844fbb
feat: update prompt and README.md
35C4n0r f1bca89
feat: update test
35C4n0r d673f3a
feat: bun fmt
35C4n0r dfc007d
feat: bump agentapi version
35C4n0r 037c223
feat: bump agentapi version
35C4n0r 6748088
Update main.tf
35C4n0r 7db6161
feat: add agent type
35C4n0r bfe56f3
Merge branch 'main' into feat/cursor-cli-from-main
DevelopmentCats 77709d1
fix: documentation
35C4n0r 71a1f3d
fix: update documentation
35C4n0r 522f095
bun fmt
35C4n0r File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
152
registry/coder-labs/modules/cursor-cli/cursor-cli.tftest.hcl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
35C4n0r marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
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 { | ||
35C4n0r marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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" | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.