Compare commits

...

17 Commits

Author SHA1 Message Date
blink-so[bot] 443db3b7dc Add MCP and force mode support to cursor-cli module
- Add MCP (Model Context Protocol) configuration options
- Add force mode for non-interactive automation
- Add default model selection
- Add rules system configuration
- Update install script to configure MCP and rules
- Update start script with environment variables
- Add comprehensive Coder Tasks integration examples
- Add configuration variables table
- Add screenshot section placeholder
- Update terminal usage examples with force mode

Features added:
- enable_mcp: Enable/disable MCP support
- mcp_config_path: Custom MCP configuration file path
- enable_force_mode: Enable force mode for automation
- default_model: Set default AI model
- enable_rules: Enable rules system

Co-authored-by: matifali <10648092+matifali@users.noreply.github.com>
2025-08-08 11:56:14 +00:00
blink-so[bot] 057d40554b Fix formatting for scripts/terraform_test_all.sh
This file was added to main branch and has formatting issues
that cause CI to fail on merge commits.

Co-authored-by: matifali <10648092+matifali@users.noreply.github.com>
2025-08-08 11:49:02 +00:00
blink-so[bot] 0d73bb6588 Remove scripts directory from cursor module
Co-authored-by: matifali <10648092+matifali@users.noreply.github.com>
2025-08-08 11:47:18 +00:00
blink-so[bot] 2932fb482b Completely restore cursor module to original state
- Undo all changes to existing cursor module
- Keep only the new cursor-cli module
- Ensure backward compatibility

Co-authored-by: matifali <10648092+matifali@users.noreply.github.com>
2025-08-08 11:46:56 +00:00
blink-so[bot] 6ce61c9acd Restore original cursor module README
Co-authored-by: matifali <10648092+matifali@users.noreply.github.com>
2025-08-08 11:43:59 +00:00
blink-so[bot] 6677432df7 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 <10648092+matifali@users.noreply.github.com>
2025-08-08 11:42:37 +00:00
blink-so[bot] 142167f9c0 Fix formatting issues in cursor README
Co-authored-by: matifali <10648092+matifali@users.noreply.github.com>
2025-08-08 11:38:39 +00:00
blink-so[bot] 798cb1d79c 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>
2025-08-08 11:37:08 +00:00
Cian Johnston 74c8698566 feat: goose: add support for subdomain=false (#299)
Updates https://github.com/coder/coder/issues/18779
Builds on https://github.com/coder/registry/pull/297

## Description

Adds support for specifying `subdomain = false` in the agentapi module.
Change added in https://github.com/coder/registry/pull/297
NOTE: `AGENTAPI_CHAT_BASE_PATH` is exported before running `main.sh` in
agentapi, so this environment variable is available to calling modules
if `var.subdomain = false`.

## Type of Change

- [ ] New module
- [ ] Bug fix
- [X] Feature/enhancement
- [ ] Documentation
- [ ] Other

## Testing & Validation

- [X] Tests pass (`bun test`)
- [X] Code formatted (`bun run fmt`)
- [X] Changes tested locally

## Related Issues

https://github.com/coder/coder/issues/18779
2025-08-07 22:12:32 -05:00
DevCats 03333991a4 feat: introduce automated tag and release process in maintainer guide (#280) 2025-08-07 16:06:13 +05:00
Susana Ferreira 2b0dba4ed1 chore: add description to JetBrains IDEs parameter (#303)
## Description

<!-- Briefly describe what this PR does and why -->

This PR adds a description field to the `jetbrains_ides`
`coder_parameter`.

This allows the JetBrains IDEs parameter to display a helpful
description in both the Coder UI and the CLI, improving clarity for
users when selecting which IDEs to configure in a workspace.

<img width="1102" height="252" alt="Screenshot 2025-08-07 at 11 04 13"
src="https://github.com/user-attachments/assets/90c78088-700a-4152-8a16-4b8c88c52e2c"
/>

## Type of Change

- [ ] New module
- [ ] Bug fix
- [x] Feature/enhancement
- [ ] Documentation
- [ ] Other

## Testing & Validation

- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun run fmt`)
- [x] Changes tested locally

## Related Issues

https://github.com/coder/coder/issues/19145
2025-08-07 11:42:48 +01:00
Cian Johnston 57c900b2c9 feat(agentapi): Add support for running under a subdomain (#297)
Updates https://github.com/coder/coder/issues/18779

A separate PR will update dependant modules `goose` and `aider`.

## Description

* Adds `subdomain` argument to `agentapi` module
* Updates `agentapi` module to set `AGENTAPI_CHAT_BASE_PATH` to an
autogenerated path if `var.subdomain = false`
* Updates default `agentapi` version to `v0.3.3` to support running
without subdomain

## Type of Change

- [ ] New module
- [ ] Bug fix
- [x] Feature/enhancement
- [ ] Documentation
- [ ] Other


## Testing & Validation

- [X] Tests pass (`bun test`)
- [X] Code formatted (`bun run fmt`)
- [x] Changes tested locally

## Related Issues

- https://github.com/coder/coder/issues/18779
2025-08-06 12:38:49 +01:00
Ben Potter 0ccee61192 chore: remove unnecessary parameter (#282)
Co-authored-by: DevCats <christofer@coder.com>
2025-08-06 07:05:18 +05:00
dependabot[bot] 494dc4b8a1 chore(deps): bump google-github-actions/auth from 2.1.11 to 2.1.12 (#288)
Bumps
[google-github-actions/auth](https://github.com/google-github-actions/auth)
from 2.1.11 to 2.1.12.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/google-github-actions/auth/releases">google-github-actions/auth's
releases</a>.</em></p>
<blockquote>
<h2>v2.1.12</h2>
<h2>What's Changed</h2>
<ul>
<li>Add retries for getIDToken by <a
href="https://github.com/sethvargo"><code>@​sethvargo</code></a> in <a
href="https://redirect.github.com/google-github-actions/auth/pull/502">google-github-actions/auth#502</a></li>
<li>Release: v2.1.12 by <a
href="https://github.com/google-github-actions-bot"><code>@​google-github-actions-bot</code></a>
in <a
href="https://redirect.github.com/google-github-actions/auth/pull/503">google-github-actions/auth#503</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/google-github-actions/auth/compare/v2.1.11...v2.1.12">https://github.com/google-github-actions/auth/compare/v2.1.11...v2.1.12</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/google-github-actions/auth/commit/b7593ed2efd1c1617e1b0254da33b86225adb2a5"><code>b7593ed</code></a>
Release: v2.1.12 (<a
href="https://redirect.github.com/google-github-actions/auth/issues/503">#503</a>)</li>
<li><a
href="https://github.com/google-github-actions/auth/commit/c1ee334b4fb145a02e9d8343bb2e9f0dd06e586b"><code>c1ee334</code></a>
Add retries for getIDToken (<a
href="https://redirect.github.com/google-github-actions/auth/issues/502">#502</a>)</li>
<li>See full diff in <a
href="https://github.com/google-github-actions/auth/compare/140bb5113ffb6b65a7e9b937a81fa96cf5064462...b7593ed2efd1c1617e1b0254da33b86225adb2a5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google-github-actions/auth&package-manager=github_actions&previous-version=2.1.11&new-version=2.1.12)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-05 21:01:49 -05:00
Hugo Dutka 3b135ad4a4 fix(claude-code): revert workaround (#298)
The workaround introduced in https://github.com/coder/registry/pull/283
sometimes causes Coder to associate the Coder agent with the
`terraform_data` resource instead of a compute resource. Additionally,
it creates a new agent once a workspace is stopped.

See https://codercom.slack.com/archives/C08PHACTZRB/p1754391012982629
for more details.

<img width="2480" height="1312" alt="image (6)"
src="https://github.com/user-attachments/assets/6ccf2b40-92e7-4c67-b61f-b26888753e72"
/>

Related to https://github.com/coder/coder/issues/18776.
2025-08-05 13:28:58 +02:00
Danielle Maywood 258591833f fix(devcontainers-cli): allow yarn to install when packageManager not yarn (#287)
On our dogfood workspaces, we fail to install `@devcontainers/cli` with
`yarn` because our agent directory `/home/coder/coder` contains a
`package.json` with `packageManager` being set to `pnpm`. This change
instead ensures to run `yarn global add` inside the
`$CODER_SCRIPT_DATA_DIR` so that we don't read a `package.json` and
cause things to break.
2025-08-04 13:00:13 +01:00
Michael Orlov 3efc22c589 fix/amazon-q mcp integration (#248)
Co-authored-by: Michael Orlov <michaelo@amdocs.com>
Co-authored-by: DevCats <christofer@coder.com>
2025-08-03 06:27:46 +00:00
28 changed files with 944 additions and 59 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Authenticate with Google Cloud
uses: google-github-actions/auth@140bb5113ffb6b65a7e9b937a81fa96cf5064462
uses: google-github-actions/auth@b7593ed2efd1c1617e1b0254da33b86225adb2a5
with:
workload_identity_provider: projects/309789351055/locations/global/workloadIdentityPools/github-actions/providers/github
service_account: registry-v2-github@coder-registry-1.iam.gserviceaccount.com
+50 -4
View File
@@ -42,12 +42,58 @@ go build ./cmd/readmevalidation && ./readmevalidation
## Making a Release
### Create Release Tags
### Automated Tag and Release Process
After merging a PR:
After merging a PR, use the automated script to create and push release tags:
1. Get the new version from the PR (shown as `old → new`)
2. Checkout the merge commit and create the tag:
**Prerequisites:**
- Ensure all module versions are updated in their respective README files (the script uses this as the source of truth)
- Make sure you have the necessary permissions to push tags to the repository
**Steps:**
1. **Checkout the merge commit:**
```bash
git checkout MERGE_COMMIT_ID
```
2. **Run the tag release script:**
```bash
./scripts/tag_release.sh
```
3. **Review and confirm:**
- The script will automatically scan all modules in the registry
- It will detect which modules need version bumps by comparing README versions to existing tags
- A summary will be displayed showing which modules need tagging
- Confirm the list is correct when prompted
4. **Automatic tagging:**
- After confirmation, the script will automatically create all necessary release tags
- Tags will be pushed to the remote repository
- The script operates on the current checked-out commit
**Example output:**
```text
🔍 Scanning all modules for missing release tags...
📦 coder/code-server: v4.1.2 (needs tag)
✅ coder/dotfiles: v1.0.5 (already tagged)
## Tags to be created:
- `release/coder/code-server/v4.1.2`
❓ Do you want to proceed with creating and pushing these release tags?
Continue? [y/N]: y
```
### Manual Process (Fallback)
If the automated script fails, you can manually tag and release modules:
```bash
# Checkout the merge commit
@@ -118,7 +118,6 @@ data "coder_workspace_preset" "default" {
EOT
"preview_port" = "4200"
"container_image" = "codercom/example-universal:ubuntu"
"jetbrains_ide" = "PY"
}
# Pre-builds is a Coder Premium
+1 -1
View File
@@ -16,7 +16,7 @@ The AgentAPI module is a building block for modules that need to run an AgentAPI
```tf
module "agentapi" {
source = "registry.coder.com/coder/agentapi/coder"
version = "1.0.2"
version = "1.1.0"
agent_id = var.agent_id
web_app_slug = local.app_slug
@@ -148,4 +148,92 @@ describe("agentapi", async () => {
]);
expect(respAgentAPI.exitCode).toBe(0);
});
test("no-subdomain-base-path", async () => {
const { id } = await setup({
moduleVariables: {
agentapi_subdomain: "false",
},
});
const respModuleScript = await execModuleScript(id);
expect(respModuleScript.exitCode).toBe(0);
await expectAgentAPIStarted(id);
const agentApiStartLog = await readFileContainer(
id,
"/home/coder/test-agentapi-start.log",
);
expect(agentApiStartLog).toContain("Using AGENTAPI_CHAT_BASE_PATH: /@default/default.foo/apps/agentapi-web/chat");
});
test("validate-agentapi-version", async () => {
const cases = [
{
moduleVariables: {
agentapi_version: "v0.3.2",
},
shouldThrow: "",
},
{
moduleVariables: {
agentapi_version: "v0.3.3",
},
shouldThrow: "",
},
{
moduleVariables: {
agentapi_version: "v0.0.1",
agentapi_subdomain: "false",
},
shouldThrow: "Running with subdomain = false is only supported by agentapi >= v0.3.3.",
},
{
moduleVariables: {
agentapi_version: "v0.3.2",
agentapi_subdomain: "false",
},
shouldThrow: "Running with subdomain = false is only supported by agentapi >= v0.3.3.",
},
{
moduleVariables: {
agentapi_version: "v0.3.3",
agentapi_subdomain: "false",
},
shouldThrow: "",
},
{
moduleVariables: {
agentapi_version: "v0.3.999",
agentapi_subdomain: "false",
},
shouldThrow: "",
},
{
moduleVariables: {
agentapi_version: "v0.999.999",
agentapi_subdomain: "false",
},
},
{
moduleVariables: {
agentapi_version: "v999.999.999",
agentapi_subdomain: "false",
},
},
{
moduleVariables: {
agentapi_version: "arbitrary-string-bypasses-validation",
},
shouldThrow: "",
}
];
for (const { moduleVariables, shouldThrow } of cases) {
if (shouldThrow) {
expect(setup({ moduleVariables: moduleVariables as Record<string, string> })).rejects.toThrow(shouldThrow);
} else {
expect(setup({ moduleVariables: moduleVariables as Record<string, string> })).resolves.toBeDefined();
}
}
});
});
+36 -3
View File
@@ -117,7 +117,7 @@ variable "install_agentapi" {
variable "agentapi_version" {
type = string
description = "The version of AgentAPI to install."
default = "v0.2.3"
default = "v0.3.3"
}
variable "agentapi_port" {
@@ -126,6 +126,31 @@ variable "agentapi_port" {
default = 3284
}
locals {
# agentapi_subdomain_false_min_version_expr matches a semantic version >= v0.3.3.
# Initial support was added in v0.3.1 but configuration via environment variable
# was added in v0.3.3.
# This is unfortunately a regex because there is no builtin way to compare semantic versions in Terraform.
# See: https://regex101.com/r/oHPyRa/1
agentapi_subdomain_false_min_version_expr = "^v(0\\.(3\\.[3-9]|3.[1-9]\\d+|[4-9]\\.\\d+|[1-9]\\d+\\.\\d+)|[1-9]\\d*\\.\\d+\\.\\d+)$"
}
variable "agentapi_subdomain" {
type = bool
description = "Whether to use a subdomain for AgentAPI."
default = true
validation {
condition = var.agentapi_subdomain || (
# If version doesn't look like a valid semantic version, just allow it.
# Note that boolean operators do not short-circuit in Terraform.
can(regex("^v\\d+\\.\\d+\\.\\d+$", var.agentapi_version)) ?
can(regex(local.agentapi_subdomain_false_min_version_expr, var.agentapi_version)) :
true
)
error_message = "Running with subdomain = false is only supported by agentapi >= v0.3.3."
}
}
variable "module_dir_name" {
type = string
description = "Name of the subdirectory in the home directory for module files."
@@ -140,7 +165,14 @@ locals {
encoded_post_install_script = var.post_install_script != null ? base64encode(var.post_install_script) : ""
agentapi_start_script_b64 = base64encode(var.start_script)
agentapi_wait_for_start_script_b64 = base64encode(file("${path.module}/scripts/agentapi-wait-for-start.sh"))
main_script = file("${path.module}/scripts/main.sh")
// Chat base path is only set if not using a subdomain.
// NOTE:
// - Initial support for --chat-base-path was added in v0.3.1 but configuration
// via environment variable AGENTAPI_CHAT_BASE_PATH was added in v0.3.3.
// - As CODER_WORKSPACE_AGENT_NAME is a recent addition we use agent ID
// for backward compatibility.
agentapi_chat_base_path = var.agentapi_subdomain ? "" : "/@${data.coder_workspace_owner.me.name}/${data.coder_workspace.me.name}.${var.agent_id}/apps/${var.web_app_slug}/chat"
main_script = file("${path.module}/scripts/main.sh")
}
resource "coder_script" "agentapi" {
@@ -165,6 +197,7 @@ resource "coder_script" "agentapi" {
ARG_WAIT_FOR_START_SCRIPT="$(echo -n '${local.agentapi_wait_for_start_script_b64}' | base64 -d)" \
ARG_POST_INSTALL_SCRIPT="$(echo -n '${local.encoded_post_install_script}' | base64 -d)" \
ARG_AGENTAPI_PORT='${var.agentapi_port}' \
ARG_AGENTAPI_CHAT_BASE_PATH='${local.agentapi_chat_base_path}' \
/tmp/main.sh
EOT
run_on_start = true
@@ -178,7 +211,7 @@ resource "coder_app" "agentapi_web" {
icon = var.web_app_icon
order = var.web_app_order
group = var.web_app_group
subdomain = true
subdomain = var.agentapi_subdomain
healthcheck {
url = "http://localhost:${var.agentapi_port}/status"
interval = 3
@@ -13,6 +13,7 @@ START_SCRIPT="$ARG_START_SCRIPT"
WAIT_FOR_START_SCRIPT="$ARG_WAIT_FOR_START_SCRIPT"
POST_INSTALL_SCRIPT="$ARG_POST_INSTALL_SCRIPT"
AGENTAPI_PORT="$ARG_AGENTAPI_PORT"
AGENTAPI_CHAT_BASE_PATH="${ARG_AGENTAPI_CHAT_BASE_PATH:-}"
set +o nounset
command_exists() {
@@ -92,5 +93,7 @@ export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
cd "${WORKDIR}"
export AGENTAPI_CHAT_BASE_PATH="${AGENTAPI_CHAT_BASE_PATH:-}"
nohup "$module_path/scripts/agentapi-start.sh" true "${AGENTAPI_PORT}" &>"$module_path/agentapi-start.log" &
"$module_path/scripts/agentapi-wait-for-start.sh" "${AGENTAPI_PORT}"
+10 -1
View File
@@ -24,7 +24,16 @@ export const setupContainer = async ({
});
const coderScript = findResourceInstance(state, "coder_script");
const id = await runContainer(image ?? "codercom/enterprise-node:latest");
return { id, coderScript, cleanup: () => removeContainer(id) };
return {
id, coderScript, cleanup: async () => {
if (process.env["DEBUG"] === "true" || process.env["DEBUG"] === "1" || process.env["DEBUG"] === "yes") {
console.log(`Not removing container ${id} in debug mode`);
console.log(`Run "docker rm -f ${id}" to remove it manually.`);
} else {
await removeContainer(id);
}
}
};
};
export const loadTestFile = async (
@@ -11,6 +11,12 @@ log_file_path="$module_path/agentapi.log"
echo "using prompt: $use_prompt" >>/home/coder/test-agentapi-start.log
echo "using port: $port" >>/home/coder/test-agentapi-start.log
AGENTAPI_CHAT_BASE_PATH="${AGENTAPI_CHAT_BASE_PATH:-}"
if [ -n "$AGENTAPI_CHAT_BASE_PATH" ]; then
echo "Using AGENTAPI_CHAT_BASE_PATH: $AGENTAPI_CHAT_BASE_PATH" >>/home/coder/test-agentapi-start.log
export AGENTAPI_CHAT_BASE_PATH
fi
agentapi server --port "$port" --term-width 67 --term-height 1190 -- \
bash -c aiagent \
>"$log_file_path" 2>&1
+7 -25
View File
@@ -125,24 +125,7 @@ variable "ai_prompt" {
locals {
encoded_pre_install_script = var.experiment_pre_install_script != null ? base64encode(var.experiment_pre_install_script) : ""
encoded_post_install_script = var.experiment_post_install_script != null ? base64encode(var.experiment_post_install_script) : ""
# We need to use allowed tools to limit the context Amazon Q receives.
# Amazon Q can't handle big contexts, and the `create_template_version` tool
# has a description that's too long.
mcp_json = <<EOT
{
"mcpServers": {
"coder": {
"command": "coder",
"args": ["exp", "mcp", "server", "--allowed-tools", "coder_report_task"],
"env": {
"CODER_MCP_APP_STATUS_SLUG": "amazon-q"
}
}
}
}
EOT
encoded_mcp_json = base64encode(local.mcp_json)
full_prompt = <<-EOT
full_prompt = <<-EOT
${var.system_prompt}
Your first task is:
@@ -211,6 +194,12 @@ resource "coder_script" "amazon_q" {
cd "$PREV_DIR"
echo "Extracted auth tarball"
if [ "${var.experiment_report_tasks}" = "true" ]; then
echo "Configuring Amazon Q to report tasks via Coder MCP..."
q mcp add --name coder --command "coder" --args "exp,mcp,server,--allowed-tools,coder_report_task" --env "CODER_MCP_APP_STATUS_SLUG=amazon-q" --scope global --force
echo "Added Coder MCP server to Amazon Q configuration"
fi
if [ -n "${local.encoded_post_install_script}" ]; then
echo "Running post-install script..."
echo "${local.encoded_post_install_script}" | base64 -d > /tmp/post_install.sh
@@ -218,13 +207,6 @@ resource "coder_script" "amazon_q" {
/tmp/post_install.sh
fi
if [ "${var.experiment_report_tasks}" = "true" ]; then
echo "Configuring Amazon Q to report tasks via Coder MCP..."
mkdir -p ~/.aws/amazonq
echo "${local.encoded_mcp_json}" | base64 -d > ~/.aws/amazonq/mcp.json
echo "Created the ~/.aws/amazonq/mcp.json configuration file"
fi
if [ "${var.experiment_use_tmux}" = "true" ] && [ "${var.experiment_use_screen}" = "true" ]; then
echo "Error: Both experiment_use_tmux and experiment_use_screen cannot be true simultaneously."
echo "Please set only one of them to true."
+3 -3
View File
@@ -13,7 +13,7 @@ Run the [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude
```tf
module "claude-code" {
source = "registry.coder.com/coder/claude-code/coder"
version = "2.0.5"
version = "2.0.6"
agent_id = coder_agent.example.id
folder = "/home/coder"
install_claude_code = true
@@ -84,7 +84,7 @@ resource "coder_agent" "main" {
module "claude-code" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/claude-code/coder"
version = "2.0.5"
version = "2.0.6"
agent_id = coder_agent.example.id
folder = "/home/coder"
install_claude_code = true
@@ -102,7 +102,7 @@ Run Claude Code as a standalone app in your workspace. This will install Claude
```tf
module "claude-code" {
source = "registry.coder.com/coder/claude-code/coder"
version = "2.0.5"
version = "2.0.6"
agent_id = coder_agent.example.id
folder = "/home/coder"
install_claude_code = true
@@ -289,11 +289,3 @@ resource "coder_ai_task" "claude_code" {
id = coder_app.claude_code_web.id
}
}
# As of https://github.com/coder/coder/commit/6ba4b5bbc95e2e528d7f5b1e31fffa200ae1a6db,
# there's a bug in Coder's Terraform statefile parsing which prevents it from seeing coder_apps
# in certain scenarios. This is a workaround to bypass this bug until we have a proper fix.
# For more details see https://github.com/coder/coder/issues/18776
resource "terraform_data" "claude_code_app_id" {
input = coder_app.claude_code_web.id
}
+261
View File
@@ -0,0 +1,261 @@
---
display_name: Cursor CLI
description: Run Cursor CLI agent in your workspace with MCP and force mode support
icon: ../../../../.icons/cursor.svg
verified: true
tags: [cli, cursor, ai, agent, mcp, automation]
---
# Cursor CLI
Run the [Cursor CLI](https://docs.cursor.com/en/cli/overview) agent in your workspace for terminal-based AI coding assistance. Supports both interactive and non-interactive modes, MCP (Model Context Protocol), and automation features.
```tf
module "cursor-cli" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/cursor-cli/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
folder = "/home/coder"
}
```
## Prerequisites
- You must add the [Coder Login](https://registry.coder.com/modules/coder-login) module to your template
## Features
- **CLI Agent**: Terminal-based AI coding assistant with interactive and non-interactive modes
- **AgentAPI Integration**: Web interface for CLI interactions
- **Interactive Mode**: Conversational sessions with text output
- **Non-Interactive Mode**: Automation-friendly for scripts and CI pipelines
- **Session Management**: List, resume, and manage coding sessions
- **Model Selection**: Support for multiple AI models (GPT-5, Claude, etc.)
- **MCP Support**: Model Context Protocol for extended functionality
- **Rules System**: Custom agent behavior configuration
## Examples
### Basic setup
```tf
module "coder-login" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/coder-login/coder"
version = "1.0.15"
agent_id = coder_agent.example.id
}
module "cursor-cli" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/cursor-cli/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
install_cursor_cli = true
install_agentapi = true
}
```
### CLI only (no web interface)
```tf
module "cursor-cli" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/cursor-cli/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
install_cursor_cli = true
install_agentapi = false
}
```
### With MCP and force mode for automation
```tf
module "cursor-cli" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/cursor-cli/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
# MCP Configuration
enable_mcp = true
mcp_config_path = "/home/coder/.cursor/custom-mcp.json"
# Automation Features
enable_force_mode = true
default_model = "gpt-5"
# Rules System
enable_rules = true
}
```
### Integration with Coder Tasks
```tf
# Cursor CLI module with automation features
module "cursor-cli" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/cursor-cli/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
enable_force_mode = true
default_model = "claude-4-sonnet"
}
# Automated code review task
resource "coder_task" "ai_code_review" {
agent_id = coder_agent.example.id
name = "AI Code Review"
command = "cursor-agent -p 'review the latest git changes for security issues and best practices' --force --output-format text"
cron = "0 9 * * 1-5" # Weekdays at 9 AM
}
# Automated test generation
resource "coder_task" "generate_tests" {
agent_id = coder_agent.example.id
name = "Generate Missing Tests"
command = "cursor-agent -p 'analyze the src/ directory and generate unit tests for functions missing test coverage' --force"
cron = "0 18 * * *" # Daily at 6 PM
}
# Documentation updates
resource "coder_task" "update_docs" {
agent_id = coder_agent.example.id
name = "Update Documentation"
command = "cursor-agent -p 'review and update README.md to reflect any new features or API changes' --force --model gpt-5"
cron = "0 12 * * 0" # Sundays at noon
}
```
### With custom pre-install script
```tf
module "cursor-cli" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/cursor-cli/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
pre_install_script = <<-EOT
# Install additional dependencies
npm install -g typescript
EOT
}
```
## Usage
### Web Interface
1. Click the "Cursor CLI" button to access the web interface
2. Start interactive sessions with text output
### Terminal Usage
```bash
# Interactive mode (default)
cursor-agent
# Interactive mode with initial prompt
cursor-agent "refactor the auth module to use JWT tokens"
# Non-interactive mode with text output
cursor-agent -p "find and fix performance issues" --output-format text
# Force mode for automation (non-interactive)
cursor-agent -p "review code for security issues" --force
# Use specific model
cursor-agent -p "add error handling" --model "gpt-5"
# Combine force mode with model selection
cursor-agent -p "generate comprehensive tests" --force --model "claude-4-sonnet"
# Session management
cursor-agent ls # List all previous chats
cursor-agent resume # Resume latest conversation
cursor-agent --resume="chat-id" # Resume specific conversation
```
### Interactive Mode Features
- Conversational sessions with the agent
- Review proposed changes before applying
- Real-time guidance and steering
- Text-based output optimized for terminal use
- Session persistence and resumption
### Non-Interactive Mode Features
- Automation-friendly for scripts and CI pipelines
- Direct prompt execution with text output
- Model selection support
- Git integration for change reviews
## Screenshots
### Cursor CLI with Coder Tasks Integration
*Screenshot showing the cursor-cli module working with automated Coder Tasks will be added here*
- Interactive web interface for cursor-agent
- Automated code review tasks running in background
- Terminal output showing force mode execution
- MCP integration with custom tools
## Configuration
The module supports comprehensive configuration options:
### Core Features
- **MCP (Model Context Protocol)**: Automatically detects `mcp.json` configuration or uses custom path
- **Rules System**: Supports `.cursor/rules` directory for custom agent behavior
- **Force Mode**: Enable non-interactive automation for CI/CD pipelines
- **Model Selection**: Set default AI model (gpt-5, claude-4-sonnet, etc.)
- **Environment Variables**: Respects Cursor CLI environment settings
### Available Variables
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `enable_mcp` | bool | `true` | Enable MCP (Model Context Protocol) support |
| `mcp_config_path` | string | `""` | Path to custom MCP configuration file |
| `enable_force_mode` | bool | `false` | Enable force mode for non-interactive automation |
| `default_model` | string | `""` | Default AI model (e.g., gpt-5, claude-4-sonnet) |
| `enable_rules` | bool | `true` | Enable the rules system (.cursor/rules directory) |
| `install_cursor_cli` | bool | `true` | Whether to install Cursor CLI |
| `install_agentapi` | bool | `true` | Whether to install AgentAPI web interface |
| `folder` | string | `"/home/coder"` | Working directory for cursor-agent |
## Troubleshooting
The module creates log files in the workspace's `~/.cursor-cli-module` directory. Check these files if you encounter issues:
```bash
# Check installation logs
cat ~/.cursor-cli-module/install.log
# Check runtime logs
cat ~/.cursor-cli-module/runtime.log
# Verify Cursor CLI installation
cursor-agent --help
```
### Common Issues
1. **Cursor CLI not found**: Ensure `install_cursor_cli = true` or install manually:
```bash
curl https://cursor.com/install -fsS | bash
```
2. **Permission issues**: Check that the installation script has proper permissions
3. **Path issues**: The module automatically adds Cursor CLI to PATH, but you may need to restart your shell
@@ -0,0 +1,80 @@
import { describe, expect, it } from "bun:test";
import {
runTerraformApply,
runTerraformInit,
testRequiredVariables,
} from "~test";
describe("cursor-cli", async () => {
await runTerraformInit(import.meta.dir);
testRequiredVariables(import.meta.dir, {
agent_id: "foo",
});
it("default output with CLI enabled", async () => {
const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo",
});
// Check that AgentAPI module is created
const agentapi_module = state.resources.find(
(res) => res.type === "module" && res.name === "agentapi",
);
expect(agentapi_module).not.toBeNull();
});
it("adds custom folder", async () => {
const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo",
folder: "/foo/bar",
});
// Check that AgentAPI module is created with custom folder
const agentapi_module = state.resources.find(
(res) => res.type === "module" && res.name === "agentapi",
);
expect(agentapi_module).not.toBeNull();
});
it("expect order to be set", async () => {
const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo",
order: "22",
});
// Check that AgentAPI module is created
const agentapi_module = state.resources.find(
(res) => res.type === "module" && res.name === "agentapi",
);
expect(agentapi_module).not.toBeNull();
});
it("disables CLI installation", async () => {
const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo",
install_cursor_cli: "false",
install_agentapi: "false",
});
// AgentAPI module should still exist but with install_agentapi = false
const agentapi_module = state.resources.find(
(res) => res.type === "module" && res.name === "agentapi",
);
expect(agentapi_module).not.toBeNull();
});
it("enables only CLI without web interface", async () => {
const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo",
install_cursor_cli: "true",
install_agentapi: "false",
});
// AgentAPI module should exist but with install_agentapi = false
const agentapi_module = state.resources.find(
(res) => res.type === "module" && res.name === "agentapi",
);
expect(agentapi_module).not.toBeNull();
});
});
+154
View File
@@ -0,0 +1,154 @@
terraform {
required_version = ">= 1.0"
required_providers {
coder = {
source = "coder/coder"
version = ">= 2.7"
}
}
}
variable "agent_id" {
type = string
description = "The ID of a Coder agent."
}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}
variable "order" {
type = number
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)."
default = null
}
variable "group" {
type = string
description = "The name of a group that this app belongs to."
default = null
}
variable "icon" {
type = string
description = "The icon to use for the app."
default = "/icon/cursor.svg"
}
variable "folder" {
type = string
description = "The folder to run Cursor CLI in."
default = "/home/coder"
}
variable "install_cursor_cli" {
type = bool
description = "Whether to install Cursor CLI."
default = true
}
variable "install_agentapi" {
type = bool
description = "Whether to install AgentAPI."
default = true
}
variable "agentapi_version" {
type = string
description = "The version of AgentAPI to install."
default = "v0.3.3"
}
variable "subdomain" {
type = bool
description = "Whether to use a subdomain for AgentAPI."
default = true
}
variable "pre_install_script" {
type = string
description = "Custom script to run before installing Cursor CLI."
default = null
}
variable "post_install_script" {
type = string
description = "Custom script to run after installing Cursor CLI."
default = null
}
variable "enable_mcp" {
type = bool
description = "Whether to enable MCP (Model Context Protocol) support."
default = true
}
variable "mcp_config_path" {
type = string
description = "Path to the MCP configuration file (mcp.json)."
default = ""
}
variable "enable_force_mode" {
type = bool
description = "Whether to enable force mode for non-interactive automation."
default = false
}
variable "default_model" {
type = string
description = "Default AI model to use (e.g., gpt-5, claude-4-sonnet)."
default = ""
}
variable "enable_rules" {
type = bool
description = "Whether to enable the rules system (.cursor/rules directory)."
default = true
}
locals {
app_slug = "cursor-cli"
install_script = file("${path.module}/scripts/install.sh")
start_script = file("${path.module}/scripts/start.sh")
module_dir_name = ".cursor-cli-module"
}
module "agentapi" {
source = "registry.coder.com/coder/agentapi/coder"
version = "1.1.0"
agent_id = var.agent_id
web_app_slug = local.app_slug
web_app_order = var.order
web_app_group = var.group
web_app_icon = var.icon
web_app_display_name = "Cursor CLI"
cli_app_slug = "${local.app_slug}-terminal"
cli_app_display_name = "Cursor CLI Terminal"
module_dir_name = local.module_dir_name
install_agentapi = var.install_agentapi
agentapi_version = var.agentapi_version
agentapi_subdomain = var.subdomain
pre_install_script = var.pre_install_script
post_install_script = var.post_install_script
start_script = local.start_script
install_script = <<-EOT
#!/bin/bash
set -o errexit
set -o pipefail
echo -n '${base64encode(local.install_script)}' | base64 -d > /tmp/install.sh
chmod +x /tmp/install.sh
ARG_FOLDER='${var.folder}' \
ARG_INSTALL='${var.install_cursor_cli}' \
ARG_ENABLE_MCP='${var.enable_mcp}' \
ARG_MCP_CONFIG_PATH='${var.mcp_config_path}' \
ARG_ENABLE_FORCE_MODE='${var.enable_force_mode}' \
ARG_DEFAULT_MODEL='${var.default_model}' \
ARG_ENABLE_RULES='${var.enable_rules}' \
/tmp/install.sh
EOT
}
@@ -0,0 +1,103 @@
#!/bin/bash
# Function to check if a command exists
command_exists() {
command -v "$1" > /dev/null 2>&1
}
set -o nounset
echo "--------------------------------"
echo "folder: $ARG_FOLDER"
echo "install: $ARG_INSTALL"
echo "enable_mcp: $ARG_ENABLE_MCP"
echo "mcp_config_path: $ARG_MCP_CONFIG_PATH"
echo "enable_force_mode: $ARG_ENABLE_FORCE_MODE"
echo "default_model: $ARG_DEFAULT_MODEL"
echo "enable_rules: $ARG_ENABLE_RULES"
echo "--------------------------------"
set +o nounset
if [ "${ARG_INSTALL}" = "true" ]; then
echo "Installing Cursor CLI..."
# Install Cursor CLI using the official installer
curl https://cursor.com/install -fsS | bash
# Add cursor-agent to PATH if not already there
if ! command_exists cursor-agent; then
echo 'export PATH="$HOME/.cursor/bin:$PATH"' >> "$HOME/.bashrc"
echo 'export PATH="$HOME/.cursor/bin:$PATH"' >> "$HOME/.zshrc" 2> /dev/null || true
export PATH="$HOME/.cursor/bin:$PATH"
fi
echo "Cursor CLI installed"
# Configure MCP if enabled
if [ "${ARG_ENABLE_MCP}" = "true" ]; then
echo "Configuring MCP (Model Context Protocol)..."
# Create MCP config directory if it doesn't exist
mkdir -p "$HOME/.cursor"
# If custom MCP config path is provided, copy it
if [ -n "${ARG_MCP_CONFIG_PATH}" ] && [ -f "${ARG_MCP_CONFIG_PATH}" ]; then
cp "${ARG_MCP_CONFIG_PATH}" "$HOME/.cursor/mcp.json"
echo "MCP configuration copied from ${ARG_MCP_CONFIG_PATH}"
else
# Create a basic MCP config if none exists
if [ ! -f "$HOME/.cursor/mcp.json" ]; then
cat > "$HOME/.cursor/mcp.json" << 'EOF'
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem", "/tmp"]
}
}
}
EOF
echo "Basic MCP configuration created"
fi
fi
fi
# Configure rules system if enabled
if [ "${ARG_ENABLE_RULES}" = "true" ]; then
echo "Setting up Cursor rules system..."
mkdir -p "$HOME/.cursor/rules"
# Create a basic rules file if none exists
if [ ! -f "$HOME/.cursor/rules/general.md" ]; then
cat > "$HOME/.cursor/rules/general.md" << 'EOF'
# General Coding Rules
## Code Style
- Use consistent indentation (2 spaces for JS/TS, 4 for Python)
- Add meaningful comments for complex logic
- Follow language-specific naming conventions
## Best Practices
- Write tests for new functionality
- Handle errors gracefully
- Use descriptive variable and function names
EOF
echo "Basic rules configuration created"
fi
fi
else
echo "Skipping Cursor CLI installation"
fi
# Verify installation
if command_exists cursor-agent; then
CURSOR_CMD=cursor-agent
elif [ -f "$HOME/.cursor/bin/cursor-agent" ]; then
CURSOR_CMD="$HOME/.cursor/bin/cursor-agent"
else
echo "Warning: Cursor CLI is not installed or not found in PATH. Please enable install_cursor_cli or install it manually."
echo "You can install it manually with: curl https://cursor.com/install -fsS | bash"
fi
echo "Cursor CLI setup complete"
@@ -0,0 +1,67 @@
#!/bin/bash
# Function to check if a command exists
command_exists() {
command -v "$1" > /dev/null 2>&1
}
# Set working directory
if [ -n "${ARG_FOLDER:-}" ] && [ -d "${ARG_FOLDER}" ]; then
cd "${ARG_FOLDER}" || {
echo "Warning: Could not change to directory ${ARG_FOLDER}, using current directory"
}
fi
# Find cursor-agent command
if command_exists cursor-agent; then
CURSOR_CMD=cursor-agent
elif [ -f "$HOME/.cursor/bin/cursor-agent" ]; then
CURSOR_CMD="$HOME/.cursor/bin/cursor-agent"
else
echo "Error: Cursor CLI is not installed. Please enable install_cursor_cli or install it manually."
echo "You can install it manually with: curl https://cursor.com/install -fsS | bash"
exit 1
fi
echo "Starting Cursor CLI in $(pwd)"
echo "Interactive mode with text output enabled"
echo "Available commands:"
echo " - Start interactive session: cursor-agent"
echo " - Non-interactive mode: cursor-agent -p 'your prompt here'"
echo " - With specific model: cursor-agent -p 'prompt' --model 'gpt-5'"
echo " - Text output format: cursor-agent -p 'prompt' --output-format text"
echo " - Force mode (non-interactive): cursor-agent -p 'prompt' --force"
echo " - List sessions: cursor-agent ls"
echo " - Resume session: cursor-agent resume"
echo ""
# Set up environment variables for configuration
if [ -n "${ARG_DEFAULT_MODEL:-}" ]; then
export CURSOR_DEFAULT_MODEL="${ARG_DEFAULT_MODEL}"
echo "Default model set to: ${ARG_DEFAULT_MODEL}"
fi
if [ "${ARG_ENABLE_FORCE_MODE:-false}" = "true" ]; then
export CURSOR_FORCE_MODE="true"
echo "Force mode enabled for non-interactive automation"
fi
if [ "${ARG_ENABLE_MCP:-true}" = "true" ]; then
echo "MCP (Model Context Protocol) support enabled"
fi
if [ "${ARG_ENABLE_RULES:-true}" = "true" ]; then
echo "Rules system enabled (.cursor/rules directory)"
fi
echo ""
# Configure for interactive mode with text output
# If no arguments provided, start in interactive mode
if [ $# -eq 0 ]; then
echo "Starting interactive session..."
exec "$CURSOR_CMD"
else
# Pass through all arguments for custom usage
exec "$CURSOR_CMD" "$@"
fi
@@ -15,7 +15,7 @@ The devcontainers-cli module provides an easy way to install [`@devcontainers/cl
```tf
module "devcontainers-cli" {
source = "registry.coder.com/coder/devcontainers-cli/coder"
version = "1.0.31"
version = "1.0.32"
agent_id = coder_agent.example.id
}
```
@@ -45,6 +45,8 @@ const executeScriptInContainerWithPackageManager = async (
console.log(path);
await execContainer(id, [shell, "-c", "mkdir -p /tmp/coder-script-data"]);
const resp = await execContainer(
id,
[shell, "-c", instance.script],
@@ -52,6 +54,8 @@ const executeScriptInContainerWithPackageManager = async (
"--env",
"CODER_SCRIPT_BIN_DIR=/tmp/coder-script-data/bin",
"--env",
"CODER_SCRIPT_DATA_DIR=/tmp/coder-script-data",
"--env",
`PATH=${path}:/tmp/coder-script-data/bin`,
],
);
+7 -1
View File
@@ -1,5 +1,11 @@
#!/usr/bin/env sh
# We want to cd into `$CODER_SCRIPT_DATA_DIR` as the current directory
# might contain a `package.json` with `packageManager` set to something
# other than the detected package manager. When this happens, it can
# cause the installation to fail.
cd "$CODER_SCRIPT_DATA_DIR"
# If @devcontainers/cli is already installed, we can skip
if command -v devcontainer >/dev/null 2>&1; then
echo "🥳 @devcontainers/cli is already installed into $(which devcontainer)!"
@@ -34,7 +40,7 @@ install() {
# so that the devcontainer command is available
if [ -z "$PNPM_HOME" ]; then
PNPM_HOME="$CODER_SCRIPT_BIN_DIR"
export M_HOME
export PNPM_HOME
fi
pnpm add -g @devcontainers/cli
elif [ "$PACKAGE_MANAGER" = "yarn" ]; then
+2 -2
View File
@@ -13,7 +13,7 @@ Run the [Goose](https://block.github.io/goose/) agent in your workspace to gener
```tf
module "goose" {
source = "registry.coder.com/coder/goose/coder"
version = "2.0.1"
version = "2.1.0"
agent_id = coder_agent.example.id
folder = "/home/coder"
install_goose = true
@@ -79,7 +79,7 @@ resource "coder_agent" "main" {
module "goose" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/goose/coder"
version = "2.0.1"
version = "2.1.0"
agent_id = coder_agent.example.id
folder = "/home/coder"
install_goose = true
+17
View File
@@ -251,4 +251,21 @@ describe("goose", async () => {
expect(prompt.exitCode).not.toBe(0);
expect(prompt.stderr).toContain("No such file or directory");
});
test("subdomain-false", async () => {
const { id } = await setup({
agentapiMockScript: await loadTestFile(
import.meta.dir,
"agentapi-mock-print-args.js",
),
moduleVariables: {
subdomain: "false",
},
});
await execModuleScript(id);
const agentapiMockOutput = await readFileContainer(id, agentapiStartLog);
expect(agentapiMockOutput).toContain("AGENTAPI_CHAT_BASE_PATH=/@default/default.foo/apps/goose/chat");
});
});
+9 -2
View File
@@ -63,7 +63,13 @@ variable "install_agentapi" {
variable "agentapi_version" {
type = string
description = "The version of AgentAPI to install."
default = "v0.2.3"
default = "v0.3.3"
}
variable "subdomain" {
type = bool
description = "Whether to use a subdomain for AgentAPI."
default = true
}
variable "goose_provider" {
@@ -133,7 +139,7 @@ EOT
module "agentapi" {
source = "registry.coder.com/coder/agentapi/coder"
version = "1.0.0"
version = "1.1.0"
agent_id = var.agent_id
web_app_slug = local.app_slug
@@ -146,6 +152,7 @@ module "agentapi" {
module_dir_name = local.module_dir_name
install_agentapi = var.install_agentapi
agentapi_version = var.agentapi_version
agentapi_subdomain = var.subdomain
pre_install_script = var.pre_install_script
post_install_script = var.post_install_script
start_script = local.start_script
@@ -3,6 +3,7 @@
const http = require("http");
const args = process.argv.slice(2);
console.log(args);
console.log(`AGENTAPI_CHAT_BASE_PATH=${process.env["AGENTAPI_CHAT_BASE_PATH"]}`);
const port = 3284;
console.log(`starting server on port ${port}`);
+6 -6
View File
@@ -14,7 +14,7 @@ This module adds JetBrains IDE buttons to launch IDEs directly from the dashboar
module "jetbrains" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains/coder"
version = "1.0.1"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
}
@@ -39,7 +39,7 @@ When `default` contains IDE codes, those IDEs are created directly without user
module "jetbrains" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains/coder"
version = "1.0.1"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
default = ["PY", "IU"] # Pre-configure GoLand and IntelliJ IDEA
@@ -52,7 +52,7 @@ module "jetbrains" {
module "jetbrains" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains/coder"
version = "1.0.1"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
# Show parameter with limited options
@@ -66,7 +66,7 @@ module "jetbrains" {
module "jetbrains" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains/coder"
version = "1.0.1"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
default = ["IU", "PY"]
@@ -81,7 +81,7 @@ module "jetbrains" {
module "jetbrains" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains/coder"
version = "1.0.1"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/workspace/project"
@@ -107,7 +107,7 @@ module "jetbrains" {
module "jetbrains_pycharm" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains/coder"
version = "1.0.1"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/workspace/project"
+1
View File
@@ -202,6 +202,7 @@ data "coder_parameter" "jetbrains_ides" {
count = length(var.default) == 0 ? 1 : 0
type = "list(string)"
name = "jetbrains_ides"
description = "Select which JetBrains IDEs to configure for use in this workspace."
display_name = "JetBrains IDEs"
icon = "/icon/jetbrains-toolbox.svg"
mutable = true
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail
# Find all directories that contain any .tftest.hcl files and run terraform test in each
run_dir() {
local dir="$1"
echo "==> Running terraform test in $dir"
(cd "$dir" && terraform init -upgrade -input=false -no-color > /dev/null && terraform test -no-color -verbose)
}
mapfile -t test_dirs < <(find . -type f -name "*.tftest.hcl" -print0 | xargs -0 -I{} dirname {} | sort -u)
if [[ ${#test_dirs[@]} -eq 0 ]]; then
echo "No .tftest.hcl tests found."
exit 0
fi
status=0
for d in "${test_dirs[@]}"; do
if ! run_dir "$d"; then
status=1
fi
done
exit $status