Skip to content

Commit e13e7b5

Browse files
Add Kiro IDE module (#232)
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com> Co-authored-by: matifali <[email protected]> Co-authored-by: Atif Ali <[email protected]>
1 parent b446173 commit e13e7b5

File tree

4 files changed

+226
-0
lines changed

4 files changed

+226
-0
lines changed

.icons/kiro.svg

Lines changed: 1 addition & 0 deletions
Loading

registry/coder/modules/kiro/README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
display_name: Kiro IDE
3+
description: Add a one-click button to launch Kiro IDE
4+
icon: ../../../../.icons/kiro.svg
5+
verified: true
6+
tags: [ide, kiro, ai, aws]
7+
---
8+
9+
# Kiro IDE
10+
11+
Add a button to open any workspace with a single click in [Kiro IDE](https://kiro.dev).
12+
13+
Kiro is an AI-powered IDE from AWS that helps developers build from concept to production with spec-driven development, featuring AI agents, hooks, and steering files.
14+
15+
Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder) and [open-remote-ssh extension](https://open-vsx.org/extension/jeanp413/open-remote-ssh) for establishing connections to Coder workspaces.
16+
17+
```tf
18+
module "kiro" {
19+
count = data.coder_workspace.me.start_count
20+
source = "registry.coder.com/coder/kiro/coder"
21+
version = "1.0.0"
22+
agent_id = coder_agent.example.id
23+
}
24+
```
25+
26+
## Examples
27+
28+
### Open in a specific directory
29+
30+
```tf
31+
module "kiro" {
32+
count = data.coder_workspace.me.start_count
33+
source = "registry.coder.com/coder/kiro/coder"
34+
version = "1.0.0"
35+
agent_id = coder_agent.example.id
36+
folder = "/home/coder/project"
37+
}
38+
```
39+
40+
### Open with custom display name and order
41+
42+
```tf
43+
module "kiro" {
44+
count = data.coder_workspace.me.start_count
45+
source = "registry.coder.com/coder/kiro/coder"
46+
version = "1.0.0"
47+
agent_id = coder_agent.example.id
48+
display_name = "Kiro AI IDE"
49+
order = 1
50+
}
51+
```
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { describe, expect, it } from "bun:test";
2+
import {
3+
runTerraformApply,
4+
runTerraformInit,
5+
testRequiredVariables,
6+
} from "~test";
7+
8+
describe("kiro", async () => {
9+
await runTerraformInit(import.meta.dir);
10+
11+
testRequiredVariables(import.meta.dir, {
12+
agent_id: "foo",
13+
});
14+
15+
it("default output", async () => {
16+
const state = await runTerraformApply(import.meta.dir, {
17+
agent_id: "foo",
18+
});
19+
expect(state.outputs.kiro_url.value).toBe(
20+
"kiro://coder.coder-remote/open?owner=default&workspace=default&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
21+
);
22+
23+
const coder_app = state.resources.find(
24+
(res) => res.type === "coder_app" && res.name === "kiro",
25+
);
26+
27+
expect(coder_app).not.toBeNull();
28+
expect(coder_app?.instances.length).toBe(1);
29+
expect(coder_app?.instances[0].attributes.order).toBeNull();
30+
});
31+
32+
it("adds folder", async () => {
33+
const state = await runTerraformApply(import.meta.dir, {
34+
agent_id: "foo",
35+
folder: "/foo/bar",
36+
});
37+
expect(state.outputs.kiro_url.value).toBe(
38+
"kiro://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
39+
);
40+
});
41+
42+
it("adds folder and open_recent", async () => {
43+
const state = await runTerraformApply(import.meta.dir, {
44+
agent_id: "foo",
45+
folder: "/foo/bar",
46+
open_recent: "true",
47+
});
48+
expect(state.outputs.kiro_url.value).toBe(
49+
"kiro://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
50+
);
51+
});
52+
53+
it("custom slug and display_name", async () => {
54+
const state = await runTerraformApply(import.meta.dir, {
55+
agent_id: "foo",
56+
slug: "kiro-ai",
57+
display_name: "Kiro AI IDE",
58+
});
59+
60+
const coder_app = state.resources.find(
61+
(res) => res.type === "coder_app" && res.name === "kiro",
62+
);
63+
64+
expect(coder_app?.instances[0].attributes.slug).toBe("kiro-ai");
65+
expect(coder_app?.instances[0].attributes.display_name).toBe("Kiro AI IDE");
66+
});
67+
68+
it("sets order", async () => {
69+
const state = await runTerraformApply(import.meta.dir, {
70+
agent_id: "foo",
71+
order: "5",
72+
});
73+
74+
const coder_app = state.resources.find(
75+
(res) => res.type === "coder_app" && res.name === "kiro",
76+
);
77+
78+
expect(coder_app?.instances[0].attributes.order).toBe(5);
79+
});
80+
81+
it("sets group", async () => {
82+
const state = await runTerraformApply(import.meta.dir, {
83+
agent_id: "foo",
84+
group: "AI IDEs",
85+
});
86+
87+
const coder_app = state.resources.find(
88+
(res) => res.type === "coder_app" && res.name === "kiro",
89+
);
90+
91+
expect(coder_app?.instances[0].attributes.group).toBe("AI IDEs");
92+
});
93+
});

registry/coder/modules/kiro/main.tf

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
terraform {
2+
required_version = ">= 1.0"
3+
4+
required_providers {
5+
coder = {
6+
source = "coder/coder"
7+
version = ">= 2.5"
8+
}
9+
}
10+
}
11+
12+
variable "agent_id" {
13+
type = string
14+
description = "The ID of a Coder agent."
15+
}
16+
17+
variable "folder" {
18+
type = string
19+
description = "The folder to open in Kiro IDE."
20+
default = ""
21+
}
22+
23+
variable "open_recent" {
24+
type = bool
25+
description = "Open the most recent workspace or folder. Falls back to the folder if there is no recent workspace or folder to open."
26+
default = false
27+
}
28+
29+
variable "order" {
30+
type = number
31+
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)."
32+
default = null
33+
}
34+
35+
variable "group" {
36+
type = string
37+
description = "The name of a group that this app belongs to."
38+
default = null
39+
}
40+
41+
variable "slug" {
42+
type = string
43+
description = "The slug of the app."
44+
default = "kiro"
45+
}
46+
47+
variable "display_name" {
48+
type = string
49+
description = "The display name of the app."
50+
default = "Kiro IDE"
51+
}
52+
53+
data "coder_workspace" "me" {}
54+
data "coder_workspace_owner" "me" {}
55+
56+
resource "coder_app" "kiro" {
57+
agent_id = var.agent_id
58+
external = true
59+
icon = "/icon/kiro.svg"
60+
slug = var.slug
61+
display_name = var.display_name
62+
order = var.order
63+
group = var.group
64+
url = join("", [
65+
"kiro://coder.coder-remote/open",
66+
"?owner=",
67+
data.coder_workspace_owner.me.name,
68+
"&workspace=",
69+
data.coder_workspace.me.name,
70+
var.folder != "" ? join("", ["&folder=", var.folder]) : "",
71+
var.open_recent ? "&openRecent" : "",
72+
"&url=",
73+
data.coder_workspace.me.access_url,
74+
"&token=$SESSION_TOKEN",
75+
])
76+
}
77+
78+
output "kiro_url" {
79+
value = coder_app.kiro.url
80+
description = "Kiro IDE URL."
81+
}

0 commit comments

Comments
 (0)