From ec0240ee281815f69b2e8fde2b4a68341bf127b5 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Mon, 17 Aug 2026 10:13:42 +0000 Subject: [PATCH 01/12] feat: add devin-desktop module (Windsurf's June 2026 rebrand) --- .../coder/modules/devin-desktop/README.md | 75 ++++++++++ .../coder/modules/devin-desktop/main.test.ts | 132 ++++++++++++++++++ registry/coder/modules/devin-desktop/main.tf | 110 +++++++++++++++ registry/coder/modules/windsurf/README.md | 5 + 4 files changed, 322 insertions(+) create mode 100644 registry/coder/modules/devin-desktop/README.md create mode 100644 registry/coder/modules/devin-desktop/main.test.ts create mode 100644 registry/coder/modules/devin-desktop/main.tf diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md new file mode 100644 index 000000000..7d21ece8d --- /dev/null +++ b/registry/coder/modules/devin-desktop/README.md @@ -0,0 +1,75 @@ +--- +display_name: Devin Desktop +description: Add a one-click button to launch Devin Desktop (formerly Windsurf Editor) +icon: ../../../../.icons/windsurf.svg +verified: true +tags: [ide, devin-desktop, windsurf, ai] +--- + +# Devin Desktop + +> [!NOTE] +> Devin Desktop is Cognition's June 2, 2026 rebrand of the Windsurf Editor (itself a rebrand of Codeium's +> original editor). It shipped as an automatic update to existing Windsurf installs, so it reuses Windsurf's +> `windsurf://` deep link protocol and `~/.codeium/windsurf/` config paths. This registry does not have a +> dedicated Devin Desktop icon yet, so this module reuses the Windsurf mark. + +Add a button to open any workspace with a single click in Devin Desktop. + +Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder). + +```tf +module "devin-desktop" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/devin-desktop/coder" + version = "1.0.0" + agent_id = coder_agent.main.id +} +``` + +## Examples + +### Open in a specific directory + +```tf +module "devin-desktop" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/devin-desktop/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + folder = "/home/coder/project" +} +``` + +### Configure MCP servers for Devin Desktop + +Provide a JSON-encoded string via the `mcp` input. When set, the module writes the value to `~/.codeium/windsurf/mcp_config.json` using a `coder_script` on workspace start. + +The following example configures Devin Desktop to use the GitHub MCP server with authentication facilitated by the [`coder_external_auth`](https://coder.com/docs/admin/external-auth#configure-a-github-oauth-app) resource. + +```tf +module "devin-desktop" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/devin-desktop/coder" + version = "1.0.0" + agent_id = coder_agent.main.id + folder = "/home/coder/project" + mcp = jsonencode({ + mcpServers = { + "github" : { + "url" : "https://api.githubcopilot.com/mcp/", + "headers" : { + "Authorization" : "Bearer ${data.coder_external_auth.github.access_token}", + }, + "type" : "http" + } + + + } + }) +} + +data "coder_external_auth" "github" { + id = "github" +} +``` diff --git a/registry/coder/modules/devin-desktop/main.test.ts b/registry/coder/modules/devin-desktop/main.test.ts new file mode 100644 index 000000000..c8f3fc41b --- /dev/null +++ b/registry/coder/modules/devin-desktop/main.test.ts @@ -0,0 +1,132 @@ +import { describe, expect, it } from "bun:test"; +import { + runTerraformApply, + runTerraformInit, + testRequiredVariables, + runContainer, + execContainer, + removeContainer, + findResourceInstance, + readFileContainer, +} from "~test"; + +describe("devin-desktop", 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.devin_desktop_url.value).toBe( + "windsurf://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.module === "module.vscode-desktop-core" && + res.name === "vscode-desktop", + ); + + expect(coder_app).not.toBeNull(); + expect(coder_app?.instances.length).toBe(1); + expect(coder_app?.instances[0].attributes.order).toBeNull(); + expect(coder_app?.instances[0].attributes.slug).toBe("devin-desktop"); + expect(coder_app?.instances[0].attributes.display_name).toBe( + "Devin Desktop", + ); + }); + + it("adds folder", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + folder: "/foo/bar", + }); + expect(state.outputs.devin_desktop_url.value).toBe( + "windsurf://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.devin_desktop_url.value).toBe( + "windsurf://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", + open_recent: false, + }); + expect(state.outputs.devin_desktop_url.value).toBe( + "windsurf://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.devin_desktop_url.value).toBe( + "windsurf://coder.coder-remote/open?owner=default&workspace=default&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", + ); + }); + + it("allows overriding slug and display_name", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + slug: "devin", + display_name: "Devin", + }); + const coder_app = state.resources.find( + (res) => + res.type === "coder_app" && + res.module === "module.vscode-desktop-core" && + res.name === "vscode-desktop", + ); + expect(coder_app?.instances[0].attributes.slug).toBe("devin"); + expect(coder_app?.instances[0].attributes.display_name).toBe("Devin"); + }); + + it("writes ~/.codeium/windsurf/mcp_config.json when mcp provided", async () => { + const id = await runContainer("alpine"); + try { + const mcp = JSON.stringify({ + servers: { demo: { url: "http://localhost:1234" } }, + }); + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + mcp, + }); + const script = findResourceInstance( + state, + "coder_script", + "devin_desktop_mcp", + ).script; + const resp = await execContainer(id, ["sh", "-c", script]); + if (resp.exitCode !== 0) { + console.log(resp.stdout); + console.log(resp.stderr); + } + expect(resp.exitCode).toBe(0); + const content = await readFileContainer( + id, + "/root/.codeium/windsurf/mcp_config.json", + ); + expect(content).toBe(mcp); + } finally { + await removeContainer(id); + } + }); +}); diff --git a/registry/coder/modules/devin-desktop/main.tf b/registry/coder/modules/devin-desktop/main.tf new file mode 100644 index 000000000..ed196cb4d --- /dev/null +++ b/registry/coder/modules/devin-desktop/main.tf @@ -0,0 +1,110 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 2.5" + } + } +} + +variable "agent_id" { + type = string + description = "The ID of a Coder agent." +} + +variable "folder" { + type = string + description = "The folder to open in Devin Desktop." + 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 +} + +variable "group" { + type = string + description = "The name of a group that this app belongs to." + default = null +} + +variable "slug" { + type = string + description = "The slug of the app." + default = "devin-desktop" +} + +variable "display_name" { + type = string + description = "The display name of the app." + default = "Devin Desktop" +} + +variable "mcp" { + type = string + description = "JSON-encoded string to configure MCP servers for Devin Desktop. When set, writes ~/.codeium/windsurf/mcp_config.json, the path Devin Desktop inherited from Windsurf." + default = "" +} + +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +locals { + mcp_b64 = var.mcp != "" ? base64encode(var.mcp) : "" +} + +# Devin Desktop is Cognition's rebrand of the Windsurf Editor (June 2, 2026), +# which was itself Codeium's rebrand of its original editor. It uses the same +# VS Code Desktop launch mechanism as the windsurf module, so this wraps the +# same shared vscode-desktop-core module with Devin Desktop's branding. +module "vscode-desktop-core" { + source = "registry.coder.com/coder/vscode-desktop-core/coder" + version = "1.0.2" + + agent_id = var.agent_id + + # No dedicated Devin Desktop icon is published in this registry yet, so + # this reuses the Windsurf mark it was rebranded from. + coder_app_icon = "/icon/windsurf.svg" + coder_app_slug = var.slug + coder_app_display_name = var.display_name + coder_app_order = var.order + coder_app_group = var.group + + folder = var.folder + open_recent = var.open_recent + # Devin Desktop is documented as backwards-compatible with Windsurf, so it + # still opens via the windsurf:// URI scheme. + protocol = "windsurf" +} + +resource "coder_script" "devin_desktop_mcp" { + count = var.mcp != "" ? 1 : 0 + agent_id = var.agent_id + display_name = "Devin Desktop MCP" + icon = "/icon/windsurf.svg" + run_on_start = true + start_blocks_login = false + script = <<-EOT + #!/bin/sh + set -eu + mkdir -p "$HOME/.codeium/windsurf" + echo -n "${local.mcp_b64}" | base64 -d > "$HOME/.codeium/windsurf/mcp_config.json" + chmod 600 "$HOME/.codeium/windsurf/mcp_config.json" + EOT +} + +output "devin_desktop_url" { + value = module.vscode-desktop-core.ide_uri + description = "Devin Desktop URL." +} diff --git a/registry/coder/modules/windsurf/README.md b/registry/coder/modules/windsurf/README.md index 4463552f5..b9806a551 100644 --- a/registry/coder/modules/windsurf/README.md +++ b/registry/coder/modules/windsurf/README.md @@ -8,6 +8,11 @@ tags: [ide, windsurf, ai] # Windsurf Editor +> [!IMPORTANT] +> Windsurf Editor was rebranded to Devin Desktop by Cognition on June 2, 2026. New templates should use the +> [`devin-desktop`](https://registry.coder.com/modules/coder/devin-desktop) module instead. This module is kept +> published and fully functional for existing templates that reference it; it is not being removed. + Add a button to open any workspace with a single click in Windsurf Editor. Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder). From 667200aba3c5d833ae07aa5cba6e898c9dcf5c9b Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Mon, 17 Aug 2026 10:23:53 +0000 Subject: [PATCH 02/12] feat: add dedicated devin-desktop icon --- .icons/devin-desktop.svg | 1 + registry/coder/modules/devin-desktop/README.md | 5 ++--- registry/coder/modules/devin-desktop/main.tf | 6 ++---- 3 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 .icons/devin-desktop.svg diff --git a/.icons/devin-desktop.svg b/.icons/devin-desktop.svg new file mode 100644 index 000000000..43148d76c --- /dev/null +++ b/.icons/devin-desktop.svg @@ -0,0 +1 @@ +Devin \ No newline at end of file diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md index 7d21ece8d..8571efc7f 100644 --- a/registry/coder/modules/devin-desktop/README.md +++ b/registry/coder/modules/devin-desktop/README.md @@ -1,7 +1,7 @@ --- display_name: Devin Desktop description: Add a one-click button to launch Devin Desktop (formerly Windsurf Editor) -icon: ../../../../.icons/windsurf.svg +icon: ../../../../.icons/devin-desktop.svg verified: true tags: [ide, devin-desktop, windsurf, ai] --- @@ -11,8 +11,7 @@ tags: [ide, devin-desktop, windsurf, ai] > [!NOTE] > Devin Desktop is Cognition's June 2, 2026 rebrand of the Windsurf Editor (itself a rebrand of Codeium's > original editor). It shipped as an automatic update to existing Windsurf installs, so it reuses Windsurf's -> `windsurf://` deep link protocol and `~/.codeium/windsurf/` config paths. This registry does not have a -> dedicated Devin Desktop icon yet, so this module reuses the Windsurf mark. +> `windsurf://` deep link protocol and `~/.codeium/windsurf/` config paths. Add a button to open any workspace with a single click in Devin Desktop. diff --git a/registry/coder/modules/devin-desktop/main.tf b/registry/coder/modules/devin-desktop/main.tf index ed196cb4d..31fd38ce1 100644 --- a/registry/coder/modules/devin-desktop/main.tf +++ b/registry/coder/modules/devin-desktop/main.tf @@ -73,9 +73,7 @@ module "vscode-desktop-core" { agent_id = var.agent_id - # No dedicated Devin Desktop icon is published in this registry yet, so - # this reuses the Windsurf mark it was rebranded from. - coder_app_icon = "/icon/windsurf.svg" + coder_app_icon = "/icon/devin-desktop.svg" coder_app_slug = var.slug coder_app_display_name = var.display_name coder_app_order = var.order @@ -92,7 +90,7 @@ resource "coder_script" "devin_desktop_mcp" { count = var.mcp != "" ? 1 : 0 agent_id = var.agent_id display_name = "Devin Desktop MCP" - icon = "/icon/windsurf.svg" + icon = "/icon/devin-desktop.svg" run_on_start = true start_blocks_login = false script = <<-EOT From 3b3f8ba2cbb1f312472a314e750e13b22db7fe30 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Mon, 17 Aug 2026 10:34:16 +0000 Subject: [PATCH 03/12] chore: rename devin-desktop icon to devin.svg --- .icons/{devin-desktop.svg => devin.svg} | 0 registry/coder/modules/devin-desktop/README.md | 2 +- registry/coder/modules/devin-desktop/main.tf | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) rename .icons/{devin-desktop.svg => devin.svg} (100%) diff --git a/.icons/devin-desktop.svg b/.icons/devin.svg similarity index 100% rename from .icons/devin-desktop.svg rename to .icons/devin.svg diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md index 8571efc7f..312b3da34 100644 --- a/registry/coder/modules/devin-desktop/README.md +++ b/registry/coder/modules/devin-desktop/README.md @@ -1,7 +1,7 @@ --- display_name: Devin Desktop description: Add a one-click button to launch Devin Desktop (formerly Windsurf Editor) -icon: ../../../../.icons/devin-desktop.svg +icon: ../../../../.icons/devin.svg verified: true tags: [ide, devin-desktop, windsurf, ai] --- diff --git a/registry/coder/modules/devin-desktop/main.tf b/registry/coder/modules/devin-desktop/main.tf index 31fd38ce1..18a8b5cf7 100644 --- a/registry/coder/modules/devin-desktop/main.tf +++ b/registry/coder/modules/devin-desktop/main.tf @@ -73,7 +73,7 @@ module "vscode-desktop-core" { agent_id = var.agent_id - coder_app_icon = "/icon/devin-desktop.svg" + coder_app_icon = "/icon/devin.svg" coder_app_slug = var.slug coder_app_display_name = var.display_name coder_app_order = var.order @@ -90,7 +90,7 @@ resource "coder_script" "devin_desktop_mcp" { count = var.mcp != "" ? 1 : 0 agent_id = var.agent_id display_name = "Devin Desktop MCP" - icon = "/icon/devin-desktop.svg" + icon = "/icon/devin.svg" run_on_start = true start_blocks_login = false script = <<-EOT From cf7be24dc9103e49c8cdae579e20d90a6f783704 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Mon, 17 Aug 2026 10:45:02 +0000 Subject: [PATCH 04/12] chore: use devin tag instead of devin-desktop --- registry/coder/modules/devin-desktop/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md index 312b3da34..d6c46730d 100644 --- a/registry/coder/modules/devin-desktop/README.md +++ b/registry/coder/modules/devin-desktop/README.md @@ -3,7 +3,7 @@ display_name: Devin Desktop description: Add a one-click button to launch Devin Desktop (formerly Windsurf Editor) icon: ../../../../.icons/devin.svg verified: true -tags: [ide, devin-desktop, windsurf, ai] +tags: [ide, devin, windsurf, ai] --- # Devin Desktop From 01abcd9ddaf3132d183e53d95278efc1c958623b Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Mon, 17 Aug 2026 13:32:01 +0000 Subject: [PATCH 05/12] feat: use devin:// as placeholder protocol pending coder/coder support --- .../coder/modules/devin-desktop/README.md | 11 ++++++++-- .../coder/modules/devin-desktop/main.test.ts | 20 ++++++++++++++----- registry/coder/modules/devin-desktop/main.tf | 15 +++++++++++--- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md index d6c46730d..28f10c1c5 100644 --- a/registry/coder/modules/devin-desktop/README.md +++ b/registry/coder/modules/devin-desktop/README.md @@ -10,8 +10,15 @@ tags: [ide, devin, windsurf, ai] > [!NOTE] > Devin Desktop is Cognition's June 2, 2026 rebrand of the Windsurf Editor (itself a rebrand of Codeium's -> original editor). It shipped as an automatic update to existing Windsurf installs, so it reuses Windsurf's -> `windsurf://` deep link protocol and `~/.codeium/windsurf/` config paths. +> original editor). It reuses Windsurf's `~/.codeium/windsurf/` MCP config path. + +> [!IMPORTANT] +> This module defaults to opening Devin Desktop via a `devin://` deep link, a placeholder that has not +> been independently verified against a live Devin Desktop install. Opening `devin://` links also requires +> `"devin:"` to be registered in Coder's `ALLOWED_EXTERNAL_APP_PROTOCOLS` +> ([coder/coder#28214](https://github.com/coder/coder/pull/28214)), so this module should not be tagged/released +> until that ships in a released Coder version. Override the `protocol` input (e.g. back to `"windsurf"`) if +> needed in the meantime. Add a button to open any workspace with a single click in Devin Desktop. diff --git a/registry/coder/modules/devin-desktop/main.test.ts b/registry/coder/modules/devin-desktop/main.test.ts index c8f3fc41b..66d9ad4ee 100644 --- a/registry/coder/modules/devin-desktop/main.test.ts +++ b/registry/coder/modules/devin-desktop/main.test.ts @@ -22,7 +22,7 @@ describe("devin-desktop", async () => { agent_id: "foo", }); expect(state.outputs.devin_desktop_url.value).toBe( - "windsurf://coder.coder-remote/open?owner=default&workspace=default&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", + "devin://coder.coder-remote/open?owner=default&workspace=default&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", ); const coder_app = state.resources.find( @@ -47,7 +47,7 @@ describe("devin-desktop", async () => { folder: "/foo/bar", }); expect(state.outputs.devin_desktop_url.value).toBe( - "windsurf://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", + "devin://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", ); }); @@ -58,7 +58,7 @@ describe("devin-desktop", async () => { open_recent: true, }); expect(state.outputs.devin_desktop_url.value).toBe( - "windsurf://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", + "devin://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", ); }); @@ -69,7 +69,7 @@ describe("devin-desktop", async () => { open_recent: false, }); expect(state.outputs.devin_desktop_url.value).toBe( - "windsurf://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", + "devin://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", ); }); @@ -79,7 +79,17 @@ describe("devin-desktop", async () => { open_recent: true, }); expect(state.outputs.devin_desktop_url.value).toBe( - "windsurf://coder.coder-remote/open?owner=default&workspace=default&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", + "devin://coder.coder-remote/open?owner=default&workspace=default&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", + ); + }); + + it("allows overriding protocol", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + protocol: "windsurf", + }); + expect(state.outputs.devin_desktop_url.value).toBe( + "windsurf://coder.coder-remote/open?owner=default&workspace=default&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", ); }); diff --git a/registry/coder/modules/devin-desktop/main.tf b/registry/coder/modules/devin-desktop/main.tf index 18a8b5cf7..ba34113d2 100644 --- a/registry/coder/modules/devin-desktop/main.tf +++ b/registry/coder/modules/devin-desktop/main.tf @@ -56,6 +56,12 @@ variable "mcp" { default = "" } +variable "protocol" { + type = string + description = "The URI protocol used to open Devin Desktop. Defaults to the devin:// scheme; override this if Cognition ships Devin Desktop under a different scheme before this default is updated." + default = "devin" +} + data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} @@ -81,9 +87,12 @@ module "vscode-desktop-core" { folder = var.folder open_recent = var.open_recent - # Devin Desktop is documented as backwards-compatible with Windsurf, so it - # still opens via the windsurf:// URI scheme. - protocol = "windsurf" + # Placeholder: devin:// is not independently verified against a live + # Devin Desktop install. Requires registering "devin:" in coder/coder's + # ALLOWED_EXTERNAL_APP_PROTOCOLS (site/src/modules/apps/apps.ts) and a + # released Coder version with that change before this module is usable + # end to end; do not release/tag this module until that ships. + protocol = var.protocol } resource "coder_script" "devin_desktop_mcp" { From d4476a150cc493b9203c5d619c33b8fd7c2443a1 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Tue, 18 Aug 2026 10:35:25 +0000 Subject: [PATCH 06/12] fix: address review feedback - drop windsurf tag from devin-desktop (already covered by devin/ide/ai) - drop rebrand-history/placeholder admonitions from devin-desktop README now that devin:// has been hands-on verified against a live install - bump windsurf module to 1.3.2 (patch) for the deprecation-notice README change --- registry/coder/modules/devin-desktop/README.md | 14 +------------- registry/coder/modules/devin-desktop/main.tf | 9 +++------ registry/coder/modules/windsurf/README.md | 6 +++--- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md index 28f10c1c5..0867536a5 100644 --- a/registry/coder/modules/devin-desktop/README.md +++ b/registry/coder/modules/devin-desktop/README.md @@ -3,23 +3,11 @@ display_name: Devin Desktop description: Add a one-click button to launch Devin Desktop (formerly Windsurf Editor) icon: ../../../../.icons/devin.svg verified: true -tags: [ide, devin, windsurf, ai] +tags: [ide, devin, ai] --- # Devin Desktop -> [!NOTE] -> Devin Desktop is Cognition's June 2, 2026 rebrand of the Windsurf Editor (itself a rebrand of Codeium's -> original editor). It reuses Windsurf's `~/.codeium/windsurf/` MCP config path. - -> [!IMPORTANT] -> This module defaults to opening Devin Desktop via a `devin://` deep link, a placeholder that has not -> been independently verified against a live Devin Desktop install. Opening `devin://` links also requires -> `"devin:"` to be registered in Coder's `ALLOWED_EXTERNAL_APP_PROTOCOLS` -> ([coder/coder#28214](https://github.com/coder/coder/pull/28214)), so this module should not be tagged/released -> until that ships in a released Coder version. Override the `protocol` input (e.g. back to `"windsurf"`) if -> needed in the meantime. - Add a button to open any workspace with a single click in Devin Desktop. Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder). diff --git a/registry/coder/modules/devin-desktop/main.tf b/registry/coder/modules/devin-desktop/main.tf index ba34113d2..18229ef4c 100644 --- a/registry/coder/modules/devin-desktop/main.tf +++ b/registry/coder/modules/devin-desktop/main.tf @@ -58,7 +58,7 @@ variable "mcp" { variable "protocol" { type = string - description = "The URI protocol used to open Devin Desktop. Defaults to the devin:// scheme; override this if Cognition ships Devin Desktop under a different scheme before this default is updated." + description = "The URI protocol used to open Devin Desktop. Defaults to the devin:// scheme." default = "devin" } @@ -87,11 +87,8 @@ module "vscode-desktop-core" { folder = var.folder open_recent = var.open_recent - # Placeholder: devin:// is not independently verified against a live - # Devin Desktop install. Requires registering "devin:" in coder/coder's - # ALLOWED_EXTERNAL_APP_PROTOCOLS (site/src/modules/apps/apps.ts) and a - # released Coder version with that change before this module is usable - # end to end; do not release/tag this module until that ships. + # devin:// is registered as an external app protocol in coder/coder + # (ALLOWED_EXTERNAL_APP_PROTOCOLS, coder/coder#28214). protocol = var.protocol } diff --git a/registry/coder/modules/windsurf/README.md b/registry/coder/modules/windsurf/README.md index b9806a551..f52cf1795 100644 --- a/registry/coder/modules/windsurf/README.md +++ b/registry/coder/modules/windsurf/README.md @@ -21,7 +21,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder) module "windsurf" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/windsurf/coder" - version = "1.3.1" + version = "1.3.2" agent_id = coder_agent.main.id } ``` @@ -34,7 +34,7 @@ module "windsurf" { module "windsurf" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/windsurf/coder" - version = "1.3.1" + version = "1.3.2" agent_id = coder_agent.main.id folder = "/home/coder/project" } @@ -50,7 +50,7 @@ The following example configures Windsurf to use the GitHub MCP server with auth module "windsurf" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/windsurf/coder" - version = "1.3.1" + version = "1.3.2" agent_id = coder_agent.main.id folder = "/home/coder/project" mcp = jsonencode({ From 8b09d61723705a21ff51e31fa8f79e9ebe8d38f6 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Tue, 18 Aug 2026 10:38:02 +0000 Subject: [PATCH 07/12] chore: bump devin-desktop to v1.0.1 per version-bump CI --- registry/coder/modules/devin-desktop/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md index 0867536a5..b0e5eebdc 100644 --- a/registry/coder/modules/devin-desktop/README.md +++ b/registry/coder/modules/devin-desktop/README.md @@ -16,7 +16,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder) module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "1.0.0" + version = "1.0.1" agent_id = coder_agent.main.id } ``` @@ -29,7 +29,7 @@ module "devin-desktop" { module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "1.0.0" + version = "1.0.1" agent_id = coder_agent.main.id folder = "/home/coder/project" } @@ -45,7 +45,7 @@ The following example configures Devin Desktop to use the GitHub MCP server with module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "1.0.0" + version = "1.0.1" agent_id = coder_agent.main.id folder = "/home/coder/project" mcp = jsonencode({ From 12f44023e0cf4b3b970a9eb310c18b28eba0c0f9 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Tue, 18 Aug 2026 10:40:49 +0000 Subject: [PATCH 08/12] chore: revert devin-desktop to v1.0.0 (initial release, no prior tag to bump from) --- registry/coder/modules/devin-desktop/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md index b0e5eebdc..0867536a5 100644 --- a/registry/coder/modules/devin-desktop/README.md +++ b/registry/coder/modules/devin-desktop/README.md @@ -16,7 +16,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder) module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "1.0.1" + version = "1.0.0" agent_id = coder_agent.main.id } ``` @@ -29,7 +29,7 @@ module "devin-desktop" { module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "1.0.1" + version = "1.0.0" agent_id = coder_agent.main.id folder = "/home/coder/project" } @@ -45,7 +45,7 @@ The following example configures Devin Desktop to use the GitHub MCP server with module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "1.0.1" + version = "1.0.0" agent_id = coder_agent.main.id folder = "/home/coder/project" mcp = jsonencode({ From 20bd191ee7c66d9ed930ebd4f1df3d7475378ae2 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Tue, 18 Aug 2026 10:43:19 +0000 Subject: [PATCH 09/12] chore: start devin-desktop version at 0.1.0 --- registry/coder/modules/devin-desktop/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md index 0867536a5..53b356354 100644 --- a/registry/coder/modules/devin-desktop/README.md +++ b/registry/coder/modules/devin-desktop/README.md @@ -16,7 +16,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder) module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "1.0.0" + version = "0.1.0" agent_id = coder_agent.main.id } ``` @@ -29,7 +29,7 @@ module "devin-desktop" { module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "1.0.0" + version = "0.1.0" agent_id = coder_agent.main.id folder = "/home/coder/project" } @@ -45,7 +45,7 @@ The following example configures Devin Desktop to use the GitHub MCP server with module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "1.0.0" + version = "0.1.0" agent_id = coder_agent.main.id folder = "/home/coder/project" mcp = jsonencode({ From 76493172ef3af1a914e7a35fcd42d29ae4f5e46a Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Tue, 18 Aug 2026 10:51:04 +0000 Subject: [PATCH 10/12] fix: drop protocol override, move MCP config to ~/.config/devin - protocol input is unnecessary now that devin:// is confirmed working; hardcode it directly - write MCP config to the new ~/.config/devin/mcp_config.json location instead of the inherited ~/.codeium/windsurf/ path --- registry/coder/modules/devin-desktop/README.md | 2 +- .../coder/modules/devin-desktop/main.test.ts | 14 ++------------ registry/coder/modules/devin-desktop/main.tf | 16 +++++----------- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md index 53b356354..517c3dcc8 100644 --- a/registry/coder/modules/devin-desktop/README.md +++ b/registry/coder/modules/devin-desktop/README.md @@ -37,7 +37,7 @@ module "devin-desktop" { ### Configure MCP servers for Devin Desktop -Provide a JSON-encoded string via the `mcp` input. When set, the module writes the value to `~/.codeium/windsurf/mcp_config.json` using a `coder_script` on workspace start. +Provide a JSON-encoded string via the `mcp` input. When set, the module writes the value to `~/.config/devin/mcp_config.json` using a `coder_script` on workspace start. The following example configures Devin Desktop to use the GitHub MCP server with authentication facilitated by the [`coder_external_auth`](https://coder.com/docs/admin/external-auth#configure-a-github-oauth-app) resource. diff --git a/registry/coder/modules/devin-desktop/main.test.ts b/registry/coder/modules/devin-desktop/main.test.ts index 66d9ad4ee..11ad905d9 100644 --- a/registry/coder/modules/devin-desktop/main.test.ts +++ b/registry/coder/modules/devin-desktop/main.test.ts @@ -83,16 +83,6 @@ describe("devin-desktop", async () => { ); }); - it("allows overriding protocol", async () => { - const state = await runTerraformApply(import.meta.dir, { - agent_id: "foo", - protocol: "windsurf", - }); - expect(state.outputs.devin_desktop_url.value).toBe( - "windsurf://coder.coder-remote/open?owner=default&workspace=default&url=https://mydeployment.coder.com&token=$SESSION_TOKEN", - ); - }); - it("allows overriding slug and display_name", async () => { const state = await runTerraformApply(import.meta.dir, { agent_id: "foo", @@ -109,7 +99,7 @@ describe("devin-desktop", async () => { expect(coder_app?.instances[0].attributes.display_name).toBe("Devin"); }); - it("writes ~/.codeium/windsurf/mcp_config.json when mcp provided", async () => { + it("writes ~/.config/devin/mcp_config.json when mcp provided", async () => { const id = await runContainer("alpine"); try { const mcp = JSON.stringify({ @@ -132,7 +122,7 @@ describe("devin-desktop", async () => { expect(resp.exitCode).toBe(0); const content = await readFileContainer( id, - "/root/.codeium/windsurf/mcp_config.json", + "/root/.config/devin/mcp_config.json", ); expect(content).toBe(mcp); } finally { diff --git a/registry/coder/modules/devin-desktop/main.tf b/registry/coder/modules/devin-desktop/main.tf index 18229ef4c..8a76f5436 100644 --- a/registry/coder/modules/devin-desktop/main.tf +++ b/registry/coder/modules/devin-desktop/main.tf @@ -52,16 +52,10 @@ variable "display_name" { variable "mcp" { type = string - description = "JSON-encoded string to configure MCP servers for Devin Desktop. When set, writes ~/.codeium/windsurf/mcp_config.json, the path Devin Desktop inherited from Windsurf." + description = "JSON-encoded string to configure MCP servers for Devin Desktop. When set, writes ~/.config/devin/mcp_config.json." default = "" } -variable "protocol" { - type = string - description = "The URI protocol used to open Devin Desktop. Defaults to the devin:// scheme." - default = "devin" -} - data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} @@ -89,7 +83,7 @@ module "vscode-desktop-core" { open_recent = var.open_recent # devin:// is registered as an external app protocol in coder/coder # (ALLOWED_EXTERNAL_APP_PROTOCOLS, coder/coder#28214). - protocol = var.protocol + protocol = "devin" } resource "coder_script" "devin_desktop_mcp" { @@ -102,9 +96,9 @@ resource "coder_script" "devin_desktop_mcp" { script = <<-EOT #!/bin/sh set -eu - mkdir -p "$HOME/.codeium/windsurf" - echo -n "${local.mcp_b64}" | base64 -d > "$HOME/.codeium/windsurf/mcp_config.json" - chmod 600 "$HOME/.codeium/windsurf/mcp_config.json" + mkdir -p "$HOME/.config/devin" + echo -n "${local.mcp_b64}" | base64 -d > "$HOME/.config/devin/mcp_config.json" + chmod 600 "$HOME/.config/devin/mcp_config.json" EOT } From 7cf38d97cdb9512b8a69fab71a0cbd7f15151444 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Tue, 18 Aug 2026 10:54:09 +0000 Subject: [PATCH 11/12] chore: revert devin-desktop to v1.0.0 --- registry/coder/modules/devin-desktop/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/coder/modules/devin-desktop/README.md b/registry/coder/modules/devin-desktop/README.md index 517c3dcc8..85927e8b5 100644 --- a/registry/coder/modules/devin-desktop/README.md +++ b/registry/coder/modules/devin-desktop/README.md @@ -16,7 +16,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder) module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "0.1.0" + version = "1.0.0" agent_id = coder_agent.main.id } ``` @@ -29,7 +29,7 @@ module "devin-desktop" { module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "0.1.0" + version = "1.0.0" agent_id = coder_agent.main.id folder = "/home/coder/project" } @@ -45,7 +45,7 @@ The following example configures Devin Desktop to use the GitHub MCP server with module "devin-desktop" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/devin-desktop/coder" - version = "0.1.0" + version = "1.0.0" agent_id = coder_agent.main.id folder = "/home/coder/project" mcp = jsonencode({ From 0689946ce8fd8828d8d5dd7059b94d4c1b28b2d8 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Wed, 19 Aug 2026 09:40:51 +0000 Subject: [PATCH 12/12] test(registry/devin-desktop): raise mcp config test timeout to 10s The Docker pull and container exec for the alpine-based MCP config test can exceed bun's 5000ms default test timeout on CI runners, matching the same override already used by the antigravity and vscode-desktop-core module tests. --- registry/coder/modules/devin-desktop/main.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder/modules/devin-desktop/main.test.ts b/registry/coder/modules/devin-desktop/main.test.ts index 11ad905d9..24d4e57e9 100644 --- a/registry/coder/modules/devin-desktop/main.test.ts +++ b/registry/coder/modules/devin-desktop/main.test.ts @@ -128,5 +128,5 @@ describe("devin-desktop", async () => { } finally { await removeContainer(id); } - }); + }, 10000); });