chore: add sample data
This commit is contained in:
parent
a00a9ce589
commit
f10f5a4403
3
.gitignore
vendored
3
.gitignore
vendored
@ -135,5 +135,6 @@ dist
|
|||||||
.yarn/install-state.gz
|
.yarn/install-state.gz
|
||||||
.pnp.*
|
.pnp.*
|
||||||
|
|
||||||
# Script output
|
# Things needed for CI
|
||||||
/readmevalidation
|
/readmevalidation
|
||||||
|
/readmevalidation-git
|
||||||
|
|||||||
@ -12,6 +12,13 @@ import (
|
|||||||
"coder.com/coder-registry/cmd/github"
|
"coder.com/coder-registry/cmd/github"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// dummyGitDirectory is the directory that a full version of the Registry will
|
||||||
|
// be cloned into during CI. The CI needs to use Git history to validate
|
||||||
|
// certain README files, and using the root branch itself (even though it's
|
||||||
|
// fully equivalent) has a risk of breaking other CI steps when switching
|
||||||
|
// branches. Better to make a full isolated copy and manipulate that.
|
||||||
|
const dummyGitDirectory = "./readmevalidation-git"
|
||||||
|
|
||||||
var supportedResourceTypes = []string{"modules", "templates"}
|
var supportedResourceTypes = []string{"modules", "templates"}
|
||||||
|
|
||||||
type coderResourceFrontmatter struct {
|
type coderResourceFrontmatter struct {
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import (
|
|||||||
"coder.com/coder-registry/cmd/github"
|
"coder.com/coder-registry/cmd/github"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -110,9 +111,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
fmt.Printf("------ got %d back\n", len(baseRefReadmeFiles))
|
fmt.Printf("------ got %d back\n", len(baseRefReadmeFiles))
|
||||||
|
|
||||||
repo, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{
|
repo, err := git.PlainClone(dummyGitDirectory, true, &git.CloneOptions{
|
||||||
DetectDotGit: false,
|
URL: "https://github.com/coder/registry",
|
||||||
EnableDotGitCommonDir: false,
|
Auth: &http.BasicAuth{},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -123,7 +124,6 @@ func main() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
activeBranchName := head.Name().Short()
|
activeBranchName := head.Name().Short()
|
||||||
fmt.Println("yeah...")
|
|
||||||
|
|
||||||
tree, err := repo.Worktree()
|
tree, err := repo.Worktree()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -71,6 +71,12 @@ func validateRegistryDirectory() []error {
|
|||||||
problems = append(problems, err)
|
problems = append(problems, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainTerraformPath := path.Join(dirPath, "main.tf")
|
||||||
|
_, err = os.Stat(mainTerraformPath)
|
||||||
|
if err != nil {
|
||||||
|
problems = append(problems, err)
|
||||||
|
}
|
||||||
|
|
||||||
for _, rType := range supportedResourceTypes {
|
for _, rType := range supportedResourceTypes {
|
||||||
resourcePath := path.Join(dirPath, rType)
|
resourcePath := path.Join(dirPath, rType)
|
||||||
if errs := validateCoderResourceSubdirectory(resourcePath); len(errs) != 0 {
|
if errs := validateCoderResourceSubdirectory(resourcePath); len(errs) != 0 {
|
||||||
|
|||||||
113
registry/coder/modules/claude-code/README.md
Normal file
113
registry/coder/modules/claude-code/README.md
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
---
|
||||||
|
display_name: Claude Code
|
||||||
|
description: Run Claude Code in your workspace
|
||||||
|
icon: ../.icons/claude.svg
|
||||||
|
verified: true
|
||||||
|
tags: [agent, claude-code]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Claude Code
|
||||||
|
|
||||||
|
Run the [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview) agent in your workspace to generate code and perform tasks.
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "claude-code" {
|
||||||
|
source = "registry.coder.com/modules/claude-code/coder"
|
||||||
|
version = "1.0.31"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
folder = "/home/coder"
|
||||||
|
install_claude_code = true
|
||||||
|
claude_code_version = "latest"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Node.js and npm must be installed in your workspace to install Claude Code
|
||||||
|
- `screen` must be installed in your workspace to run Claude Code in the background
|
||||||
|
- You must add the [Coder Login](https://registry.coder.com/modules/coder-login) module to your template
|
||||||
|
|
||||||
|
The `codercom/oss-dogfood:latest` container image can be used for testing on container-based workspaces.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Run in the background and report tasks (Experimental)
|
||||||
|
|
||||||
|
> This functionality is in early access as of Coder v2.21 and is still evolving.
|
||||||
|
> For now, we recommend testing it in a demo or staging environment,
|
||||||
|
> rather than deploying to production
|
||||||
|
>
|
||||||
|
> Learn more in [the Coder documentation](https://coder.com/docs/tutorials/ai-agents)
|
||||||
|
>
|
||||||
|
> Join our [Discord channel](https://discord.gg/coder) or
|
||||||
|
> [contact us](https://coder.com/contact) to get help or share feedback.
|
||||||
|
|
||||||
|
Your workspace must have `screen` installed to use this.
|
||||||
|
|
||||||
|
```tf
|
||||||
|
variable "anthropic_api_key" {
|
||||||
|
type = string
|
||||||
|
description = "The Anthropic API key"
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
module "coder-login" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/modules/coder-login/coder"
|
||||||
|
version = "1.0.15"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
}
|
||||||
|
|
||||||
|
data "coder_parameter" "ai_prompt" {
|
||||||
|
type = "string"
|
||||||
|
name = "AI Prompt"
|
||||||
|
default = ""
|
||||||
|
description = "Write a prompt for Claude Code"
|
||||||
|
mutable = true
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set the prompt and system prompt for Claude Code via environment variables
|
||||||
|
resource "coder_agent" "main" {
|
||||||
|
# ...
|
||||||
|
env = {
|
||||||
|
CODER_MCP_CLAUDE_API_KEY = var.anthropic_api_key # or use a coder_parameter
|
||||||
|
CODER_MCP_CLAUDE_TASK_PROMPT = data.coder_parameter.ai_prompt.value
|
||||||
|
CODER_MCP_APP_STATUS_SLUG = "claude-code"
|
||||||
|
CODER_MCP_CLAUDE_SYSTEM_PROMPT = <<-EOT
|
||||||
|
You are a helpful assistant that can help with code.
|
||||||
|
EOT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module "claude-code" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/modules/claude-code/coder"
|
||||||
|
version = "1.0.31"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
folder = "/home/coder"
|
||||||
|
install_claude_code = true
|
||||||
|
claude_code_version = "0.2.57"
|
||||||
|
|
||||||
|
# Enable experimental features
|
||||||
|
experiment_use_screen = true
|
||||||
|
experiment_report_tasks = true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run standalone
|
||||||
|
|
||||||
|
Run Claude Code as a standalone app in your workspace. This will install Claude Code and run it directly without using screen or any task reporting to the Coder UI.
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "claude-code" {
|
||||||
|
source = "registry.coder.com/modules/claude-code/coder"
|
||||||
|
version = "1.0.31"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
folder = "/home/coder"
|
||||||
|
install_claude_code = true
|
||||||
|
claude_code_version = "latest"
|
||||||
|
|
||||||
|
# Icon is not available in Coder v2.20 and below, so we'll use a custom icon URL
|
||||||
|
icon = "https://registry.npmmirror.com/@lobehub/icons-static-png/1.24.0/files/dark/claude-color.png"
|
||||||
|
}
|
||||||
|
```
|
||||||
170
registry/coder/modules/claude-code/main.tf
Normal file
170
registry/coder/modules/claude-code/main.tf
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
terraform {
|
||||||
|
required_version = ">= 1.0"
|
||||||
|
|
||||||
|
required_providers {
|
||||||
|
coder = {
|
||||||
|
source = "coder/coder"
|
||||||
|
version = ">= 0.17"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 "icon" {
|
||||||
|
type = string
|
||||||
|
description = "The icon to use for the app."
|
||||||
|
default = "/icon/claude.svg"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "folder" {
|
||||||
|
type = string
|
||||||
|
description = "The folder to run Claude Code in."
|
||||||
|
default = "/home/coder"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "install_claude_code" {
|
||||||
|
type = bool
|
||||||
|
description = "Whether to install Claude Code."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "claude_code_version" {
|
||||||
|
type = string
|
||||||
|
description = "The version of Claude Code to install."
|
||||||
|
default = "latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "experiment_use_screen" {
|
||||||
|
type = bool
|
||||||
|
description = "Whether to use screen for running Claude Code in the background."
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "experiment_report_tasks" {
|
||||||
|
type = bool
|
||||||
|
description = "Whether to enable task reporting."
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install and Initialize Claude Code
|
||||||
|
resource "coder_script" "claude_code" {
|
||||||
|
agent_id = var.agent_id
|
||||||
|
display_name = "Claude Code"
|
||||||
|
icon = var.icon
|
||||||
|
script = <<-EOT
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Function to check if a command exists
|
||||||
|
command_exists() {
|
||||||
|
command -v "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install Claude Code if enabled
|
||||||
|
if [ "${var.install_claude_code}" = "true" ]; then
|
||||||
|
if ! command_exists npm; then
|
||||||
|
echo "Error: npm is not installed. Please install Node.js and npm first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Installing Claude Code..."
|
||||||
|
npm install -g @anthropic-ai/claude-code@${var.claude_code_version}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${var.experiment_report_tasks}" = "true" ]; then
|
||||||
|
echo "Configuring Claude Code to report tasks via Coder MCP..."
|
||||||
|
coder exp mcp configure claude-code ${var.folder}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run with screen if enabled
|
||||||
|
if [ "${var.experiment_use_screen}" = "true" ]; then
|
||||||
|
echo "Running Claude Code in the background..."
|
||||||
|
|
||||||
|
# Check if screen is installed
|
||||||
|
if ! command_exists screen; then
|
||||||
|
echo "Error: screen is not installed. Please install screen manually."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
touch "$HOME/.claude-code.log"
|
||||||
|
|
||||||
|
# Ensure the screenrc exists
|
||||||
|
if [ ! -f "$HOME/.screenrc" ]; then
|
||||||
|
echo "Creating ~/.screenrc and adding multiuser settings..." | tee -a "$HOME/.claude-code.log"
|
||||||
|
echo -e "multiuser on\nacladd $(whoami)" > "$HOME/.screenrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q "^multiuser on$" "$HOME/.screenrc"; then
|
||||||
|
echo "Adding 'multiuser on' to ~/.screenrc..." | tee -a "$HOME/.claude-code.log"
|
||||||
|
echo "multiuser on" >> "$HOME/.screenrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q "^acladd $(whoami)$" "$HOME/.screenrc"; then
|
||||||
|
echo "Adding 'acladd $(whoami)' to ~/.screenrc..." | tee -a "$HOME/.claude-code.log"
|
||||||
|
echo "acladd $(whoami)" >> "$HOME/.screenrc"
|
||||||
|
fi
|
||||||
|
export LANG=en_US.UTF-8
|
||||||
|
export LC_ALL=en_US.UTF-8
|
||||||
|
|
||||||
|
screen -U -dmS claude-code bash -c '
|
||||||
|
cd ${var.folder}
|
||||||
|
claude --dangerously-skip-permissions | tee -a "$HOME/.claude-code.log"
|
||||||
|
exec bash
|
||||||
|
'
|
||||||
|
# Extremely hacky way to send the prompt to the screen session
|
||||||
|
# This will be fixed in the future, but `claude` was not sending MCP
|
||||||
|
# tasks when an initial prompt is provided.
|
||||||
|
screen -S claude-code -X stuff "$CODER_MCP_CLAUDE_TASK_PROMPT"
|
||||||
|
sleep 5
|
||||||
|
screen -S claude-code -X stuff "^M"
|
||||||
|
else
|
||||||
|
# Check if claude is installed before running
|
||||||
|
if ! command_exists claude; then
|
||||||
|
echo "Error: Claude Code is not installed. Please enable install_claude_code or install it manually."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
EOT
|
||||||
|
run_on_start = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "coder_app" "claude_code" {
|
||||||
|
slug = "claude-code"
|
||||||
|
display_name = "Claude Code"
|
||||||
|
agent_id = var.agent_id
|
||||||
|
command = <<-EOT
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "${var.experiment_use_screen}" = "true" ]; then
|
||||||
|
if screen -list | grep -q "claude-code"; then
|
||||||
|
export LANG=en_US.UTF-8
|
||||||
|
export LC_ALL=en_US.UTF-8
|
||||||
|
echo "Attaching to existing Claude Code session." | tee -a "$HOME/.claude-code.log"
|
||||||
|
screen -xRR claude-code
|
||||||
|
else
|
||||||
|
echo "Starting a new Claude Code session." | tee -a "$HOME/.claude-code.log"
|
||||||
|
screen -S claude-code bash -c 'export LANG=en_US.UTF-8; export LC_ALL=en_US.UTF-8; claude --dangerously-skip-permissions | tee -a "$HOME/.claude-code.log"; exec bash'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cd ${var.folder}
|
||||||
|
export LANG=en_US.UTF-8
|
||||||
|
export LC_ALL=en_US.UTF-8
|
||||||
|
claude
|
||||||
|
fi
|
||||||
|
EOT
|
||||||
|
icon = var.icon
|
||||||
|
}
|
||||||
36
registry/coder/modules/cursor/README.md
Normal file
36
registry/coder/modules/cursor/README.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
display_name: Cursor IDE
|
||||||
|
description: Add a one-click button to launch Cursor IDE
|
||||||
|
icon: ../.icons/cursor.svg
|
||||||
|
verified: true
|
||||||
|
tags: [ide, cursor, helper]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Cursor IDE
|
||||||
|
|
||||||
|
Add a button to open any workspace with a single click in Cursor IDE.
|
||||||
|
|
||||||
|
Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder).
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "cursor" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/modules/cursor/coder"
|
||||||
|
version = "1.0.19"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Open in a specific directory
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "cursor" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/modules/cursor/coder"
|
||||||
|
version = "1.0.19"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
folder = "/home/coder/project"
|
||||||
|
}
|
||||||
|
```
|
||||||
88
registry/coder/modules/cursor/main.test.ts
Normal file
88
registry/coder/modules/cursor/main.test.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import { describe, expect, it } from "bun:test";
|
||||||
|
import {
|
||||||
|
runTerraformApply,
|
||||||
|
runTerraformInit,
|
||||||
|
testRequiredVariables,
|
||||||
|
} from "../test";
|
||||||
|
|
||||||
|
describe("cursor", async () => {
|
||||||
|
await runTerraformInit(import.meta.dir);
|
||||||
|
|
||||||
|
testRequiredVariables(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
});
|
||||||
|
|
||||||
|
it("default output", async () => {
|
||||||
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
});
|
||||||
|
expect(state.outputs.cursor_url.value).toBe(
|
||||||
|
"cursor://coder.coder-remote/open?owner=default&workspace=default&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
|
||||||
|
);
|
||||||
|
|
||||||
|
const coder_app = state.resources.find(
|
||||||
|
(res) => res.type === "coder_app" && res.name === "cursor",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(coder_app).not.toBeNull();
|
||||||
|
expect(coder_app?.instances.length).toBe(1);
|
||||||
|
expect(coder_app?.instances[0].attributes.order).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds folder", async () => {
|
||||||
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
folder: "/foo/bar",
|
||||||
|
});
|
||||||
|
expect(state.outputs.cursor_url.value).toBe(
|
||||||
|
"cursor://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds folder and open_recent", async () => {
|
||||||
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
folder: "/foo/bar",
|
||||||
|
open_recent: "true",
|
||||||
|
});
|
||||||
|
expect(state.outputs.cursor_url.value).toBe(
|
||||||
|
"cursor://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds folder but not open_recent", async () => {
|
||||||
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
folder: "/foo/bar",
|
||||||
|
openRecent: "false",
|
||||||
|
});
|
||||||
|
expect(state.outputs.cursor_url.value).toBe(
|
||||||
|
"cursor://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds open_recent", async () => {
|
||||||
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
open_recent: "true",
|
||||||
|
});
|
||||||
|
expect(state.outputs.cursor_url.value).toBe(
|
||||||
|
"cursor://coder.coder-remote/open?owner=default&workspace=default&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("expect order to be set", async () => {
|
||||||
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
order: "22",
|
||||||
|
});
|
||||||
|
|
||||||
|
const coder_app = state.resources.find(
|
||||||
|
(res) => res.type === "coder_app" && res.name === "cursor",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(coder_app).not.toBeNull();
|
||||||
|
expect(coder_app?.instances.length).toBe(1);
|
||||||
|
expect(coder_app?.instances[0].attributes.order).toBe(22);
|
||||||
|
});
|
||||||
|
});
|
||||||
62
registry/coder/modules/cursor/main.tf
Normal file
62
registry/coder/modules/cursor/main.tf
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
terraform {
|
||||||
|
required_version = ">= 1.0"
|
||||||
|
|
||||||
|
required_providers {
|
||||||
|
coder = {
|
||||||
|
source = "coder/coder"
|
||||||
|
version = ">= 0.23"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "agent_id" {
|
||||||
|
type = string
|
||||||
|
description = "The ID of a Coder agent."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "folder" {
|
||||||
|
type = string
|
||||||
|
description = "The folder to open in Cursor IDE."
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "open_recent" {
|
||||||
|
type = bool
|
||||||
|
description = "Open the most recent workspace or folder. Falls back to the folder if there is no recent workspace or folder to open."
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
data "coder_workspace" "me" {}
|
||||||
|
data "coder_workspace_owner" "me" {}
|
||||||
|
|
||||||
|
resource "coder_app" "cursor" {
|
||||||
|
agent_id = var.agent_id
|
||||||
|
external = true
|
||||||
|
icon = "/icon/cursor.svg"
|
||||||
|
slug = "cursor"
|
||||||
|
display_name = "Cursor Desktop"
|
||||||
|
order = var.order
|
||||||
|
url = join("", [
|
||||||
|
"cursor://coder.coder-remote/open",
|
||||||
|
"?owner=",
|
||||||
|
data.coder_workspace_owner.me.name,
|
||||||
|
"&workspace=",
|
||||||
|
data.coder_workspace.me.name,
|
||||||
|
var.folder != "" ? join("", ["&folder=", var.folder]) : "",
|
||||||
|
var.open_recent ? "&openRecent" : "",
|
||||||
|
"&url=",
|
||||||
|
data.coder_workspace.me.access_url,
|
||||||
|
"&token=$SESSION_TOKEN",
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
output "cursor_url" {
|
||||||
|
value = coder_app.cursor.url
|
||||||
|
description = "Cursor IDE Desktop URL."
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user