Compare commits

..

36 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
Hugo Dutka 8ba4c323c2 fix(claude-code): workaround for a coder bug (#283)
Workaround to address https://github.com/coder/coder/issues/18776
2025-08-02 16:21:13 +02:00
Phorcys 3afa72095b chore: polish some modules readme (#272) 2025-08-01 21:12:05 -05:00
Michael Smith cf66809349 fix: update HCP vault links to use current URL patterns (#275)
Realized this was an issue while fixing how we're rendering GFM alerts
on the Registry website.

## Description

Basically, the URLs we're using right now are technically valid, but
they were using the old URL pattern from before we created the
`coder/registry` repo. The Registry website has logic to handle
redirects for these, but we should avoid triggering it as it adds
unnecessary entries to the user's browser history.

### Changes made
- Updated all Registry links in the HCP Vault alert to include `coder`
as the namespace

## Type of Change

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

## Testing & Validation

- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun run fmt`)
- [x] Changes tested locally
2025-07-31 19:50:37 -05:00
Michael Smith 020a2cba79 fix: update icon path for k8s-username (#276)
## Description

This is an issue that doesn't exist within `coder/registry`, but was
breaking our build process for the Registry website. We were using an
invalid image path.

## Type of Change

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

## Testing & Validation

- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun run fmt`)
- [x] Changes tested locally
2025-07-31 20:58:06 +01:00
Eric Paulsen 3fd7b47097 feat: dynamic username template (#261)
## Description

this PR adds a new template that creates & runs Coder workspaces on K8s
with the user's Coder `username` as the Linux UID. a commonly requested
use-case by customers.

## Type of Change

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

## Module Information

<!-- Delete this section if not applicable -->

**Path:** `registry/ericpaulsen/templates/k8s-pod-username.tf`  

## Testing & Validation

- [x] Changes tested locally
2025-07-31 14:25:29 +00:00
Atif Ali e1f077dac3 chore: deploy registry changes nightly (#264) 2025-07-30 22:33:25 -04:00
Marcin Tojek 29c52b7072 feat: jupyter-notebook: preinstall Python packages (#263) 2025-07-30 20:25:53 -05:00
Hugo Dutka 312cb71bf0 chore: bump agentapi version in the claude code module (#265)
Bump agentapi to v0.3.0 and claude code module version.
2025-07-30 13:37:30 +02:00
35C4n0r f89ea12d9e feat: gemini cli module (#246)
Closes #237
/claim #237

## Description

~https://www.loom.com/share/5b099c73935f4f87b8fdafe1509bb79d?sid=7fea43d6-86e9-45ae-9892-efeb3c820b82~
Updated:
https://www.loom.com/share/62e907eae8544d8cbbe560d7f63bd02d?sid=201212fa-eb58-44b5-8706-8bf9c2c37433
<!-- Briefly describe what this PR does and why -->

## Type of Change

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

## Module Information

<!-- Delete this section if not applicable -->

**Path:** `registry/coder-labs/modules/gemini`  
**New version:** `v1.0.0`  
**Breaking change:** [ ] Yes [ ] No

## Testing & Validation

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

## Related Issues

<!-- Link related issues or write "None" if not applicable -->

---------

Co-authored-by: Atif Ali <me@matifali.dev>
Co-authored-by: Hugo Dutka <dutkahugo@gmail.com>
Co-authored-by: DevCats <christofer@coder.com>
2025-07-29 05:26:30 -05:00
dependabot[bot] 0fe47943aa chore(deps): bump google-github-actions/auth from 2.1.10 to 2.1.11 (#255)
Bumps
[google-github-actions/auth](https://github.com/google-github-actions/auth)
from 2.1.10 to 2.1.11.
<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.11</h2>
<h2>What's Changed</h2>
<ul>
<li>Update troubleshooting docs for Python by <a
href="https://github.com/sethvargo"><code>@​sethvargo</code></a> in <a
href="https://redirect.github.com/google-github-actions/auth/pull/488">google-github-actions/auth#488</a></li>
<li>Add linters by <a
href="https://github.com/sethvargo"><code>@​sethvargo</code></a> in <a
href="https://redirect.github.com/google-github-actions/auth/pull/499">google-github-actions/auth#499</a></li>
<li>Update deps by <a
href="https://github.com/sethvargo"><code>@​sethvargo</code></a> in <a
href="https://redirect.github.com/google-github-actions/auth/pull/500">google-github-actions/auth#500</a></li>
<li>Release: v2.1.11 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/501">google-github-actions/auth#501</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/google-github-actions/auth/compare/v2.1.10...v2.1.11">https://github.com/google-github-actions/auth/compare/v2.1.10...v2.1.11</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/google-github-actions/auth/commit/140bb5113ffb6b65a7e9b937a81fa96cf5064462"><code>140bb51</code></a>
Release: v2.1.11 (<a
href="https://redirect.github.com/google-github-actions/auth/issues/501">#501</a>)</li>
<li><a
href="https://github.com/google-github-actions/auth/commit/ab3132e2ad698521ee1355566103fa838732e48c"><code>ab3132e</code></a>
Update deps (<a
href="https://redirect.github.com/google-github-actions/auth/issues/500">#500</a>)</li>
<li><a
href="https://github.com/google-github-actions/auth/commit/25b96bac992fdf64486c6fd3fd3d9c4cddb3a812"><code>25b96ba</code></a>
Add linters (<a
href="https://redirect.github.com/google-github-actions/auth/issues/499">#499</a>)</li>
<li><a
href="https://github.com/google-github-actions/auth/commit/0920706a19e9d22c3d0da43d1db5939c6ad837a8"><code>0920706</code></a>
Update troubleshooting docs for Python (<a
href="https://redirect.github.com/google-github-actions/auth/issues/488">#488</a>)</li>
<li>See full diff in <a
href="https://github.com/google-github-actions/auth/compare/ba79af03959ebeac9769e648f473a284504d9193...140bb5113ffb6b65a7e9b937a81fa96cf5064462">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.10&new-version=2.1.11)](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-07-28 18:17:31 -05:00
dependabot[bot] 4f225fd7d3 chore(deps): bump google-github-actions/setup-gcloud from 2.1.4 to 2.1.5 (#256)
Bumps
[google-github-actions/setup-gcloud](https://github.com/google-github-actions/setup-gcloud)
from 2.1.4 to 2.1.5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/google-github-actions/setup-gcloud/releases">google-github-actions/setup-gcloud's
releases</a>.</em></p>
<blockquote>
<h2>v2.1.5</h2>
<h2>What's Changed</h2>
<ul>
<li>security: bump undici from 5.28.5 to 5.29.0 in the npm_and_yarn
group by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/google-github-actions/setup-gcloud/pull/711">google-github-actions/setup-gcloud#711</a></li>
<li>Update linters by <a
href="https://github.com/sethvargo"><code>@​sethvargo</code></a> in <a
href="https://redirect.github.com/google-github-actions/setup-gcloud/pull/715">google-github-actions/setup-gcloud#715</a></li>
<li>Update deps by <a
href="https://github.com/sethvargo"><code>@​sethvargo</code></a> in <a
href="https://redirect.github.com/google-github-actions/setup-gcloud/pull/716">google-github-actions/setup-gcloud#716</a></li>
<li>Release: v2.1.5 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/setup-gcloud/pull/717">google-github-actions/setup-gcloud#717</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/google-github-actions/setup-gcloud/compare/v2.1.4...v2.1.5">https://github.com/google-github-actions/setup-gcloud/compare/v2.1.4...v2.1.5</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/google-github-actions/setup-gcloud/commit/6a7c903a70c8625ed6700fa299f5ddb4ca6022e9"><code>6a7c903</code></a>
Release: v2.1.5 (<a
href="https://redirect.github.com/google-github-actions/setup-gcloud/issues/717">#717</a>)</li>
<li><a
href="https://github.com/google-github-actions/setup-gcloud/commit/e838bc6edfe3907980c74d5aad506fd6e173b0d6"><code>e838bc6</code></a>
Update deps (<a
href="https://redirect.github.com/google-github-actions/setup-gcloud/issues/716">#716</a>)</li>
<li><a
href="https://github.com/google-github-actions/setup-gcloud/commit/98d8f78fcc2354c736499a506ad9e7be3f4c2640"><code>98d8f78</code></a>
Update linters (<a
href="https://redirect.github.com/google-github-actions/setup-gcloud/issues/715">#715</a>)</li>
<li><a
href="https://github.com/google-github-actions/setup-gcloud/commit/a8b58010a5b2a061afd605f50e88629c9ec7536b"><code>a8b5801</code></a>
security: bump undici from 5.28.5 to 5.29.0 in the npm_and_yarn group
(<a
href="https://redirect.github.com/google-github-actions/setup-gcloud/issues/711">#711</a>)</li>
<li>See full diff in <a
href="https://github.com/google-github-actions/setup-gcloud/compare/77e7a554d41e2ee56fc945c52dfd3f33d12def9a...6a7c903a70c8625ed6700fa299f5ddb4ca6022e9">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google-github-actions/setup-gcloud&package-manager=github_actions&previous-version=2.1.4&new-version=2.1.5)](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-07-28 18:13:18 -05:00
35C4n0r f04d7d2808 feat: tmux module (#229)
Closes #203
/claim #203

## Description

Introduce the `tmux` module

## Demo

https://www.loom.com/share/ec8169d34c3043f7af2163b1a1a14a4b?sid=1ea8bcb2-3db0-43ca-965a-5ed42eec3448

## Type of Change

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

## Module Information

<!-- Delete this section if not applicable -->

**Path:** `registry/anomaly/modules/tmux`  
**New version:** `v1.0.0`  
**Breaking change:** [ ] Yes [x] No

## Testing & Validation

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

## Related Issues
#203
2025-07-24 20:31:57 -05:00
DevCats 4ae6370bcf feat(tag_release): add script for automatically tagging and releasing modules (#250)
## Description

This PR introduces a script `.github/scripts/tag_release.sh` which
allows the maintainer and other org members to automatically tag and
release modules based on the checked out commit id. This script relies
on the README's for the updated modules to accurately reflect the
version bump to work properly.
<!-- Briefly describe what this PR does and why -->

## Type of Change

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

## Testing & Validation

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

## Reference

Run on this Commit:
https://github.com/coder/registry/commit/9ed5084bfbad9266469a9d189635d7fccb1ed277

### Script Output:

```
coder@tagging-test:~/workspace/registry$ ./.github/scripts/tag_release.sh 
🚀 Coder Registry Tag Release Script
Operating on commit: 9ed5084bfb

🔍 Scanning all modules for missing release tags...

find: warning: you have specified the global option -mindepth after the argument -type, but global options are not positional, i.e., -mindepth affects tests specified before it as well as those specified after it.  Please specify global options before other arguments.
find: warning: you have specified the global option -maxdepth after the argument -type, but global options are not positional, i.e., -maxdepth affects tests specified before it as well as those specified after it.  Please specify global options before other arguments.
📦 coder/agentapi: v1.0.1 (needs tag)
📦 coder/aider: v1.1.1 (needs tag)
📦 coder/amazon-dcv-windows: v1.1.1 (needs tag)
📦 coder/amazon-q: v1.1.1 (needs tag)
📦 coder/aws-region: v1.0.31 (needs tag)
📦 coder/azure-region: v1.0.31 (needs tag)
 coder/claude-code: v2.0.3 (already tagged)
📦 coder/coder-login: v1.0.31 (needs tag)
📦 coder/code-server: v1.3.1 (needs tag)
📦 coder/cursor: v1.2.1 (needs tag)
📦 coder/devcontainers-cli: v1.0.31 (needs tag)
📦 coder/dotfiles: v1.2.1 (needs tag)
📦 coder/filebrowser: v1.1.2 (needs tag)
📦 coder/fly-region: v1.0.31 (needs tag)
📦 coder/gcp-region: v1.0.31 (needs tag)
📦 coder/git-clone: v1.1.1 (needs tag)
📦 coder/git-commit-signing: v1.0.31 (needs tag)
📦 coder/git-config: v1.0.31 (needs tag)
📦 coder/github-upload-public-key: v1.0.31 (needs tag)
📦 coder/goose: v2.0.1 (needs tag)
📦 coder/hcp-vault-secrets: v1.0.33 (needs tag)
📦 coder/jetbrains: v1.0.1 (needs tag)
 coder/jetbrains-fleet: v1.0.1 (already tagged)
📦 coder/jetbrains-gateway: v1.2.2 (needs tag)
📦 coder/jfrog-oauth: v1.0.31 (needs tag)
📦 coder/jfrog-token: v1.0.31 (needs tag)
📦 coder/jupyterlab: v1.1.1 (needs tag)
📦 coder/jupyter-notebook: v1.1.1 (needs tag)
📦 coder/kasmvnc: v1.2.1 (needs tag)
 coder/kiro: v1.0.0 (already tagged)
📦 coder/local-windows-rdp: v1.0.2 (needs tag)
📦 coder/personalize: v1.0.31 (needs tag)
📦 coder/slackme: v1.0.31 (needs tag)
📦 coder/vault-github: v1.0.31 (needs tag)
📦 coder/vault-jwt: v1.1.1 (needs tag)
📦 coder/vault-token: v1.2.1 (needs tag)
📦 coder/vscode-desktop: v1.1.1 (needs tag)
📦 coder/vscode-web: v1.3.1 (needs tag)
📦 coder/windows-rdp: v1.2.3 (needs tag)
📦 coder/windsurf: v1.1.1 (needs tag)
📦 coder/zed: v1.0.1 (needs tag)
 nataindata/apache-airflow: v1.0.14 (already tagged)
 thezoker/nodejs: v1.0.11 (already tagged)
 whizus/exoscale-instance-type: v1.0.13 (already tagged)
 whizus/exoscale-zone: v1.0.13 (already tagged)

📊 Summary: 38 of 45 modules need tagging

## Tags to be created:
- `release/coder/agentapi/v1.0.1`
- `release/coder/aider/v1.1.1`
- `release/coder/amazon-dcv-windows/v1.1.1`
- `release/coder/amazon-q/v1.1.1`
- `release/coder/aws-region/v1.0.31`
- `release/coder/azure-region/v1.0.31`
- `release/coder/coder-login/v1.0.31`
- `release/coder/code-server/v1.3.1`
- `release/coder/cursor/v1.2.1`
- `release/coder/devcontainers-cli/v1.0.31`
- `release/coder/dotfiles/v1.2.1`
- `release/coder/filebrowser/v1.1.2`
- `release/coder/fly-region/v1.0.31`
- `release/coder/gcp-region/v1.0.31`
- `release/coder/git-clone/v1.1.1`
- `release/coder/git-commit-signing/v1.0.31`
- `release/coder/git-config/v1.0.31`
- `release/coder/github-upload-public-key/v1.0.31`
- `release/coder/goose/v2.0.1`
- `release/coder/hcp-vault-secrets/v1.0.33`
- `release/coder/jetbrains/v1.0.1`
- `release/coder/jetbrains-gateway/v1.2.2`
- `release/coder/jfrog-oauth/v1.0.31`
- `release/coder/jfrog-token/v1.0.31`
- `release/coder/jupyterlab/v1.1.1`
- `release/coder/jupyter-notebook/v1.1.1`
- `release/coder/kasmvnc/v1.2.1`
- `release/coder/local-windows-rdp/v1.0.2`
- `release/coder/personalize/v1.0.31`
- `release/coder/slackme/v1.0.31`
- `release/coder/vault-github/v1.0.31`
- `release/coder/vault-jwt/v1.1.1`
- `release/coder/vault-token/v1.2.1`
- `release/coder/vscode-desktop/v1.1.1`
- `release/coder/vscode-web/v1.3.1`
- `release/coder/windows-rdp/v1.2.3`
- `release/coder/windsurf/v1.1.1`
- `release/coder/zed/v1.0.1`


 Do you want to proceed with creating and pushing these release tags?
   This will create git tags and push them to the remote repository.

Continue? [y/N]: y

🏷️  Creating release tags for commit: 9ed5084bfb

Creating tag: release/coder/agentapi/v1.0.1
 Created: release/coder/agentapi/v1.0.1
Creating tag: release/coder/aider/v1.1.1
 Created: release/coder/aider/v1.1.1
Creating tag: release/coder/amazon-dcv-windows/v1.1.1
 Created: release/coder/amazon-dcv-windows/v1.1.1
Creating tag: release/coder/amazon-q/v1.1.1
 Created: release/coder/amazon-q/v1.1.1
Creating tag: release/coder/aws-region/v1.0.31
 Created: release/coder/aws-region/v1.0.31
Creating tag: release/coder/azure-region/v1.0.31
 Created: release/coder/azure-region/v1.0.31
Creating tag: release/coder/coder-login/v1.0.31
 Created: release/coder/coder-login/v1.0.31
Creating tag: release/coder/code-server/v1.3.1
 Created: release/coder/code-server/v1.3.1
Creating tag: release/coder/cursor/v1.2.1
 Created: release/coder/cursor/v1.2.1
Creating tag: release/coder/devcontainers-cli/v1.0.31
 Created: release/coder/devcontainers-cli/v1.0.31
Creating tag: release/coder/dotfiles/v1.2.1
 Created: release/coder/dotfiles/v1.2.1
Creating tag: release/coder/filebrowser/v1.1.2
 Created: release/coder/filebrowser/v1.1.2
Creating tag: release/coder/fly-region/v1.0.31
 Created: release/coder/fly-region/v1.0.31
Creating tag: release/coder/gcp-region/v1.0.31
 Created: release/coder/gcp-region/v1.0.31
Creating tag: release/coder/git-clone/v1.1.1
 Created: release/coder/git-clone/v1.1.1
Creating tag: release/coder/git-commit-signing/v1.0.31
 Created: release/coder/git-commit-signing/v1.0.31
Creating tag: release/coder/git-config/v1.0.31
 Created: release/coder/git-config/v1.0.31
Creating tag: release/coder/github-upload-public-key/v1.0.31
 Created: release/coder/github-upload-public-key/v1.0.31
Creating tag: release/coder/goose/v2.0.1
 Created: release/coder/goose/v2.0.1
Creating tag: release/coder/hcp-vault-secrets/v1.0.33
 Created: release/coder/hcp-vault-secrets/v1.0.33
Creating tag: release/coder/jetbrains/v1.0.1
 Created: release/coder/jetbrains/v1.0.1
Creating tag: release/coder/jetbrains-gateway/v1.2.2
 Created: release/coder/jetbrains-gateway/v1.2.2
Creating tag: release/coder/jfrog-oauth/v1.0.31
 Created: release/coder/jfrog-oauth/v1.0.31
Creating tag: release/coder/jfrog-token/v1.0.31
 Created: release/coder/jfrog-token/v1.0.31
Creating tag: release/coder/jupyterlab/v1.1.1
 Created: release/coder/jupyterlab/v1.1.1
Creating tag: release/coder/jupyter-notebook/v1.1.1
 Created: release/coder/jupyter-notebook/v1.1.1
Creating tag: release/coder/kasmvnc/v1.2.1
 Created: release/coder/kasmvnc/v1.2.1
Creating tag: release/coder/local-windows-rdp/v1.0.2
 Created: release/coder/local-windows-rdp/v1.0.2
Creating tag: release/coder/personalize/v1.0.31
 Created: release/coder/personalize/v1.0.31
Creating tag: release/coder/slackme/v1.0.31
 Created: release/coder/slackme/v1.0.31
Creating tag: release/coder/vault-github/v1.0.31
 Created: release/coder/vault-github/v1.0.31
Creating tag: release/coder/vault-jwt/v1.1.1
 Created: release/coder/vault-jwt/v1.1.1
Creating tag: release/coder/vault-token/v1.2.1
 Created: release/coder/vault-token/v1.2.1
Creating tag: release/coder/vscode-desktop/v1.1.1
 Created: release/coder/vscode-desktop/v1.1.1
Creating tag: release/coder/vscode-web/v1.3.1
 Created: release/coder/vscode-web/v1.3.1
Creating tag: release/coder/windows-rdp/v1.2.3
 Created: release/coder/windows-rdp/v1.2.3
Creating tag: release/coder/windsurf/v1.1.1
 Created: release/coder/windsurf/v1.1.1
Creating tag: release/coder/zed/v1.0.1
 Created: release/coder/zed/v1.0.1

📊 Tag creation summary:
  Created: 38
  Failed: 0

🚀 Pushing tags to origin...
Pushing: release/coder/agentapi/v1.0.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 187 bytes | 26.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/agentapi/v1.0.1 -> release/coder/agentapi/v1.0.1
 Pushed: release/coder/agentapi/v1.0.1
Pushing: release/coder/aider/v1.1.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 184 bytes | 26.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/aider/v1.1.1 -> release/coder/aider/v1.1.1
 Pushed: release/coder/aider/v1.1.1
Pushing: release/coder/amazon-dcv-windows/v1.1.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 195 bytes | 65.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/amazon-dcv-windows/v1.1.1 -> release/coder/amazon-dcv-windows/v1.1.1
 Pushed: release/coder/amazon-dcv-windows/v1.1.1
Pushing: release/coder/amazon-q/v1.1.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 187 bytes | 26.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/amazon-q/v1.1.1 -> release/coder/amazon-q/v1.1.1
 Pushed: release/coder/amazon-q/v1.1.1
Pushing: release/coder/aws-region/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 190 bytes | 23.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/aws-region/v1.0.31 -> release/coder/aws-region/v1.0.31
 Pushed: release/coder/aws-region/v1.0.31
Pushing: release/coder/azure-region/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 192 bytes | 27.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/azure-region/v1.0.31 -> release/coder/azure-region/v1.0.31
 Pushed: release/coder/azure-region/v1.0.31
Pushing: release/coder/coder-login/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 189 bytes | 31.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/coder-login/v1.0.31 -> release/coder/coder-login/v1.0.31
 Pushed: release/coder/coder-login/v1.0.31
Pushing: release/coder/code-server/v1.3.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 188 bytes | 31.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/code-server/v1.3.1 -> release/coder/code-server/v1.3.1
 Pushed: release/coder/code-server/v1.3.1
Pushing: release/coder/cursor/v1.2.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 186 bytes | 62.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/cursor/v1.2.1 -> release/coder/cursor/v1.2.1
 Pushed: release/coder/cursor/v1.2.1
Pushing: release/coder/devcontainers-cli/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 194 bytes | 32.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/devcontainers-cli/v1.0.31 -> release/coder/devcontainers-cli/v1.0.31
 Pushed: release/coder/devcontainers-cli/v1.0.31
Pushing: release/coder/dotfiles/v1.2.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 187 bytes | 31.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/dotfiles/v1.2.1 -> release/coder/dotfiles/v1.2.1
 Pushed: release/coder/dotfiles/v1.2.1
Pushing: release/coder/filebrowser/v1.1.2
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 190 bytes | 63.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/filebrowser/v1.1.2 -> release/coder/filebrowser/v1.1.2
 Pushed: release/coder/filebrowser/v1.1.2
Pushing: release/coder/fly-region/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 190 bytes | 63.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/fly-region/v1.0.31 -> release/coder/fly-region/v1.0.31
 Pushed: release/coder/fly-region/v1.0.31
Pushing: release/coder/gcp-region/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 190 bytes | 63.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/gcp-region/v1.0.31 -> release/coder/gcp-region/v1.0.31
 Pushed: release/coder/gcp-region/v1.0.31
Pushing: release/coder/git-clone/v1.1.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 187 bytes | 93.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/git-clone/v1.1.1 -> release/coder/git-clone/v1.1.1
 Pushed: release/coder/git-clone/v1.1.1
Pushing: release/coder/git-commit-signing/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 194 bytes | 38.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/git-commit-signing/v1.0.31 -> release/coder/git-commit-signing/v1.0.31
 Pushed: release/coder/git-commit-signing/v1.0.31
Pushing: release/coder/git-config/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 190 bytes | 38.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/git-config/v1.0.31 -> release/coder/git-config/v1.0.31
 Pushed: release/coder/git-config/v1.0.31
Pushing: release/coder/github-upload-public-key/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 200 bytes | 40.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/github-upload-public-key/v1.0.31 -> release/coder/github-upload-public-key/v1.0.31
 Pushed: release/coder/github-upload-public-key/v1.0.31
Pushing: release/coder/goose/v2.0.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 185 bytes | 46.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/goose/v2.0.1 -> release/coder/goose/v2.0.1
 Pushed: release/coder/goose/v2.0.1
Pushing: release/coder/hcp-vault-secrets/v1.0.33
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 195 bytes | 39.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/hcp-vault-secrets/v1.0.33 -> release/coder/hcp-vault-secrets/v1.0.33
 Pushed: release/coder/hcp-vault-secrets/v1.0.33
Pushing: release/coder/jetbrains/v1.0.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 187 bytes | 46.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/jetbrains/v1.0.1 -> release/coder/jetbrains/v1.0.1
 Pushed: release/coder/jetbrains/v1.0.1
Pushing: release/coder/jetbrains-gateway/v1.2.2
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 194 bytes | 97.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/jetbrains-gateway/v1.2.2 -> release/coder/jetbrains-gateway/v1.2.2
 Pushed: release/coder/jetbrains-gateway/v1.2.2
Pushing: release/coder/jfrog-oauth/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 191 bytes | 47.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/jfrog-oauth/v1.0.31 -> release/coder/jfrog-oauth/v1.0.31
 Pushed: release/coder/jfrog-oauth/v1.0.31
Pushing: release/coder/jfrog-token/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 191 bytes | 47.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/jfrog-token/v1.0.31 -> release/coder/jfrog-token/v1.0.31
 Pushed: release/coder/jfrog-token/v1.0.31
Pushing: release/coder/jupyterlab/v1.1.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 188 bytes | 47.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/jupyterlab/v1.1.1 -> release/coder/jupyterlab/v1.1.1
 Pushed: release/coder/jupyterlab/v1.1.1
Pushing: release/coder/jupyter-notebook/v1.1.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 192 bytes | 96.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/jupyter-notebook/v1.1.1 -> release/coder/jupyter-notebook/v1.1.1
 Pushed: release/coder/jupyter-notebook/v1.1.1
Pushing: release/coder/kasmvnc/v1.2.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 187 bytes | 46.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/kasmvnc/v1.2.1 -> release/coder/kasmvnc/v1.2.1
 Pushed: release/coder/kasmvnc/v1.2.1
Pushing: release/coder/local-windows-rdp/v1.0.2
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 194 bytes | 97.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/local-windows-rdp/v1.0.2 -> release/coder/local-windows-rdp/v1.0.2
 Pushed: release/coder/local-windows-rdp/v1.0.2
Pushing: release/coder/personalize/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 191 bytes | 63.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/personalize/v1.0.31 -> release/coder/personalize/v1.0.31
 Pushed: release/coder/personalize/v1.0.31
Pushing: release/coder/slackme/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 187 bytes | 62.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/slackme/v1.0.31 -> release/coder/slackme/v1.0.31
 Pushed: release/coder/slackme/v1.0.31
Pushing: release/coder/vault-github/v1.0.31
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 192 bytes | 64.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/vault-github/v1.0.31 -> release/coder/vault-github/v1.0.31
 Pushed: release/coder/vault-github/v1.0.31
Pushing: release/coder/vault-jwt/v1.1.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 188 bytes | 62.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/vault-jwt/v1.1.1 -> release/coder/vault-jwt/v1.1.1
 Pushed: release/coder/vault-jwt/v1.1.1
Pushing: release/coder/vault-token/v1.2.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 190 bytes | 63.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/vault-token/v1.2.1 -> release/coder/vault-token/v1.2.1
 Pushed: release/coder/vault-token/v1.2.1
Pushing: release/coder/vscode-desktop/v1.1.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 191 bytes | 191.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/vscode-desktop/v1.1.1 -> release/coder/vscode-desktop/v1.1.1
 Pushed: release/coder/vscode-desktop/v1.1.1
Pushing: release/coder/vscode-web/v1.3.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 188 bytes | 47.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/vscode-web/v1.3.1 -> release/coder/vscode-web/v1.3.1
 Pushed: release/coder/vscode-web/v1.3.1
Pushing: release/coder/windows-rdp/v1.2.3
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 190 bytes | 63.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/windows-rdp/v1.2.3 -> release/coder/windows-rdp/v1.2.3
 Pushed: release/coder/windows-rdp/v1.2.3
Pushing: release/coder/windsurf/v1.1.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 187 bytes | 93.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/windsurf/v1.1.1 -> release/coder/windsurf/v1.1.1
 Pushed: release/coder/windsurf/v1.1.1
Pushing: release/coder/zed/v1.0.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 183 bytes | 91.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/coder/registry
 * [new tag]         release/coder/zed/v1.0.1 -> release/coder/zed/v1.0.1
 Pushed: release/coder/zed/v1.0.1

📊 Push summary:
  Pushed: 38
  Failed: 0

🎉 Successfully created and pushed 38 release tags!

📝 Next steps:
  - Tags will be automatically published to registry.coder.com
  - Monitor the registry website for updates
  - Check GitHub releases for any issues
```
2025-07-23 14:20:10 -05:00
DevCats 9ed5084bfb chore: remove maintainer_github from all modules and examples (#231)
This PR updates all modules to remove maintainer_github field from
frontmatter.

I also updated a few modules to 1.0.31 to be later than the latest
general release on coder/modules.

⚠️  Modules Without Git Tags:

- coder/aws-region (README: v1.0.12) SHOULD BE: 1.0.31 Missed Tag
- coder/azure-region (README: v1.0.12) SHOULD BE: 1.0.31 Missed Tag
- coder/coder-login (README: v1.0.15) SHOULD BE: 1.0.31 Missed Tag
- coder/devcontainers-cli (README: v1.0.3) SHOULD BE: 1.0.31 Missed Tag
- coder/fly-region (README: v1.0.2) SHOULD BE: 1.0.31 Missed Tag
- coder/gcp-region (README: v1.0.12) SHOULD BE: 1.0.31 Missed Tag
- coder/git-commit-signing (README: v1.0.11) SHOULD BE: 1.0.31 Missed
Tag
- coder/git-config (README: v1.0.15) SHOULD BE: 1.0.31 Missed Tag
- coder/github-upload-public-key (README: v1.0.15) SHOULD BE: 1.0.31
Missed Tag
- coder/jfrog-oauth (README: v1.0.19) SHOULD BE: 1.0.31 Missed Tag
- coder/jfrog-token (README: v1.0.30) SHOULD BE: 1.0.31 Missed Tag
- coder/personalize (README: v1.0.2) SHOULD BE: 1.0.31 Missed Tag
- coder/slackme (README: v1.0.2) SHOULD BE: 1.0.31 Missed Tag
- coder/vault-github (README: v1.0.7) SHOULD BE: 1.0.31 Missed Tag
- coder/vault-jwt (README: v1.1.0) Missed Tag but correct

All of these modules have not been tagged since the move from
coder/modules. I believe they all need to move to 1.0.31 to outpace the
latest published general version from coder/modules.


Modules Updated:

- coder/agentapi: v1.0.0 → v1.0.1
- coder/aider: v1.1.0 → v1.1.1
- coder/amazon-dcv-windows: v1.1.0 → v1.1.1
- coder/amazon-q: v1.1.0 → v1.1.1
- coder/aws-region: v1.0.12 → v1.0.31
- coder/azure-region: v1.0.12 → v1.0.31
- coder/claude-code: v2.0.2 → v2.0.3
- coder/coder-login: v1.0.15 → v1.0.31
- coder/code-server: v1.3.0 → v1.3.1
- coder/cursor: v1.2.0 → v1.2.1
- coder/devcontainers-cli: v1.0.3 → v1.0.31
- coder/dotfiles: v1.2.0 → v1.2.1
- coder/filebrowser: v1.1.1 → v1.1.2
- coder/fly-region: v1.0.2 → v1.0.31
- coder/gcp-region: v1.0.12 → v1.0.31
- coder/git-clone: v1.1.0 → v1.1.1
- coder/git-commit-signing: v1.0.11 → v1.0.31
- coder/git-config: v1.0.15 → v1.0.31
- coder/github-upload-public-key: v1.0.15 → v1.0.31
- coder/goose: v2.0.0 → v2.0.1
- coder/hcp-vault-secrets: v1.0.32 → v1.0.33
- coder/jetbrains: v1.0.0 → v1.0.1
- coder/jetbrains-gateway: v1.2.1 → v1.2.2
- coder/jfrog-oauth: v1.0.19 → v1.0.31
- coder/jfrog-token: v1.0.30 → v1.0.31
- coder/jupyterlab: v1.1.0 → v1.1.1
- coder/jupyter-notebook: v1.1.0 → v1.1.1
- coder/kasmvnc: v1.2.0 → v1.2.1
- coder/local-windows-rdp: v1.0.1 → v1.0.2
- coder/personalize: v1.0.2 → v1.0.31
- coder/slackme: v1.0.2 → v1.0.31
- coder/vault-github: v1.0.7 → v1.0.31
- coder/vault-jwt: v1.1.0 → v1.1.1
- coder/vault-token: v1.2.0 → v1.2.1
- coder/vscode-desktop: v1.1.0 → v1.1.1
- coder/vscode-web: v1.3.0 → v1.3.1
- coder/windows-rdp: v1.2.2 → v1.2.3
- coder/windsurf: v1.1.0 → v1.1.1
- coder/zed: v1.0.0 → v1.0.1
2025-07-22 19:48:01 -05:00
Marcin Tojek 959878d41e chore: bump agentapi version to v0.2.3 (#247) 2025-07-22 13:55:36 +02:00
Ben Potter 53af6e0f20 chore: update coder labs avatar (#243)
context:
https://codercom.slack.com/archives/C082RQ830NR/p1751551577242049
2025-07-19 16:04:12 -05:00
Atif Ali ce1d0cb833 Add docker-build template to coder-labs namespace (#235)
This template builds Docker containers from a Dockerfile, rather than
using a pre-built image, allowing for more customization of the
development environment.

Based on the docker template that was removed in coder/coder#15504.

---------

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2025-07-18 19:46:30 +05:00
Atif Ali ab87e0e329 chore: remove extra lockfiles (#233)
We use bun and should only have `bun.lock`
2025-07-15 20:26:58 -05:00
blink-so[bot] e13e7b5862 Add Kiro IDE module (#232)
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
Co-authored-by: matifali <10648092+matifali@users.noreply.github.com>
Co-authored-by: Atif Ali <atif@coder.com>
2025-07-16 01:54:00 +05:00
116 changed files with 3550 additions and 797 deletions
+5 -2
View File
@@ -1,6 +1,9 @@
name: deploy-registry
on:
schedule:
# Runs at 02:30 UTC Monday through Friday
- cron: "30 2 * * 1-5"
push:
tags:
# Matches release/<namespace>/<resource_name>/<semantic_version>
@@ -26,12 +29,12 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Authenticate with Google Cloud
uses: google-github-actions/auth@ba79af03959ebeac9769e648f473a284504d9193
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
- name: Set up Google Cloud SDK
uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a
uses: google-github-actions/setup-gcloud@6a7c903a70c8625ed6700fa299f5ddb4ca6022e9
- name: Deploy to dev.registry.coder.com
run: gcloud builds triggers run 29818181-126d-4f8a-a937-f228b27d3d34 --branch main
- name: Deploy to registry.coder.com
+3
View File
@@ -145,3 +145,6 @@ dist
# Generated credentials from google-github-actions/auth
gha-creds-*.json
# IDEs
.idea
+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Gemini</title><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="#3186FF"></path><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#lobe-icons-gemini-fill-0)"></path><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#lobe-icons-gemini-fill-1)"></path><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#lobe-icons-gemini-fill-2)"></path><defs><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-gemini-fill-0" x1="7" x2="11" y1="15.5" y2="12"><stop stop-color="#08B962"></stop><stop offset="1" stop-color="#08B962" stop-opacity="0"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-gemini-fill-1" x1="8" x2="11.5" y1="5.5" y2="11"><stop stop-color="#F94543"></stop><stop offset="1" stop-color="#F94543" stop-opacity="0"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-gemini-fill-2" x1="3.5" x2="17.5" y1="13.5" y2="12"><stop stop-color="#FABC12"></stop><stop offset=".46" stop-color="#FABC12" stop-opacity="0"></stop></linearGradient></defs></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="24" viewBox="0 0 20 24" fill="none"><path d="M3.80081 18.5661C1.32306 24.0572 6.59904 25.434 10.4904 22.2205C11.6339 25.8242 15.926 23.1361 17.4652 20.3445C20.8578 14.1915 19.4877 7.91459 19.1361 6.61988C16.7244 -2.20972 4.67055 -2.21852 2.59581 6.6649C2.11136 8.21946 2.10284 9.98752 1.82846 11.8233C1.69011 12.749 1.59258 13.3398 1.23436 14.3135C1.02841 14.8733 0.745043 15.3704 0.299833 16.2082C-0.391594 17.5095 -0.0998802 20.021 3.46397 18.7186V18.7195L3.80081 18.5661Z" fill="white"></path><path d="M10.9614 10.4413C9.97202 10.4413 9.82422 9.25893 9.82422 8.55407C9.82422 7.91791 9.93824 7.4124 10.1542 7.09197C10.3441 6.81003 10.6158 6.66699 10.9614 6.66699C11.3071 6.66699 11.6036 6.81228 11.8128 7.09892C12.0511 7.42554 12.177 7.92861 12.177 8.55407C12.177 9.73591 11.7226 10.4413 10.9616 10.4413H10.9614Z" fill="black"></path><path d="M15.0318 10.4413C14.0423 10.4413 13.8945 9.25893 13.8945 8.55407C13.8945 7.91791 14.0086 7.4124 14.2245 7.09197C14.4144 6.81003 14.6861 6.66699 15.0318 6.66699C15.3774 6.66699 15.6739 6.81228 15.8831 7.09892C16.1214 7.42554 16.2474 7.92861 16.2474 8.55407C16.2474 9.73591 15.793 10.4413 15.0319 10.4413H15.0318Z" fill="black"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+1
View File
@@ -0,0 +1 @@
<svg fill="none" height="2500" width="2500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160"><g clip-rule="evenodd" fill-rule="evenodd"><path d="M0 116h160v28.996c0 8.287-6.722 15.004-14.998 15.004H14.998C6.716 160 0 153.293 0 144.996zm0 0h160v30H0z" fill="#1bb91f"/><path d="M83 70V0h-6v146h6V76h77v-6zM0 15.007C0 6.719 6.722 0 14.998 0h130.004C153.285 0 160 6.725 160 15.007V146H0z" fill="#3c3c3c"/></g></svg>

After

Width:  |  Height:  |  Size: 419 B

+50 -5
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
@@ -72,7 +118,6 @@ Changes are automatically published to [registry.coder.com](https://registry.cod
display_name: "Module Name"
description: "What it does"
icon: "../../../../.icons/tool.svg"
partner_github: "partner-name" # Optional - For official partner modules
verified: false # Optional - Set by maintainers only
tags: ["tag1", "tag2"]
```
+72
View File
@@ -0,0 +1,72 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "registry",
"devDependencies": {
"@types/bun": "^1.2.18",
"bun-types": "^1.2.18",
"dedent": "^1.6.0",
"gray-matter": "^4.0.3",
"marked": "^16.0.0",
"prettier": "^3.6.2",
"prettier-plugin-sh": "^0.18.0",
"prettier-plugin-terraform-formatter": "^1.2.1",
},
"peerDependencies": {
"typescript": "^5.8.3",
},
},
},
"packages": {
"@reteps/dockerfmt": ["@reteps/dockerfmt@0.3.6", "", {}, "sha512-Tb5wIMvBf/nLejTQ61krK644/CEMB/cpiaIFXqGApfGqO3GwcR3qnI0DbmkFVCl2OyEp8LnLX3EkucoL0+tbFg=="],
"@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
"@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="],
"@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="],
"argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
"bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"dedent": ["dedent@1.6.0", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA=="],
"esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
"extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="],
"gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="],
"is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="],
"js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
"marked": ["marked@16.0.0", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-MUKMXDjsD/eptB7GPzxo4xcnLS6oo7/RHimUMHEDRhUooPwmN9BEpMl7AEOJv3bmso169wHI2wUF9VQgL7zfmA=="],
"prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
"prettier-plugin-sh": ["prettier-plugin-sh@0.18.0", "", { "dependencies": { "@reteps/dockerfmt": "^0.3.6", "sh-syntax": "^0.5.8" }, "peerDependencies": { "prettier": "^3.6.0" } }, "sha512-cW1XL27FOJQ/qGHOW6IHwdCiNWQsAgK+feA8V6+xUTaH0cD3Mh+tFAtBvEEWvuY6hTDzRV943Fzeii+qMOh7nQ=="],
"prettier-plugin-terraform-formatter": ["prettier-plugin-terraform-formatter@1.2.1", "", { "peerDependencies": { "prettier": ">= 1.16.0" }, "optionalPeers": ["prettier"] }, "sha512-rdzV61Bs/Ecnn7uAS/vL5usTX8xUWM+nQejNLZxt3I1kJH5WSeLEmq7LYu1wCoEQF+y7Uv1xGvPRfl3lIe6+tA=="],
"section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="],
"sh-syntax": ["sh-syntax@0.5.8", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-JfVoxf4FxQI5qpsPbkHhZo+n6N9YMJobyl4oGEUBb/31oQYlgTjkXQD8PBiafS2UbWoxrTO0Z5PJUBXEPAG1Zw=="],
"sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
"strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="],
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
"undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
}
}
BIN
View File
Binary file not shown.
-1
View File
@@ -2,7 +2,6 @@
display_name: MODULE_NAME
description: Describe what this module does
icon: ../../../../.icons/<A_RELEVANT_ICON>.svg
maintainer_github: GITHUB_USERNAME
verified: false
tags: [helper]
---
-308
View File
@@ -1,308 +0,0 @@
{
"name": "registry",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "registry",
"devDependencies": {
"@types/bun": "^1.2.9",
"bun-types": "^1.1.23",
"gray-matter": "^4.0.3",
"marked": "^12.0.2",
"prettier": "^3.3.3",
"prettier-plugin-sh": "^0.13.1",
"prettier-plugin-terraform-formatter": "^1.2.1"
},
"peerDependencies": {
"typescript": "^5.5.4"
}
},
"node_modules/@types/bun": {
"version": "1.2.18",
"resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.2.18.tgz",
"integrity": "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"bun-types": "1.2.18"
}
},
"node_modules/@types/node": {
"version": "24.0.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.10.tgz",
"integrity": "sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.8.0"
}
},
"node_modules/@types/react": {
"version": "19.1.8",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz",
"integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"csstype": "^3.0.2"
}
},
"node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"license": "MIT",
"dependencies": {
"sprintf-js": "~1.0.2"
}
},
"node_modules/bun-types": {
"version": "1.2.18",
"resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.2.18.tgz",
"integrity": "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
},
"peerDependencies": {
"@types/react": "^19"
}
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true,
"license": "MIT",
"peer": true
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true,
"license": "BSD-2-Clause",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-extendable": "^0.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gray-matter": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz",
"integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"js-yaml": "^3.13.1",
"kind-of": "^6.0.2",
"section-matter": "^1.0.0",
"strip-bom-string": "^1.0.0"
},
"engines": {
"node": ">=6.0"
}
},
"node_modules/is-extendable": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
"integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/js-yaml": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/marked": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz",
"integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==",
"dev": true,
"license": "MIT",
"bin": {
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/mvdan-sh": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/mvdan-sh/-/mvdan-sh-0.10.1.tgz",
"integrity": "sha512-kMbrH0EObaKmK3nVRKUIIya1dpASHIEusM13S4V1ViHFuxuNxCo+arxoa6j/dbV22YBGjl7UKJm9QQKJ2Crzhg==",
"deprecated": "See https://github.com/mvdan/sh/issues/1145",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/prettier": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-plugin-sh": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/prettier-plugin-sh/-/prettier-plugin-sh-0.13.1.tgz",
"integrity": "sha512-ytMcl1qK4s4BOFGvsc9b0+k9dYECal7U29bL/ke08FEUsF/JLN0j6Peo0wUkFDG4y2UHLMhvpyd6Sd3zDXe/eg==",
"dev": true,
"license": "MIT",
"dependencies": {
"mvdan-sh": "^0.10.1",
"sh-syntax": "^0.4.1"
},
"engines": {
"node": ">=16.0.0"
},
"funding": {
"url": "https://opencollective.com/unts"
},
"peerDependencies": {
"prettier": "^3.0.0"
}
},
"node_modules/prettier-plugin-terraform-formatter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prettier-plugin-terraform-formatter/-/prettier-plugin-terraform-formatter-1.2.1.tgz",
"integrity": "sha512-rdzV61Bs/Ecnn7uAS/vL5usTX8xUWM+nQejNLZxt3I1kJH5WSeLEmq7LYu1wCoEQF+y7Uv1xGvPRfl3lIe6+tA==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"prettier": ">= 1.16.0"
},
"peerDependenciesMeta": {
"prettier": {
"optional": true
}
}
},
"node_modules/section-matter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
"integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==",
"dev": true,
"license": "MIT",
"dependencies": {
"extend-shallow": "^2.0.1",
"kind-of": "^6.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/sh-syntax": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/sh-syntax/-/sh-syntax-0.4.2.tgz",
"integrity": "sha512-/l2UZ5fhGZLVZa16XQM9/Vq/hezGGbdHeVEA01uWjOL1+7Ek/gt6FquW0iKKws4a9AYPYvlz6RyVvjh3JxOteg==",
"dev": true,
"license": "MIT",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
},
"funding": {
"url": "https://opencollective.com/unts"
}
},
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/strip-bom-string": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz",
"integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD"
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
"dev": true,
"license": "MIT"
}
}
}
-220
View File
@@ -1,220 +0,0 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
typescript:
specifier: ^5.8.3
version: 5.8.3
devDependencies:
'@types/bun':
specifier: ^1.2.18
version: 1.2.18(@types/react@19.1.8)
bun-types:
specifier: ^1.2.18
version: 1.2.18(@types/react@19.1.8)
gray-matter:
specifier: ^4.0.3
version: 4.0.3
marked:
specifier: ^16.0.0
version: 16.0.0
prettier:
specifier: ^3.6.2
version: 3.6.2
prettier-plugin-sh:
specifier: ^0.18.0
version: 0.18.0(prettier@3.6.2)
prettier-plugin-terraform-formatter:
specifier: ^1.2.1
version: 1.2.1(prettier@3.6.2)
packages:
'@reteps/dockerfmt@0.3.6':
resolution: {integrity: sha512-Tb5wIMvBf/nLejTQ61krK644/CEMB/cpiaIFXqGApfGqO3GwcR3qnI0DbmkFVCl2OyEp8LnLX3EkucoL0+tbFg==}
engines: {node: ^v12.20.0 || ^14.13.0 || >=16.0.0}
'@types/bun@1.2.18':
resolution: {integrity: sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ==}
'@types/node@24.0.10':
resolution: {integrity: sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA==}
'@types/react@19.1.8':
resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==}
argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
bun-types@1.2.18:
resolution: {integrity: sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw==}
peerDependencies:
'@types/react': ^19
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'}
hasBin: true
extend-shallow@2.0.1:
resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
engines: {node: '>=0.10.0'}
gray-matter@4.0.3:
resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
engines: {node: '>=6.0'}
is-extendable@0.1.1:
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
engines: {node: '>=0.10.0'}
js-yaml@3.14.1:
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
hasBin: true
kind-of@6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
marked@16.0.0:
resolution: {integrity: sha512-MUKMXDjsD/eptB7GPzxo4xcnLS6oo7/RHimUMHEDRhUooPwmN9BEpMl7AEOJv3bmso169wHI2wUF9VQgL7zfmA==}
engines: {node: '>= 20'}
hasBin: true
prettier-plugin-sh@0.18.0:
resolution: {integrity: sha512-cW1XL27FOJQ/qGHOW6IHwdCiNWQsAgK+feA8V6+xUTaH0cD3Mh+tFAtBvEEWvuY6hTDzRV943Fzeii+qMOh7nQ==}
engines: {node: '>=16.0.0'}
peerDependencies:
prettier: ^3.6.0
prettier-plugin-terraform-formatter@1.2.1:
resolution: {integrity: sha512-rdzV61Bs/Ecnn7uAS/vL5usTX8xUWM+nQejNLZxt3I1kJH5WSeLEmq7LYu1wCoEQF+y7Uv1xGvPRfl3lIe6+tA==}
peerDependencies:
prettier: '>= 1.16.0'
peerDependenciesMeta:
prettier:
optional: true
prettier@3.6.2:
resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
engines: {node: '>=14'}
hasBin: true
section-matter@1.0.0:
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
engines: {node: '>=4'}
sh-syntax@0.5.8:
resolution: {integrity: sha512-JfVoxf4FxQI5qpsPbkHhZo+n6N9YMJobyl4oGEUBb/31oQYlgTjkXQD8PBiafS2UbWoxrTO0Z5PJUBXEPAG1Zw==}
engines: {node: '>=16.0.0'}
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
strip-bom-string@1.0.0:
resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==}
engines: {node: '>=0.10.0'}
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
typescript@5.8.3:
resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
engines: {node: '>=14.17'}
hasBin: true
undici-types@7.8.0:
resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==}
snapshots:
'@reteps/dockerfmt@0.3.6': {}
'@types/bun@1.2.18(@types/react@19.1.8)':
dependencies:
bun-types: 1.2.18(@types/react@19.1.8)
transitivePeerDependencies:
- '@types/react'
'@types/node@24.0.10':
dependencies:
undici-types: 7.8.0
'@types/react@19.1.8':
dependencies:
csstype: 3.1.3
argparse@1.0.10:
dependencies:
sprintf-js: 1.0.3
bun-types@1.2.18(@types/react@19.1.8):
dependencies:
'@types/node': 24.0.10
'@types/react': 19.1.8
csstype@3.1.3: {}
esprima@4.0.1: {}
extend-shallow@2.0.1:
dependencies:
is-extendable: 0.1.1
gray-matter@4.0.3:
dependencies:
js-yaml: 3.14.1
kind-of: 6.0.3
section-matter: 1.0.0
strip-bom-string: 1.0.0
is-extendable@0.1.1: {}
js-yaml@3.14.1:
dependencies:
argparse: 1.0.10
esprima: 4.0.1
kind-of@6.0.3: {}
marked@16.0.0: {}
prettier-plugin-sh@0.18.0(prettier@3.6.2):
dependencies:
'@reteps/dockerfmt': 0.3.6
prettier: 3.6.2
sh-syntax: 0.5.8
prettier-plugin-terraform-formatter@1.2.1(prettier@3.6.2):
optionalDependencies:
prettier: 3.6.2
prettier@3.6.2: {}
section-matter@1.0.0:
dependencies:
extend-shallow: 2.0.1
kind-of: 6.0.3
sh-syntax@0.5.8:
dependencies:
tslib: 2.8.1
sprintf-js@1.0.3: {}
strip-bom-string@1.0.0: {}
tslib@2.8.1: {}
typescript@5.8.3: {}
undici-types@7.8.0: {}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

+13
View File
@@ -0,0 +1,13 @@
---
display_name: "Jay Kumar"
bio: "I'm a Software Engineer :)"
avatar_url: "./.images/avatar.png"
github: "35C4n0r"
linkedin: "https://www.linkedin.com/in/jaykum4r"
support_email: "work.jaykumar@gmail.com"
status: "community"
---
# Your Name
I'm a Software Engineer :)
+101
View File
@@ -0,0 +1,101 @@
---
display_name: "Tmux"
description: "Tmux for coder agent :)"
icon: "../../../../.icons/tmux.svg"
verified: false
tags: ["tmux", "terminal", "persistent"]
---
# tmux
This module provisions and configures [tmux](https://github.com/tmux/tmux) with session persistence and plugin support
for a Coder agent. It automatically installs tmux, the Tmux Plugin Manager (TPM), and a set of useful plugins, and sets
up a default or custom tmux configuration with session save/restore capabilities.
```tf
module "tmux" {
source = "registry.coder.com/anomaly/tmux/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
}
```
## Features
- Installs tmux if not already present
- Installs TPM (Tmux Plugin Manager)
- Configures tmux with plugins for sensible defaults, session persistence, and automation:
- `tmux-plugins/tpm`
- `tmux-plugins/tmux-sensible`
- `tmux-plugins/tmux-resurrect`
- `tmux-plugins/tmux-continuum`
- Supports custom tmux configuration
- Enables automatic session save
- Configurable save interval
- **Supports multiple named tmux sessions, each as a separate app in the Coder UI**
## Usage
```tf
module "tmux" {
source = "registry.coder.com/anomaly/tmux/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
tmux_config = "" # Optional: custom tmux.conf content
save_interval = 1 # Optional: save interval in minutes
sessions = ["default", "dev", "ops"] # Optional: list of tmux sessions
order = 1 # Optional: UI order
group = "Terminal" # Optional: UI group
icon = "/icon/tmux.svg" # Optional: app icon
}
```
## Multi-Session Support
This module can provision multiple tmux sessions, each as a separate app in the Coder UI. Use the `sessions` variable to specify a list of session names. For each session, a `coder_app` is created, allowing you to launch or attach to that session directly from the UI.
- **sessions**: List of tmux session names (default: `["default"]`).
## How It Works
- **tmux Installation:**
- Checks if tmux is installed; if not, installs it using the system's package manager (supports apt, yum, dnf,
zypper, apk, brew).
- **TPM Installation:**
- Installs the Tmux Plugin Manager (TPM) to `~/.tmux/plugins/tpm` if not already present.
- **tmux Configuration:**
- If `tmux_config` is provided, writes it to `~/.tmux.conf`.
- Otherwise, generates a default configuration with plugin support and session persistence (using tmux-resurrect and
tmux-continuum).
- Sets up key bindings for quick session save (`Ctrl+s`) and restore (`Ctrl+r`).
- **Plugin Installation:**
- Installs plugins via TPM.
- **Session Persistence:**
- Enables automatic session save/restore at the configured interval.
## Example
```tf
module "tmux" {
source = "registry.coder.com/anomaly/tmux/coder"
version = "1.0.0"
agent_id = var.agent_id
sessions = ["default", "dev", "anomaly"]
tmux_config = <<-EOT
set -g mouse on
set -g history-limit 10000
EOT
group = "Terminal"
order = 2
}
```
> [!IMPORTANT]
>
> - If you provide a custom `tmux_config`, it will completely replace the default configuration. Ensure you include plugin
> and TPM initialization lines if you want plugin support and session persistence.
> - The script will attempt to install dependencies using `sudo` where required.
> - If `git` is not installed, TPM installation will fail.
> - If you are using custom config, you'll be responsible for setting up persistence and plugins.
> - The `order`, `group`, and `icon` variables allow you to customize how tmux apps appear in the Coder UI.
> - In case of session restart or shh reconnection, the tmux session will be automatically restored :)
@@ -0,0 +1,35 @@
import { describe, it, expect } from "bun:test";
import {
runTerraformApply,
runTerraformInit,
testRequiredVariables,
findResourceInstance,
} from "~test";
import path from "path";
const moduleDir = path.resolve(__dirname);
const requiredVars = {
agent_id: "dummy-agent-id",
};
describe("tmux module", async () => {
await runTerraformInit(moduleDir);
// 1. Required variables
testRequiredVariables(moduleDir, requiredVars);
// 2. coder_script resource is created
it("creates coder_script resource", async () => {
const state = await runTerraformApply(moduleDir, requiredVars);
const scriptResource = findResourceInstance(state, "coder_script");
expect(scriptResource).toBeDefined();
expect(scriptResource.agent_id).toBe(requiredVars.agent_id);
// check that the script contains expected lines
expect(scriptResource.script).toContain("Installing tmux");
expect(scriptResource.script).toContain("Installing Tmux Plugin Manager (TPM)");
expect(scriptResource.script).toContain("tmux configuration created at");
expect(scriptResource.script).toContain("✅ tmux setup complete!");
});
});
+78
View File
@@ -0,0 +1,78 @@
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 "tmux_config" {
type = string
description = "Custom tmux configuration to apply."
default = ""
}
variable "save_interval" {
type = number
description = "Save interval (in minutes)."
default = 1
}
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/tmux.svg"
}
variable "sessions" {
type = list(string)
description = "List of tmux sessions to create or start."
default = ["default"]
}
resource "coder_script" "tmux" {
agent_id = var.agent_id
display_name = "tmux"
icon = "/icon/terminal.svg"
script = templatefile("${path.module}/scripts/run.sh", {
TMUX_CONFIG = var.tmux_config
SAVE_INTERVAL = var.save_interval
})
run_on_start = true
run_on_stop = false
}
resource "coder_app" "tmux_sessions" {
for_each = toset(var.sessions)
agent_id = var.agent_id
slug = "tmux-${each.value}"
display_name = "tmux - ${each.value}"
icon = var.icon
order = var.order
group = var.group
command = templatefile("${path.module}/scripts/start.sh", {
SESSION_NAME = each.value
})
}
+153
View File
@@ -0,0 +1,153 @@
#!/usr/bin/env bash
BOLD='\033[0;1m'
# Convert templated variables to shell variables
SAVE_INTERVAL="${SAVE_INTERVAL}"
TMUX_CONFIG="${TMUX_CONFIG}"
# Function to install tmux
install_tmux() {
printf "Checking for tmux installation\n"
if command -v tmux &> /dev/null; then
printf "tmux is already installed \n\n"
return 0
fi
printf "Installing tmux \n\n"
# Detect package manager and install tmux
if command -v apt-get &> /dev/null; then
sudo apt-get update
sudo apt-get install -y tmux
elif command -v yum &> /dev/null; then
sudo yum install -y tmux
elif command -v dnf &> /dev/null; then
sudo dnf install -y tmux
elif command -v zypper &> /dev/null; then
sudo zypper install -y tmux
elif command -v apk &> /dev/null; then
sudo apk add tmux
elif command -v brew &> /dev/null; then
brew install tmux
else
printf "No supported package manager found. Please install tmux manually. \n"
exit 1
fi
printf "tmux installed successfully \n"
}
# Function to install Tmux Plugin Manager (TPM)
install_tpm() {
local tpm_dir="$HOME/.tmux/plugins/tpm"
if [ -d "$tpm_dir" ]; then
printf "TPM is already installed"
return 0
fi
printf "Installing Tmux Plugin Manager (TPM) \n"
# Create plugins directory
mkdir -p "$HOME/.tmux/plugins"
# Clone TPM repository
if command -v git &> /dev/null; then
git clone https://github.com/tmux-plugins/tpm "$tpm_dir"
printf "TPM installed successfully"
else
printf "Git is not installed. Please install git to use tmux plugins. \n"
exit 1
fi
}
# Function to create tmux configuration
setup_tmux_config() {
printf "Setting up tmux configuration \n"
local config_dir="$HOME/.tmux"
local config_file="$HOME/.tmux.conf"
mkdir -p "$config_dir"
if [ -n "$TMUX_CONFIG" ]; then
printf "$TMUX_CONFIG" > "$config_file"
printf "$${BOLD}Custom tmux configuration applied at {$config_file} \n\n"
else
cat > "$config_file" << EOF
# Tmux Configuration File
# =============================================================================
# PLUGIN CONFIGURATION
# =============================================================================
# List of plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
# tmux-continuum configuration
set -g @continuum-restore 'on'
set -g @continuum-save-interval '$${SAVE_INTERVAL}'
set -g @continuum-boot 'on'
set -g status-right 'Continuum status: #{continuum_status}'
# =============================================================================
# KEY BINDINGS FOR SESSION MANAGEMENT
# =============================================================================
# Quick session save and restore
bind C-s run-shell "~/.tmux/plugins/tmux-resurrect/scripts/save.sh"
bind C-r run-shell "~/.tmux/plugins/tmux-resurrect/scripts/restore.sh"
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run '~/.tmux/plugins/tpm/tpm'
EOF
printf "tmux configuration created at {$config_file} \n\n"
fi
}
# Function to install tmux plugins
install_plugins() {
printf "Installing tmux plugins"
# Check if TPM is installed
if [ ! -d "$HOME/.tmux/plugins/tpm" ]; then
printf "TPM is not installed. Cannot install plugins. \n"
return 1
fi
# Install plugins using TPM
"$HOME/.tmux/plugins/tpm/bin/install_plugins"
printf "tmux plugins installed successfully \n"
}
# Main execution
main() {
printf "$${BOLD} 🛠️Setting up tmux with session persistence! \n\n"
printf ""
# Install dependencies
install_tmux
install_tpm
# Setup tmux configuration
setup_tmux_config
# Install plugins
install_plugins
printf "$${BOLD}✅ tmux setup complete! \n\n"
printf "$${BOLD} Attempting to restore sessions\n"
tmux new-session -d \; source-file ~/.tmux.conf \; run-shell '~/.tmux/plugins/tmux-resurrect/scripts/restore.sh'
printf "$${BOLD} Sessions restored: -> %s\n" "$(tmux ls)"
}
# Run main function
main
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
# Convert templated variables to shell variables
SESSION_NAME='${SESSION_NAME}'
# Function to check if tmux is installed
check_tmux() {
if ! command -v tmux &> /dev/null; then
echo "tmux is not installed. Please run the tmux setup script first."
exit 1
fi
}
# Function to handle a single session
handle_session() {
local session_name="$1"
# Check if the session exists
if tmux has-session -t "$session_name" 2>/dev/null; then
echo "Session '$session_name' exists, attaching to it..."
tmux attach-session -t "$session_name"
else
echo "Session '$session_name' does not exist, creating it..."
tmux new-session -d -s "$session_name"
tmux attach-session -t "$session_name"
fi
}
# Main function
main() {
# Check if tmux is installed
check_tmux
handle_session "${SESSION_NAME}"
}
# Run the main function
main
+5 -1
View File
@@ -1 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" fill="none" viewBox="0 0 512 512"><rect width="512" height="512" fill="#090B0B"/><path fill="#fff" d="M427.787 172H296.889V188.277H427.787V172Z"/><path fill="#fff" d="M427.787 190.878H296.889V207.154H427.787V190.878Z"/><path fill="#fff" d="M427.787 209.74H296.889V226.017H427.787V209.74Z"/><path fill="#fff" d="M427.787 228.618H296.889V244.895H427.787V228.618Z"/><path fill="#fff" d="M427.787 247.496H296.889V263.773H427.787V247.496Z"/><path fill="#fff" d="M428 266.359H297.102V282.636H428V266.359Z"/><path fill="#fff" d="M427.68 285.237H296.783V301.513H427.68V285.237Z"/><path fill="#fff" d="M427.68 304.115H296.783V320.391H427.68V304.115Z"/><path fill="#fff" d="M427.893 322.993H296.996V339.269H427.893V322.993Z"/><path fill="#fff" d="M245.778 172H116.325V188.277H245.778V172Z"/><path fill="#fff" d="M262.024 190.878H100.17V207.154H262.024V190.878Z"/><path fill="#fff" d="M262.024 304.115H100.17V320.391H262.024V304.115Z"/><path fill="#fff" d="M245.747 322.993H116.325V339.269H245.747V322.993Z"/><path fill="#fff" d="M138.839 247.496H84V263.773H138.839V247.496Z"/><path fill="#fff" d="M148.665 266.374H84V282.651H148.665V266.374Z"/><path fill="#fff" d="M278.088 266.374H213.422V282.651H278.088V266.374Z"/><path fill="#fff" d="M278.087 285.237H207.17V301.513H278.087V285.237Z"/><path fill="#fff" d="M156.652 285.237H84V301.513H156.652V285.237Z"/><path fill="#fff" d="M156.652 209.74H84V226.017H156.652V209.74Z"/><path fill="#fff" d="M278.118 209.74H207.17V226.017H278.118V209.74Z"/><path fill="#fff" d="M148.665 228.618H84V244.895H148.665V228.618Z"/><path fill="#fff" d="M278.118 228.618H213.392V244.895H278.118V228.618Z"/></svg>
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="160" height="160" fill="#090B0B"/>
<path d="M35 79.8451C35 67.7235 45.4217 60 59.7516 60C74.0815 60 82.1149 66.7044 82.3863 76.5733L70.0105 76.9488C69.6848 71.478 64.7725 67.8844 59.7516 67.9917C52.8581 68.1257 47.7558 72.6579 47.7558 79.8451C47.7558 87.0322 52.8581 91.4839 59.7516 91.4839C64.7725 91.4839 69.5762 88.0513 70.119 82.5805L82.4948 82.8486C82.1692 92.8784 73.6472 99.6901 59.7516 99.6901C45.856 99.6901 35 91.913 35 79.8451Z" fill="white"/>
<path d="M88.0795 62.3769C89.3463 61.1103 91.1109 60.7075 92.934 60.8066C94.7578 60.9058 96.8171 61.5088 98.9613 62.4736C101.042 63.4099 103.274 64.7207 105.547 66.3466C107.821 64.721 110.052 63.4108 112.132 62.4745C114.277 61.5095 116.337 60.9057 118.162 60.8066C119.985 60.7075 121.749 61.1102 123.016 62.3769C124.282 63.6436 124.685 65.4084 124.586 67.2314C124.487 69.0554 123.882 71.1151 122.917 73.2597C121.981 75.3406 120.67 77.571 119.044 79.8447C120.67 82.1183 121.981 84.3488 122.917 86.4296C123.882 88.5741 124.487 90.634 124.586 92.4579C124.685 94.2808 124.282 96.0457 123.016 97.3124C121.749 98.5791 119.985 98.9818 118.162 98.8828C116.337 98.7836 114.277 98.1808 112.132 97.2158C110.051 96.2794 107.82 94.9687 105.546 93.3427C103.273 94.9685 101.042 96.2795 98.9613 97.2158C96.817 98.1805 94.7578 98.7845 92.934 98.8837C91.111 98.9828 89.3462 98.5799 88.0795 97.3134C86.8128 96.0467 86.4101 94.2821 86.5092 92.4589C86.6083 90.6349 87.2113 88.5752 88.1762 86.4306C89.1125 84.3496 90.4232 82.1185 92.0492 79.8447C90.4234 77.571 89.1125 75.3405 88.1762 73.2597C87.2113 71.1152 86.6084 69.0553 86.5092 67.2314C86.4101 65.4083 86.8128 63.6437 88.0795 62.3769ZM93.9565 82.3495C92.6833 84.208 91.6584 86.0034 90.9125 87.6611C90.0348 89.6118 89.5764 91.2963 89.5043 92.622C89.4323 93.9484 89.7487 94.7404 90.2006 95.1923C90.6526 95.6441 91.4447 95.9597 92.7709 95.8876C94.0964 95.8155 95.7805 95.3579 97.7309 94.4804C99.3887 93.7344 101.184 92.7078 103.042 91.4345C101.438 90.138 99.8307 88.6984 98.2621 87.1298C96.6935 85.5612 95.253 83.954 93.9565 82.3495ZM117.137 82.3486C115.84 83.9533 114.4 85.5609 112.831 87.1298C111.263 88.6984 109.656 90.138 108.051 91.4345C109.91 92.708 111.706 93.7344 113.364 94.4804C115.314 95.358 116.999 95.8156 118.325 95.8876C119.651 95.9596 120.442 95.6432 120.894 95.1913C121.346 94.7393 121.662 93.9474 121.59 92.621C121.518 91.2955 121.06 89.6114 120.182 87.6611C119.436 86.0031 118.411 84.2074 117.137 82.3486ZM105.547 70.0937C103.831 71.4383 102.091 72.9741 100.383 74.6816C98.6759 76.389 97.1398 78.1289 95.7953 79.8447C97.1397 81.5604 98.6759 83.3004 100.383 85.0078C102.09 86.715 103.831 88.2512 105.546 89.5956C107.262 88.2512 109.003 86.7161 110.71 85.0087C112.418 83.3014 113.953 81.5604 115.297 79.8447C113.953 78.1291 112.418 76.3888 110.71 74.6816C109.003 72.9743 107.263 71.4381 105.547 70.0937ZM107.481 81.582H104.481V77.582H107.481V81.582ZM92.7709 63.8017C91.4446 63.7296 90.6526 64.0462 90.2006 64.498C89.7487 64.95 89.4322 65.7419 89.5043 67.0683C89.5764 68.3939 90.0348 70.0787 90.9125 72.0292C91.6583 73.6867 92.6835 75.4816 93.9565 77.3398C95.2529 75.7354 96.6936 74.129 98.2621 72.5605C99.831 70.9916 101.438 69.5505 103.042 68.2538C101.184 66.9808 99.3885 65.9558 97.7309 65.2099C95.7805 64.3323 94.0965 63.8738 92.7709 63.8017ZM118.325 63.8027C116.999 63.8747 115.314 64.3322 113.364 65.2099C111.706 65.9558 109.91 66.9805 108.051 68.2538C109.656 69.5504 111.263 70.9908 112.831 72.5595C114.4 74.128 115.84 75.7355 117.136 77.3398C118.41 75.481 119.436 73.6861 120.182 72.0283C121.06 70.0779 121.518 68.3938 121.59 67.0683C121.662 65.7421 121.346 64.95 120.894 64.498C120.442 64.0463 119.651 63.7307 118.325 63.8027Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

@@ -0,0 +1,78 @@
---
display_name: Gemini CLI
icon: ../../../../.icons/gemini.svg
description: Run Gemini CLI in your workspace with AgentAPI integration
verified: true
tags: [agent, gemini, ai, google, tasks]
---
# Gemini CLI
Run [Gemini CLI](https://ai.google.dev/gemini-api/docs/cli) in your workspace to access Google's Gemini AI models, and custom pre/post install scripts. This module integrates with [AgentAPI](https://github.com/coder/agentapi) for Coder Tasks compatibility.
```tf
module "gemini" {
source = "registry.coder.com/coder-labs/gemini/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
gemini_api_key = var.gemini_api_key
gemini_model = "gemini-2.5-pro"
install_gemini = true
gemini_version = "latest"
agentapi_version = "latest"
}
```
## Prerequisites
- You must add the [Coder Login](https://registry.coder.com/modules/coder-login/coder) module to your template
- Node.js and npm will be installed automatically if not present
## Usage Example
- Example 1:
```tf
variable "gemini_api_key" {
type = string
description = "Gemini API key"
sensitive = true
}
module "gemini" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder-labs/gemini/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
gemini_api_key = var.gemini_api_key # we recommend providing this parameter inorder to have a smoother experience (i.e. no google sign-in)
gemini_model = "gemini-2.5-flash"
install_gemini = true
gemini_version = "latest"
gemini_instruction_prompt = "Start every response with `Gemini says:`"
}
```
## How it Works
- **Install**: The module installs Gemini CLI using npm (installs Node.js via NVM if needed)
- **Instruction Prompt**: If `GEMINI_INSTRUCTION_PROMPT` and `GEMINI_START_DIRECTORY` are set, creates the directory (if needed) and writes the prompt to `GEMINI.md`
- **Start**: Launches Gemini CLI in the specified directory, wrapped by AgentAPI
- **Environment**: Sets `GEMINI_API_KEY`, `GOOGLE_GENAI_USE_VERTEXAI`, `GEMINI_MODEL` for the CLI (if variables provided)
## Troubleshooting
- If Gemini CLI is not found, ensure `install_gemini = true` and your API key is valid
- Node.js and npm are installed automatically if missing (using NVM)
- Check logs in `/home/coder/.gemini-module/` for install/start output
- We highly recommend using the `gemini_api_key` variable, this also ensures smooth tasks running without needing to sign in to Google.
> [!IMPORTANT]
> To use tasks with Gemini CLI, ensure you have the `gemini_api_key` variable set, and **you pass the `AI Prompt` Parameter**.
> By default we inject the "theme": "Default" and "selectedAuthType": "gemini-api-key" to your ~/.gemini/settings.json along with the coder mcp server.
> In `gemini_instruction_prompt` and `AI Prompt` text we recommend using (\`\`) backticks instead of quotes to avoid escaping issues. Eg: gemini_instruction_prompt = "Start every response with \`Gemini says:\` "
## References
- [Gemini CLI Documentation](https://ai.google.dev/gemini-api/docs/cli)
- [AgentAPI Documentation](https://github.com/coder/agentapi)
- [Coder AI Agents Guide](https://coder.com/docs/tutorials/ai-agents)
@@ -0,0 +1,207 @@
import {
test,
afterEach,
describe,
setDefaultTimeout,
beforeAll,
expect,
} from "bun:test";
import { execContainer, readFileContainer, runTerraformInit } from "~test";
import {
loadTestFile,
writeExecutable,
setup as setupUtil,
execModuleScript,
expectAgentAPIStarted,
} from "../../../coder/modules/agentapi/test-util";
let cleanupFunctions: (() => Promise<void>)[] = [];
const registerCleanup = (cleanup: () => Promise<void>) => {
cleanupFunctions.push(cleanup);
};
afterEach(async () => {
const cleanupFnsCopy = cleanupFunctions.slice().reverse();
cleanupFunctions = [];
for (const cleanup of cleanupFnsCopy) {
try {
await cleanup();
} catch (error) {
console.error("Error during cleanup:", error);
}
}
});
interface SetupProps {
skipAgentAPIMock?: boolean;
skipGeminiMock?: boolean;
moduleVariables?: Record<string, string>;
agentapiMockScript?: string;
}
const setup = async (props?: SetupProps): Promise<{ id: string }> => {
const projectDir = "/home/coder/project";
const { id } = await setupUtil({
moduleDir: import.meta.dir,
moduleVariables: {
install_gemini: props?.skipGeminiMock ? "true" : "false",
install_agentapi: props?.skipAgentAPIMock ? "true" : "false",
gemini_model: "test-model",
...props?.moduleVariables,
},
registerCleanup,
projectDir,
skipAgentAPIMock: props?.skipAgentAPIMock,
agentapiMockScript: props?.agentapiMockScript,
});
if (!props?.skipGeminiMock) {
await writeExecutable({
containerId: id,
filePath: "/usr/bin/gemini",
content: await loadTestFile(import.meta.dir, "gemini-mock.sh"),
});
}
return { id };
};
setDefaultTimeout(60 * 1000);
describe("gemini", async () => {
beforeAll(async () => {
await runTerraformInit(import.meta.dir);
});
test("happy-path", async () => {
const { id } = await setup();
await execModuleScript(id);
await expectAgentAPIStarted(id);
});
test("install-gemini-version", async () => {
const version_to_install = "0.1.13";
const { id } = await setup({
skipGeminiMock: true,
moduleVariables: {
install_gemini: "true",
gemini_version: version_to_install,
},
});
await execModuleScript(id);
const resp = await execContainer(id, [
"bash",
"-c",
`cat /home/coder/.gemini-module/install.log || true`,
]);
expect(resp.stdout).toContain(version_to_install);
});
test("gemini-settings-json", async () => {
const settings = '{"foo": "bar"}';
const { id } = await setup({
moduleVariables: {
gemini_settings_json: settings,
},
});
await execModuleScript(id);
const resp = await readFileContainer(id, "/home/coder/.gemini/settings.json");
expect(resp).toContain("foo");
expect(resp).toContain("bar");
});
test("gemini-api-key", async () => {
const apiKey = "test-api-key-123";
const { id } = await setup({
moduleVariables: {
gemini_api_key: apiKey,
},
});
await execModuleScript(id);
const resp = await readFileContainer(id, "/home/coder/.gemini-module/agentapi-start.log");
expect(resp).toContain("gemini_api_key provided !");
});
test("use-vertexai", async () => {
const { id } = await setup({
skipGeminiMock: false,
moduleVariables: {
use_vertexai: "true",
},
});
await execModuleScript(id);
const resp = await readFileContainer(id, "/home/coder/.gemini-module/install.log");
expect(resp).toContain('GOOGLE_GENAI_USE_VERTEXAI=\'true\'');
});
test("gemini-model", async () => {
const model = "gemini-2.5-pro";
const { id } = await setup({
skipGeminiMock: false,
moduleVariables: {
gemini_model: model,
},
});
await execModuleScript(id);
const resp = await readFileContainer(id, "/home/coder/.gemini-module/install.log");
expect(resp).toContain(model);
});
test("pre-post-install-scripts", async () => {
const { id } = await setup({
moduleVariables: {
pre_install_script: "#!/bin/bash\necho 'pre-install-script'",
post_install_script: "#!/bin/bash\necho 'post-install-script'",
},
});
await execModuleScript(id);
const preInstallLog = await readFileContainer(id, "/home/coder/.gemini-module/pre_install.log");
expect(preInstallLog).toContain("pre-install-script");
const postInstallLog = await readFileContainer(id, "/home/coder/.gemini-module/post_install.log");
expect(postInstallLog).toContain("post-install-script");
});
test("folder-variable", async () => {
const folder = "/tmp/gemini-test-folder";
const { id } = await setup({
skipGeminiMock: false,
moduleVariables: {
folder,
},
});
await execModuleScript(id);
const resp = await readFileContainer(id, "/home/coder/.gemini-module/install.log");
expect(resp).toContain(folder);
});
test("additional-extensions", async () => {
const additional = '{"custom": {"enabled": true}}';
const { id } = await setup({
moduleVariables: {
additional_extensions: additional,
},
});
await execModuleScript(id);
const resp = await readFileContainer(id, "/home/coder/.gemini/settings.json");
expect(resp).toContain("custom");
expect(resp).toContain("enabled");
});
test("gemini-system-prompt", async () => {
const prompt = "This is a system prompt for Gemini.";
const { id } = await setup({
moduleVariables: {
gemini_system_prompt: prompt,
},
});
await execModuleScript(id);
const resp = await readFileContainer(id, "/home/coder/GEMINI.md");
expect(resp).toContain(prompt);
});
test("start-without-prompt", async () => {
const { id } = await setup();
await execModuleScript(id);
const prompt = await execContainer(id, ["ls", "-l", "/home/coder/GEMINI.md"]);
expect(prompt.exitCode).not.toBe(0);
expect(prompt.stderr).toContain("No such file or directory");
});
});
+215
View File
@@ -0,0 +1,215 @@
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/gemini.svg"
}
variable "folder" {
type = string
description = "The folder to run Gemini in."
default = "/home/coder"
}
variable "install_gemini" {
type = bool
description = "Whether to install Gemini."
default = true
}
variable "gemini_version" {
type = string
description = "The version of Gemini to install."
default = ""
}
variable "gemini_settings_json" {
type = string
description = "json to use in ~/.gemini/settings.json."
default = ""
}
variable "gemini_api_key" {
type = string
description = "Gemini API Key"
default = ""
}
variable "use_vertexai" {
type = bool
description = "Whether to use vertex ai"
default = false
}
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.0"
}
variable "gemini_model" {
type = string
description = "The model to use for Gemini (e.g., gemini-2.5-pro)."
default = ""
}
variable "pre_install_script" {
type = string
description = "Custom script to run before installing Gemini."
default = null
}
variable "post_install_script" {
type = string
description = "Custom script to run after installing Gemini."
default = null
}
data "coder_parameter" "ai_prompt" {
type = "string"
name = "AI Prompt"
default = ""
description = "Initial prompt for the Gemini CLI"
mutable = true
}
variable "additional_extensions" {
type = string
description = "Additional extensions configuration in json format to append to the config."
default = null
}
variable "gemini_system_prompt" {
type = string
description = "System prompt for Gemini. It will be added to GEMINI.md in the specified folder."
default = ""
}
resource "coder_env" "gemini_api_key" {
agent_id = var.agent_id
name = "GEMINI_API_KEY"
value = var.gemini_api_key
}
resource "coder_env" "gemini_use_vertex_ai" {
agent_id = var.agent_id
name = "GOOGLE_GENAI_USE_VERTEXAI"
value = var.use_vertexai
}
locals {
base_extensions = <<-EOT
{
"coder": {
"args": [
"exp",
"mcp",
"server"
],
"command": "coder",
"description": "Report ALL tasks and statuses (in progress, done, failed) you are working on.",
"enabled": true,
"env": {
"CODER_MCP_APP_STATUS_SLUG": "${local.app_slug}",
"CODER_MCP_AI_AGENTAPI_URL": "http://localhost:3284"
},
"name": "Coder",
"timeout": 3000,
"type": "stdio",
"trust": true
}
}
EOT
app_slug = "gemini"
install_script = file("${path.module}/scripts/install.sh")
start_script = file("${path.module}/scripts/start.sh")
module_dir_name = ".gemini-module"
}
module "agentapi" {
source = "registry.coder.com/coder/agentapi/coder"
version = "1.0.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 = "Gemini"
cli_app_slug = "${local.app_slug}-cli"
cli_app_display_name = "Gemini CLI"
module_dir_name = local.module_dir_name
install_agentapi = var.install_agentapi
agentapi_version = var.agentapi_version
pre_install_script = var.pre_install_script
post_install_script = var.post_install_script
start_script = <<-EOT
#!/bin/bash
set -o errexit
set -o pipefail
echo -n '${base64encode(local.start_script)}' | base64 -d > /tmp/start.sh
chmod +x /tmp/start.sh
GEMINI_API_KEY='${var.gemini_api_key}' \
GOOGLE_GENAI_USE_VERTEXAI='${var.use_vertexai}' \
GEMINI_MODEL='${var.gemini_model}' \
GEMINI_START_DIRECTORY='${var.folder}' \
GEMINI_TASK_PROMPT='${base64encode(data.coder_parameter.ai_prompt.value)}' \
/tmp/start.sh
EOT
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_INSTALL='${var.install_gemini}' \
ARG_GEMINI_VERSION='${var.gemini_version}' \
ARG_GEMINI_CONFIG='${base64encode(var.gemini_settings_json)}' \
BASE_EXTENSIONS='${base64encode(replace(local.base_extensions, "'", "'\\''"))}' \
ADDITIONAL_EXTENSIONS='${base64encode(replace(var.additional_extensions != null ? var.additional_extensions : "", "'", "'\\''"))}' \
GEMINI_START_DIRECTORY='${var.folder}' \
GEMINI_INSTRUCTION_PROMPT='${base64encode(var.gemini_system_prompt)}' \
/tmp/install.sh
EOT
}
@@ -0,0 +1,175 @@
#!/bin/bash
BOLD='\033[0;1m'
# Function to check if a command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
set -o nounset
ARG_GEMINI_CONFIG=$(echo -n "$ARG_GEMINI_CONFIG" | base64 -d)
BASE_EXTENSIONS=$(echo -n "$BASE_EXTENSIONS" | base64 -d)
ADDITIONAL_EXTENSIONS=$(echo -n "$ADDITIONAL_EXTENSIONS" | base64 -d)
GEMINI_INSTRUCTION_PROMPT=$(echo -n "$GEMINI_INSTRUCTION_PROMPT" | base64 -d)
echo "--------------------------------"
printf "gemini_config: %s\n" "$ARG_GEMINI_CONFIG"
printf "install: %s\n" "$ARG_INSTALL"
printf "gemini_version: %s\n" "$ARG_GEMINI_VERSION"
echo "--------------------------------"
set +o nounset
function install_node() {
# borrowed from claude-code module
if ! command_exists npm; then
printf "npm not found, checking for Node.js installation...\n"
if ! command_exists node; then
printf "Node.js not found, installing Node.js via NVM...\n"
export NVM_DIR="$HOME/.nvm"
if [ ! -d "$NVM_DIR" ]; then
mkdir -p "$NVM_DIR"
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
else
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
fi
nvm install --lts
nvm use --lts
nvm alias default node
printf "Node.js installed: %s\n" "$(node --version)"
printf "npm installed: %s\n" "$(npm --version)"
else
printf "Node.js is installed but npm is not available. Please install npm manually.\n"
exit 1
fi
fi
}
function install_gemini() {
if [ "${ARG_INSTALL}" = "true" ]; then
# we need node to install and run gemini-cli
install_node
# If nvm does not exist, we will create a global npm directory (this os to prevent the possibility of EACCESS issues on npm -g)
if ! command_exists nvm; then
printf "which node: %s\n" "$(which node)"
printf "which npm: %s\n" "$(which npm)"
# Create a directory for global packages
mkdir -p "$HOME"/.npm-global
# Configure npm to use it
npm config set prefix "$HOME/.npm-global"
# Add to PATH for current session
export PATH="$HOME/.npm-global/bin:$PATH"
# Add to shell profile for future sessions
if ! grep -q "export PATH=$HOME/.npm-global/bin:\$PATH" ~/.bashrc; then
echo "export PATH=$HOME/.npm-global/bin:\$PATH" >> ~/.bashrc
fi
fi
printf "%s Installing Gemini CLI\n" "${BOLD}"
if [ -n "$ARG_GEMINI_VERSION" ]; then
npm install -g "@google/gemini-cli@$ARG_GEMINI_VERSION"
else
npm install -g "@google/gemini-cli"
fi
printf "%s Successfully installed Gemini CLI. Version: %s\n" "${BOLD}" "$(gemini --version)"
fi
}
function populate_settings_json() {
if [ "${ARG_GEMINI_CONFIG}" != "" ]; then
SETTINGS_PATH="$HOME/.gemini/settings.json"
mkdir -p "$(dirname "$SETTINGS_PATH")"
printf "Custom gemini_config is provided !\n"
echo "${ARG_GEMINI_CONFIG}" > "$HOME/.gemini/settings.json"
else
printf "No custom gemini_config provided, using default settings.json.\n"
append_extensions_to_settings_json
fi
}
function append_extensions_to_settings_json() {
SETTINGS_PATH="$HOME/.gemini/settings.json"
mkdir -p "$(dirname "$SETTINGS_PATH")"
printf "[append_extensions_to_settings_json] Starting extension merge process...\n"
if [ -z "${BASE_EXTENSIONS:-}" ]; then
printf "[append_extensions_to_settings_json] BASE_EXTENSIONS is empty, skipping merge.\n"
return
fi
if [ ! -f "$SETTINGS_PATH" ]; then
printf "%s does not exist. Creating with merged mcpServers structure.\n" "$SETTINGS_PATH"
# If ADDITIONAL_EXTENSIONS is not set or empty, use '{}'
ADD_EXT_JSON='{}'
if [ -n "${ADDITIONAL_EXTENSIONS:-}" ]; then
ADD_EXT_JSON="$ADDITIONAL_EXTENSIONS"
fi
printf '{"mcpServers":%s}\n' "$(jq -s 'add' <(echo "$BASE_EXTENSIONS") <(echo "$ADD_EXT_JSON"))" > "$SETTINGS_PATH"
fi
# Prepare temp files
TMP_SETTINGS=$(mktemp)
# If ADDITIONAL_EXTENSIONS is not set or empty, use '{}'
ADD_EXT_JSON='{}'
if [ -n "${ADDITIONAL_EXTENSIONS:-}" ]; then
printf "[append_extensions_to_settings_json] ADDITIONAL_EXTENSIONS is set.\n"
ADD_EXT_JSON="$ADDITIONAL_EXTENSIONS"
else
printf "[append_extensions_to_settings_json] ADDITIONAL_EXTENSIONS is empty or not set.\n"
fi
printf "[append_extensions_to_settings_json] Merging BASE_EXTENSIONS and ADDITIONAL_EXTENSIONS into mcpServers...\n"
jq --argjson base "$BASE_EXTENSIONS" --argjson add "$ADD_EXT_JSON" \
'.mcpServers = (.mcpServers // {} + $base + $add)' \
"$SETTINGS_PATH" > "$TMP_SETTINGS" && mv "$TMP_SETTINGS" "$SETTINGS_PATH"
# Add theme and selectedAuthType fields
jq '.theme = "Default" | .selectedAuthType = "gemini-api-key"' "$SETTINGS_PATH" > "$TMP_SETTINGS" && mv "$TMP_SETTINGS" "$SETTINGS_PATH"
printf "[append_extensions_to_settings_json] Merge complete.\n"
}
function add_instruction_prompt_if_exists() {
if [ -n "${GEMINI_INSTRUCTION_PROMPT:-}" ]; then
if [ -d "${GEMINI_START_DIRECTORY}" ]; then
printf "Directory '%s' exists. Changing to it.\\n" "${GEMINI_START_DIRECTORY}"
cd "${GEMINI_START_DIRECTORY}" || {
printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}"
exit 1
}
else
printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${GEMINI_START_DIRECTORY}"
mkdir -p "${GEMINI_START_DIRECTORY}" || {
printf "Error: Could not create directory '%s'.\\n" "${GEMINI_START_DIRECTORY}"
exit 1
}
cd "${GEMINI_START_DIRECTORY}" || {
printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}"
exit 1
}
fi
touch GEMINI.md
printf "Setting GEMINI.md\n"
echo "${GEMINI_INSTRUCTION_PROMPT}" > GEMINI.md
else
printf "GEMINI.md is not set.\n"
fi
}
# Install Gemini
install_gemini
gemini --version
populate_settings_json
add_instruction_prompt_if_exists
@@ -0,0 +1,62 @@
#!/bin/bash
# Load shell environment
source "$HOME"/.bashrc
command_exists() {
command -v "$1" >/dev/null 2>&1
}
if [ -f "$HOME/.nvm/nvm.sh" ]; then
source "$HOME"/.nvm/nvm.sh
else
export PATH="$HOME/.npm-global/bin:$PATH"
fi
printf "Version: %s\n" "$(gemini --version)"
GEMINI_TASK_PROMPT=$(echo -n "$GEMINI_TASK_PROMPT" | base64 -d)
if command_exists gemini; then
printf "Gemini is installed\n"
else
printf "Error: Gemini is not installed. Please enable install_gemini or install it manually :)\n"
exit 1
fi
if [ -d "${GEMINI_START_DIRECTORY}" ]; then
printf "Directory '%s' exists. Changing to it.\\n" "${GEMINI_START_DIRECTORY}"
cd "${GEMINI_START_DIRECTORY}" || {
printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}"
exit 1
}
else
printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${GEMINI_START_DIRECTORY}"
mkdir -p "${GEMINI_START_DIRECTORY}" || {
printf "Error: Could not create directory '%s'.\\n" "${GEMINI_START_DIRECTORY}"
exit 1
}
cd "${GEMINI_START_DIRECTORY}" || {
printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}"
exit 1
}
fi
if [ -n "$GEMINI_TASK_PROMPT" ]; then
printf "Running the task prompt %s\n" "$GEMINI_TASK_PROMPT"
PROMPT="Every step of the way, report tasks to Coder with proper descriptions and statuses. Your task at hand: $GEMINI_TASK_PROMPT"
GEMINI_ARGS=(--prompt-interactive "$PROMPT")
else
printf "No task prompt given.\n"
GEMINI_ARGS=()
fi
if [ -n "$GEMINI_API_KEY" ]; then
printf "gemini_api_key provided !\n"
else
printf "gemini_api_key not provided\n"
fi
# use low width to fit in the tasks UI sidebar. height is adjusted so that width x height ~= 80x1000 characters
# are visible in the terminal screen by default.
agentapi server --term-width 67 --term-height 1190 -- gemini "${GEMINI_ARGS[@]}"
@@ -0,0 +1,14 @@
#!/bin/bash
if [[ "$1" == "--version" ]]; then
echo "HELLO: $(bash -c env)"
echo "gemini version v2.5.0"
exit 0
fi
set -e
while true; do
echo "$(date) - gemini-mock"
sleep 15
done
@@ -0,0 +1,58 @@
---
display_name: Docker Build
description: Build Docker containers from Dockerfile as Coder workspaces
icon: ../../../../.icons/docker.svg
verified: true
tags: [docker, container, dockerfile]
---
# Remote Development on Docker Containers (Build from Dockerfile)
Build and provision Docker containers from a Dockerfile as [Coder workspaces](https://coder.com/docs/workspaces) with this example template.
This template builds a custom Docker image from the included Dockerfile, allowing you to customize the development environment by modifying the Dockerfile rather than using a pre-built image.
<!-- TODO: Add screenshot -->
## Prerequisites
### Infrastructure
The VM you run Coder on must have a running Docker socket and the `coder` user must be added to the Docker group:
```sh
# Add coder user to Docker group
sudo adduser coder docker
# Restart Coder server
sudo systemctl restart coder
# Test Docker
sudo -u coder docker ps
```
## Architecture
This template provisions the following resources:
- Docker image (built from Dockerfile and kept locally)
- Docker container pod (ephemeral)
- Docker volume (persistent on `/home/coder`)
This means, when the workspace restarts, any tools or files outside of the home directory are not persisted. To pre-bake tools into the workspace (e.g. `python3`), modify the `build/Dockerfile`. Alternatively, individual developers can [personalize](https://coder.com/docs/dotfiles) their workspaces with dotfiles.
> [!NOTE]
> This template is designed to be a starting point! Edit the Terraform and Dockerfile to extend the template to support your use case.
### Editing the image
Edit the `build/Dockerfile` and run `coder templates push` to update workspaces. The image will be rebuilt automatically when the Dockerfile changes.
## Difference from the standard Docker template
The main difference between this template and the standard Docker template is:
- **Standard Docker template**: Uses a pre-built image (e.g., `codercom/enterprise-base:ubuntu`)
- **Docker Build template**: Builds a custom image from the included `build/Dockerfile`
This allows for more customization of the development environment while maintaining the same workspace functionality.
@@ -0,0 +1,18 @@
FROM ubuntu
RUN apt-get update \
&& apt-get install -y \
curl \
git \
golang \
sudo \
vim \
wget \
&& rm -rf /var/lib/apt/lists/*
ARG USER=coder
RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \
&& echo "${USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/${USER} \
&& chmod 0440 /etc/sudoers.d/${USER}
USER ${USER}
WORKDIR /home/${USER}
@@ -0,0 +1,222 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
}
docker = {
source = "kreuzwerker/docker"
}
}
}
locals {
username = data.coder_workspace_owner.me.name
}
variable "docker_socket" {
default = ""
description = "(Optional) Docker socket URI"
type = string
}
provider "docker" {
# Defaulting to null if the variable is an empty string lets us have an optional variable without having to set our own default
host = var.docker_socket != "" ? var.docker_socket : null
}
data "coder_provisioner" "me" {}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}
resource "coder_agent" "main" {
arch = data.coder_provisioner.me.arch
os = "linux"
startup_script = <<-EOT
set -e
# Prepare user home with default files on first start.
if [ ! -f ~/.init_done ]; then
cp -rT /etc/skel ~
touch ~/.init_done
fi
# Install the latest code-server.
# Append "--version x.x.x" to install a specific version of code-server.
curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
# Start code-server in the background.
/tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
EOT
# These environment variables allow you to make Git commits right away after creating a
# workspace. Note that they take precedence over configuration defined in ~/.gitconfig!
# You can remove this block if you'd prefer to configure Git manually or using
# dotfiles. (see docs/dotfiles.md)
env = {
GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}"
GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
}
# The following metadata blocks are optional. They are used to display
# information about your workspace in the dashboard. You can remove them
# if you don't want to display any information.
# For basic resources, you can use the `coder stat` command.
# If you need more control, you can write your own script.
metadata {
display_name = "CPU Usage"
key = "0_cpu_usage"
script = "coder stat cpu"
interval = 10
timeout = 1
}
metadata {
display_name = "RAM Usage"
key = "1_ram_usage"
script = "coder stat mem"
interval = 10
timeout = 1
}
metadata {
display_name = "Home Disk"
key = "3_home_disk"
script = "coder stat disk --path $${HOME}"
interval = 60
timeout = 1
}
metadata {
display_name = "CPU Usage (Host)"
key = "4_cpu_usage_host"
script = "coder stat cpu --host"
interval = 10
timeout = 1
}
metadata {
display_name = "Memory Usage (Host)"
key = "5_mem_usage_host"
script = "coder stat mem --host"
interval = 10
timeout = 1
}
metadata {
display_name = "Load Average (Host)"
key = "6_load_host"
# get load avg scaled by number of cores
script = <<EOT
echo "`cat /proc/loadavg | awk '{ print $1 }'` `nproc`" | awk '{ printf "%0.2f", $1/$2 }'
EOT
interval = 60
timeout = 1
}
metadata {
display_name = "Swap Usage (Host)"
key = "7_swap_host"
script = <<EOT
free -b | awk '/^Swap/ { printf("%.1f/%.1f", $3/1024.0/1024.0/1024.0, $2/1024.0/1024.0/1024.0) }'
EOT
interval = 10
timeout = 1
}
}
resource "coder_app" "code-server" {
agent_id = coder_agent.main.id
slug = "code-server"
display_name = "code-server"
url = "http://localhost:13337/?folder=/home/${local.username}"
icon = "/icon/code.svg"
subdomain = false
share = "owner"
healthcheck {
url = "http://localhost:13337/healthz"
interval = 5
threshold = 6
}
}
resource "docker_volume" "home_volume" {
name = "coder-${data.coder_workspace.me.id}-home"
# Protect the volume from being deleted due to changes in attributes.
lifecycle {
ignore_changes = all
}
# Add labels in Docker to keep track of orphan resources.
labels {
label = "coder.owner"
value = data.coder_workspace_owner.me.name
}
labels {
label = "coder.owner_id"
value = data.coder_workspace_owner.me.id
}
labels {
label = "coder.workspace_id"
value = data.coder_workspace.me.id
}
# This field becomes outdated if the workspace is renamed but can
# be useful for debugging or cleaning out dangling volumes.
labels {
label = "coder.workspace_name_at_creation"
value = data.coder_workspace.me.name
}
}
resource "docker_image" "main" {
name = "coder-${data.coder_workspace.me.id}"
build {
context = "./build"
build_args = {
USER = local.username
}
}
triggers = {
dir_sha1 = sha1(join("", [for f in fileset(path.module, "build/*") : filesha1(f)]))
}
}
resource "docker_container" "workspace" {
count = data.coder_workspace.me.start_count
image = docker_image.main.name
# Uses lower() to avoid Docker restriction on container names.
name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
# Hostname makes the shell more user friendly: coder@my-workspace:~$
hostname = data.coder_workspace.me.name
# Use the docker gateway if the access URL is 127.0.0.1
entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")]
env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"]
host {
host = "host.docker.internal"
ip = "host-gateway"
}
volumes {
container_path = "/home/${local.username}"
volume_name = docker_volume.home_volume.name
read_only = false
}
# Add labels in Docker to keep track of orphan resources.
labels {
label = "coder.owner"
value = data.coder_workspace_owner.me.name
}
labels {
label = "coder.owner_id"
value = data.coder_workspace_owner.me.id
}
labels {
label = "coder.workspace_id"
value = data.coder_workspace.me.id
}
labels {
label = "coder.workspace_name"
value = data.coder_workspace.me.name
}
}
@@ -2,7 +2,6 @@
display_name: Tasks on Docker
description: Run Coder Tasks on Docker with an example application
icon: ../../../../.icons/tasks.svg
maintainer_github: coder-labs
verified: false
tags: [docker, container, ai, tasks]
---
@@ -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
+7 -7
View File
@@ -1,22 +1,22 @@
---
display_name: AgentAPI
description: Building block for modules that need to run an agentapi server
description: Building block for modules that need to run an AgentAPI server
icon: ../../../../.icons/coder.svg
maintainer_github: coder
verified: true
tags: [internal]
tags: [internal, library]
---
# AgentAPI
The AgentAPI module is a building block for modules that need to run an agentapi server. It is intended primarily for internal use by Coder to create modules compatible with Tasks.
> [!CAUTION]
> We do not recommend using this module directly. Instead, please consider using one of our [Tasks-compatible AI agent modules](https://registry.coder.com/modules?search=tag%3Atasks).
We do not recommend using this module directly. Instead, please consider using one of our [Tasks-compatible AI agent modules](https://registry.coder.com/modules?search=tag%3Atasks).
The AgentAPI module is a building block for modules that need to run an AgentAPI server. It is intended primarily for internal use by Coder to create modules compatible with Tasks.
```tf
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
@@ -51,4 +51,4 @@ module "agentapi" {
## For module developers
For a complete example of how to use this module, see the [goose module](https://github.com/coder/registry/blob/main/registry/coder/modules/goose/main.tf).
For a complete example of how to use this module, see the [Goose module](https://github.com/coder/registry/blob/main/registry/coder/modules/goose/main.tf).
@@ -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
+8 -34
View File
@@ -2,7 +2,6 @@
display_name: Aider
description: Run Aider AI pair programming in your workspace
icon: ../../../../.icons/aider.svg
maintainer_github: coder
verified: true
tags: [agent, ai, aider]
---
@@ -14,7 +13,7 @@ Run [Aider](https://aider.chat) AI pair programming in your workspace. This modu
```tf
module "aider" {
source = "registry.coder.com/coder/aider/coder"
version = "1.1.0"
version = "1.1.2"
agent_id = coder_agent.example.id
}
```
@@ -31,29 +30,8 @@ module "aider" {
## Module Parameters
| Parameter | Description | Type | Default |
| ---------------------------------- | -------------------------------------------------------------------------- | -------- | ------------------- |
| `agent_id` | The ID of a Coder agent (required) | `string` | - |
| `folder` | The folder to run Aider in | `string` | `/home/coder` |
| `install_aider` | Whether to install Aider | `bool` | `true` |
| `aider_version` | The version of Aider to install | `string` | `"latest"` |
| `use_screen` | Whether to use screen for running Aider in the background | `bool` | `true` |
| `use_tmux` | Whether to use tmux instead of screen for running Aider in the background | `bool` | `false` |
| `session_name` | Name for the persistent session (screen or tmux) | `string` | `"aider"` |
| `order` | Position of the app in the UI presentation | `number` | `null` |
| `icon` | The icon to use for the app | `string` | `"/icon/aider.svg"` |
| `experiment_report_tasks` | Whether to enable task reporting | `bool` | `true` |
| `system_prompt` | System prompt for instructing Aider on task reporting and behavior | `string` | See default in code |
| `task_prompt` | Task prompt to use with Aider | `string` | `""` |
| `ai_provider` | AI provider to use with Aider (openai, anthropic, azure, etc.) | `string` | `"anthropic"` |
| `ai_model` | AI model to use (can use Aider's built-in aliases like "sonnet", "4o") | `string` | `"sonnet"` |
| `ai_api_key` | API key for the selected AI provider | `string` | `""` |
| `custom_env_var_name` | Custom environment variable name when using custom provider | `string` | `""` |
| `experiment_pre_install_script` | Custom script to run before installing Aider | `string` | `null` |
| `experiment_post_install_script` | Custom script to run after installing Aider | `string` | `null` |
| `experiment_additional_extensions` | Additional extensions configuration in YAML format to append to the config | `string` | `null` |
> **Note**: `use_screen` and `use_tmux` cannot both be enabled at the same time. By default, `use_screen` is set to `true` and `use_tmux` is set to `false`.
> [!NOTE]
> The `use_screen` and `use_tmux` parameters cannot both be enabled at the same time. By default, `use_screen` is set to `true` and `use_tmux` is set to `false`.
## Usage Examples
@@ -69,7 +47,7 @@ variable "anthropic_api_key" {
module "aider" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aider/coder"
version = "1.1.0"
version = "1.1.2"
agent_id = coder_agent.example.id
ai_api_key = var.anthropic_api_key
}
@@ -94,7 +72,7 @@ variable "openai_api_key" {
module "aider" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aider/coder"
version = "1.1.0"
version = "1.1.2"
agent_id = coder_agent.example.id
use_tmux = true
ai_provider = "openai"
@@ -115,7 +93,7 @@ variable "custom_api_key" {
module "aider" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aider/coder"
version = "1.1.0"
version = "1.1.2"
agent_id = coder_agent.example.id
ai_provider = "custom"
custom_env_var_name = "MY_CUSTOM_API_KEY"
@@ -132,7 +110,7 @@ You can extend Aider's capabilities by adding custom extensions:
module "aider" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aider/coder"
version = "1.1.0"
version = "1.1.2"
agent_id = coder_agent.example.id
ai_api_key = var.anthropic_api_key
@@ -211,7 +189,7 @@ data "coder_parameter" "ai_prompt" {
module "aider" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aider/coder"
version = "1.1.0"
version = "1.1.2"
agent_id = coder_agent.example.id
ai_api_key = var.anthropic_api_key
task_prompt = data.coder_parameter.ai_prompt.value
@@ -309,7 +287,3 @@ If you encounter issues:
3. **Browser mode issues**: If the browser interface doesn't open, check that you're accessing it from a machine that can reach your Coder workspace
For more information on using Aider, see the [Aider documentation](https://aider.chat/docs/).
```
```
@@ -2,7 +2,6 @@
display_name: Amazon DCV Windows
description: Amazon DCV Server and Web Client for Windows
icon: ../../../../.icons/dcv.svg
maintainer_github: coder
verified: true
tags: [windows, amazon, dcv, web, desktop]
---
@@ -19,7 +18,7 @@ Enable DCV Server and Web Client on Windows workspaces.
module "dcv" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/amazon-dcv-windows/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = resource.coder_agent.main.id
}
+5 -5
View File
@@ -2,7 +2,6 @@
display_name: Amazon Q
description: Run Amazon Q in your workspace to access Amazon's AI coding assistant.
icon: ../../../../.icons/amazon-q.svg
maintainer_github: coder
verified: true
tags: [agent, ai, aws, amazon-q]
---
@@ -14,8 +13,9 @@ Run [Amazon Q](https://aws.amazon.com/q/) in your workspace to access Amazon's A
```tf
module "amazon-q" {
source = "registry.coder.com/coder/amazon-q/coder"
version = "1.1.0"
version = "1.1.2"
agent_id = coder_agent.example.id
# Required: see below for how to generate
experiment_auth_tarball = var.amazon_q_auth_tarball
}
@@ -82,7 +82,7 @@ module "amazon-q" {
```tf
module "amazon-q" {
source = "registry.coder.com/coder/amazon-q/coder"
version = "1.1.0"
version = "1.1.2"
agent_id = coder_agent.example.id
experiment_auth_tarball = var.amazon_q_auth_tarball
experiment_use_tmux = true
@@ -94,7 +94,7 @@ module "amazon-q" {
```tf
module "amazon-q" {
source = "registry.coder.com/coder/amazon-q/coder"
version = "1.1.0"
version = "1.1.2"
agent_id = coder_agent.example.id
experiment_auth_tarball = var.amazon_q_auth_tarball
experiment_report_tasks = true
@@ -106,7 +106,7 @@ module "amazon-q" {
```tf
module "amazon-q" {
source = "registry.coder.com/coder/amazon-q/coder"
version = "1.1.0"
version = "1.1.2"
agent_id = coder_agent.example.id
experiment_auth_tarball = var.amazon_q_auth_tarball
experiment_pre_install_script = "echo Pre-install!"
+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 -4
View File
@@ -2,7 +2,6 @@
display_name: AWS Region
description: A parameter with human region names and icons
icon: ../../../../.icons/aws.svg
maintainer_github: coder
verified: true
tags: [helper, parameter, regions, aws]
---
@@ -18,7 +17,7 @@ Customize the preselected parameter value:
module "aws-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aws-region/coder"
version = "1.0.12"
version = "1.0.31"
default = "us-east-1"
}
@@ -39,7 +38,7 @@ Change the display name and icon for a region using the corresponding maps:
module "aws-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aws-region/coder"
version = "1.0.12"
version = "1.0.31"
default = "ap-south-1"
custom_names = {
@@ -66,7 +65,7 @@ Hide the Asia Pacific regions Seoul and Osaka:
module "aws-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/aws-region/coder"
version = "1.0.12"
version = "1.0.31"
exclude = ["ap-northeast-2", "ap-northeast-3"]
}
@@ -2,7 +2,6 @@
display_name: Azure Region
description: A parameter with human region names and icons
icon: ../../../../.icons/azure.svg
maintainer_github: coder
verified: true
tags: [helper, parameter, azure, regions]
---
@@ -15,7 +14,7 @@ This module adds a parameter with all Azure regions, allowing developers to sele
module "azure_region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/azure-region/coder"
version = "1.0.12"
version = "1.0.31"
default = "eastus"
}
@@ -36,7 +35,7 @@ Change the display name and icon for a region using the corresponding maps:
module "azure-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/azure-region/coder"
version = "1.0.12"
version = "1.0.31"
custom_names = {
"australia" : "Go Australia!"
}
@@ -60,7 +59,7 @@ Hide all regions in Australia except australiacentral:
module "azure-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/azure-region/coder"
version = "1.0.12"
version = "1.0.31"
exclude = [
"australia",
"australiacentral2",
+3 -4
View File
@@ -2,7 +2,6 @@
display_name: Claude Code
description: Run Claude Code in your workspace
icon: ../../../../.icons/claude.svg
maintainer_github: coder
verified: true
tags: [agent, claude-code, ai, tasks]
---
@@ -14,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.2"
version = "2.0.6"
agent_id = coder_agent.example.id
folder = "/home/coder"
install_claude_code = true
@@ -85,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.2"
version = "2.0.6"
agent_id = coder_agent.example.id
folder = "/home/coder"
install_claude_code = true
@@ -103,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.2"
version = "2.0.6"
agent_id = coder_agent.example.id
folder = "/home/coder"
install_claude_code = true
+1 -1
View File
@@ -100,7 +100,7 @@ variable "install_agentapi" {
variable "agentapi_version" {
type = string
description = "The version of AgentAPI to install."
default = "v0.2.2"
default = "v0.3.0"
}
locals {
+7 -8
View File
@@ -2,7 +2,6 @@
display_name: code-server
description: VS Code in the browser
icon: ../../../../.icons/code.svg
maintainer_github: coder
verified: true
tags: [ide, web, code-server]
---
@@ -15,7 +14,7 @@ Automatically install [code-server](https://github.com/coder/code-server) in a w
module "code-server" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/code-server/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
}
```
@@ -30,7 +29,7 @@ module "code-server" {
module "code-server" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/code-server/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
install_version = "4.8.3"
}
@@ -44,7 +43,7 @@ Install the Dracula theme from [OpenVSX](https://open-vsx.org/):
module "code-server" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/code-server/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
extensions = [
"dracula-theme.theme-dracula"
@@ -62,7 +61,7 @@ Configure VS Code's [settings.json](https://code.visualstudio.com/docs/getstarte
module "code-server" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/code-server/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
extensions = ["dracula-theme.theme-dracula"]
settings = {
@@ -79,7 +78,7 @@ Just run code-server in the background, don't fetch it from GitHub:
module "code-server" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/code-server/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"]
}
@@ -95,7 +94,7 @@ Run an existing copy of code-server if found, otherwise download from GitHub:
module "code-server" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/code-server/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
use_cached = true
extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"]
@@ -108,7 +107,7 @@ Just run code-server in the background, don't fetch it from GitHub:
module "code-server" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/code-server/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
offline = true
}
+1 -2
View File
@@ -2,7 +2,6 @@
display_name: Coder Login
description: Automatically logs the user into Coder on their workspace
icon: ../../../../.icons/coder.svg
maintainer_github: coder
verified: true
tags: [helper]
---
@@ -15,7 +14,7 @@ Automatically logs the user into Coder when creating their workspace.
module "coder-login" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/coder-login/coder"
version = "1.0.15"
version = "1.0.31"
agent_id = coder_agent.example.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
+2 -3
View File
@@ -2,7 +2,6 @@
display_name: Cursor IDE
description: Add a one-click button to launch Cursor IDE
icon: ../../../../.icons/cursor.svg
maintainer_github: coder
verified: true
tags: [ide, cursor, ai]
---
@@ -17,7 +16,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder)
module "cursor" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/cursor/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
}
```
@@ -30,7 +29,7 @@ module "cursor" {
module "cursor" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/cursor/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
}
@@ -3,7 +3,6 @@ display_name: devcontainers-cli
description: devcontainers-cli module provides an easy way to install @devcontainers/cli into a workspace
icon: ../../../../.icons/devcontainers.svg
verified: true
maintainer_github: coder
tags: [devcontainers]
---
@@ -16,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.3"
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
+6 -7
View File
@@ -2,7 +2,6 @@
display_name: Dotfiles
description: Allow developers to optionally bring their own dotfiles repository to customize their shell and IDE settings!
icon: ../../../../.icons/dotfiles.svg
maintainer_github: coder
verified: true
tags: [helper, dotfiles]
---
@@ -19,7 +18,7 @@ Under the hood, this module uses the [coder dotfiles](https://coder.com/docs/v2/
module "dotfiles" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/dotfiles/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
}
```
@@ -32,7 +31,7 @@ module "dotfiles" {
module "dotfiles" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/dotfiles/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
}
```
@@ -43,7 +42,7 @@ module "dotfiles" {
module "dotfiles" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/dotfiles/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
user = "root"
}
@@ -55,14 +54,14 @@ module "dotfiles" {
module "dotfiles" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/dotfiles/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
}
module "dotfiles-root" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/dotfiles/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
user = "root"
dotfiles_uri = module.dotfiles.dotfiles_uri
@@ -77,7 +76,7 @@ You can set a default dotfiles repository for all users by setting the `default_
module "dotfiles" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/dotfiles/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
default_dotfiles_uri = "https://github.com/coder/dotfiles"
}
+4 -5
View File
@@ -2,7 +2,6 @@
display_name: File Browser
description: A file browser for your workspace
icon: ../../../../.icons/filebrowser.svg
maintainer_github: coder
verified: true
tags: [filebrowser, web]
---
@@ -15,7 +14,7 @@ A file browser for your workspace.
module "filebrowser" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/filebrowser/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
}
```
@@ -30,7 +29,7 @@ module "filebrowser" {
module "filebrowser" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/filebrowser/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
}
@@ -42,7 +41,7 @@ module "filebrowser" {
module "filebrowser" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/filebrowser/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
database_path = ".config/filebrowser.db"
}
@@ -54,7 +53,7 @@ module "filebrowser" {
module "filebrowser" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/filebrowser/coder"
version = "1.1.1"
version = "1.1.2"
agent_id = coder_agent.example.id
agent_name = "main"
subdomain = false
+3 -4
View File
@@ -2,7 +2,6 @@
display_name: Fly.io Region
description: A parameter with human region names and icons
icon: ../../../../.icons/fly.svg
maintainer_github: coder
verified: true
tags: [helper, parameter, fly.io, regions]
---
@@ -17,7 +16,7 @@ We can use the simplest format here, only adding a default selection as the `atl
module "fly-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/fly-region/coder"
version = "1.0.2"
version = "1.0.31"
default = "atl"
}
```
@@ -34,7 +33,7 @@ The regions argument can be used to display only the desired regions in the Code
module "fly-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/fly-region/coder"
version = "1.0.2"
version = "1.0.31"
default = "ams"
regions = ["ams", "arn", "atl"]
}
@@ -50,7 +49,7 @@ Set custom icons and names with their respective maps.
module "fly-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/fly-region/coder"
version = "1.0.2"
version = "1.0.31"
default = "ams"
custom_icons = {
+4 -5
View File
@@ -2,7 +2,6 @@
display_name: GCP Region
description: Add Google Cloud Platform regions to your Coder template.
icon: ../../../../.icons/gcp.svg
maintainer_github: coder
verified: true
tags: [gcp, regions, parameter, helper]
---
@@ -15,7 +14,7 @@ This module adds Google Cloud Platform regions to your Coder template.
module "gcp_region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/gcp-region/coder"
version = "1.0.12"
version = "1.0.31"
regions = ["us", "europe"]
}
@@ -36,7 +35,7 @@ Note: setting `gpu_only = true` and using a default region without GPU support,
module "gcp_region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/gcp-region/coder"
version = "1.0.12"
version = "1.0.31"
default = ["us-west1-a"]
regions = ["us-west1"]
gpu_only = false
@@ -53,7 +52,7 @@ resource "google_compute_instance" "example" {
module "gcp_region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/gcp-region/coder"
version = "1.0.12"
version = "1.0.31"
regions = ["europe-west"]
single_zone_per_region = false
}
@@ -69,7 +68,7 @@ resource "google_compute_instance" "example" {
module "gcp_region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/gcp-region/coder"
version = "1.0.12"
version = "1.0.31"
regions = ["us", "europe"]
gpu_only = true
single_zone_per_region = true
+9 -10
View File
@@ -2,7 +2,6 @@
display_name: Git Clone
description: Clone a Git repository by URL and skip if it exists.
icon: ../../../../.icons/git.svg
maintainer_github: coder
verified: true
tags: [git, helper]
---
@@ -15,7 +14,7 @@ This module allows you to automatically clone a repository by URL and skip if it
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
}
@@ -29,7 +28,7 @@ module "git-clone" {
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
base_dir = "~/projects/coder"
@@ -44,7 +43,7 @@ To use with [Git Authentication](https://coder.com/docs/v2/latest/admin/git-prov
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
}
@@ -70,7 +69,7 @@ data "coder_parameter" "git_repo" {
module "git_clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
url = data.coder_parameter.git_repo.value
}
@@ -104,7 +103,7 @@ Configuring `git-clone` for a self-hosted GitHub Enterprise Server running at `g
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
url = "https://github.example.com/coder/coder/tree/feat/example"
git_providers = {
@@ -123,7 +122,7 @@ To GitLab clone with a specific branch like `feat/example`
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
url = "https://gitlab.com/coder/coder/-/tree/feat/example"
}
@@ -135,7 +134,7 @@ Configuring `git-clone` for a self-hosted GitLab running at `gitlab.example.com`
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
url = "https://gitlab.example.com/coder/coder/-/tree/feat/example"
git_providers = {
@@ -156,7 +155,7 @@ For example, to clone the `feat/example` branch:
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
branch_name = "feat/example"
@@ -174,7 +173,7 @@ For example, this will clone into the `~/projects/coder/coder-dev` folder:
module "git-clone" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-clone/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
url = "https://github.com/coder/coder"
folder_name = "coder-dev"
@@ -2,7 +2,6 @@
display_name: Git commit signing
description: Configures Git to sign commits using your Coder SSH key
icon: ../../../../.icons/git.svg
maintainer_github: coder
verified: true
tags: [helper, git]
---
@@ -23,7 +22,7 @@ This module has a chance of conflicting with the user's dotfiles / the personali
module "git-commit-signing" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-commit-signing/coder"
version = "1.0.11"
version = "1.0.31"
agent_id = coder_agent.example.id
}
```
+3 -4
View File
@@ -2,7 +2,6 @@
display_name: Git Config
description: Stores Git configuration from Coder credentials
icon: ../../../../.icons/git.svg
maintainer_github: coder
verified: true
tags: [helper, git]
---
@@ -15,7 +14,7 @@ Runs a script that updates git credentials in the workspace to match the user's
module "git-config" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-config/coder"
version = "1.0.15"
version = "1.0.31"
agent_id = coder_agent.example.id
}
```
@@ -30,7 +29,7 @@ TODO: Add screenshot
module "git-config" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-config/coder"
version = "1.0.15"
version = "1.0.31"
agent_id = coder_agent.example.id
allow_email_change = true
}
@@ -44,7 +43,7 @@ TODO: Add screenshot
module "git-config" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/git-config/coder"
version = "1.0.15"
version = "1.0.31"
agent_id = coder_agent.example.id
allow_username_change = false
allow_email_change = false
@@ -2,7 +2,6 @@
display_name: Github Upload Public Key
description: Automates uploading Coder public key to Github so users don't have to.
icon: ../../../../.icons/github.svg
maintainer_github: coder
verified: true
tags: [helper, git]
---
@@ -15,7 +14,7 @@ Templates that utilize Github External Auth can automatically ensure that the Co
module "github-upload-public-key" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/github-upload-public-key/coder"
version = "1.0.15"
version = "1.0.31"
agent_id = coder_agent.example.id
}
```
@@ -48,7 +47,7 @@ data "coder_external_auth" "github" {
module "github-upload-public-key" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/github-upload-public-key/coder"
version = "1.0.15"
version = "1.0.31"
agent_id = coder_agent.example.id
external_auth_id = data.coder_external_auth.github.id
}
+2 -3
View File
@@ -2,7 +2,6 @@
display_name: Goose
description: Run Goose in your workspace
icon: ../../../../.icons/goose.svg
maintainer_github: coder
verified: true
tags: [agent, goose, ai, tasks]
---
@@ -14,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.0"
version = "2.1.0"
agent_id = coder_agent.example.id
folder = "/home/coder"
install_goose = true
@@ -80,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.0"
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}`);
@@ -2,8 +2,6 @@
display_name: "HCP Vault Secrets"
description: "Fetch secrets from HCP Vault"
icon: ../../../../.icons/vault.svg
maintainer_github: coder
partner_github: hashicorp
verified: true
tags: [integration, vault, hashicorp, hvs]
---
@@ -17,9 +15,9 @@ tags: [integration, vault, hashicorp, hvs]
>
> **Use these Coder registry modules instead:**
>
> - **[vault-token](https://registry.coder.com/modules/vault-token)** - Connect to Vault using access tokens
> - **[vault-jwt](https://registry.coder.com/modules/vault-jwt)** - Connect to Vault using JWT/OIDC authentication
> - **[vault-github](https://registry.coder.com/modules/vault-github)** - Connect to Vault using GitHub authentication
> - **[vault-token](https://registry.coder.com/modules/coder/vault-token)** - Connect to Vault using access tokens
> - **[vault-jwt](https://registry.coder.com/modules/coder/vault-jwt)** - Connect to Vault using JWT/OIDC authentication
> - **[vault-github](https://registry.coder.com/modules/coder/vault-github)** - Connect to Vault using GitHub authentication
>
> These modules work with both self-hosted Vault and HCP Vault Dedicated. For migration help, see the [official HashiCorp announcement](https://developer.hashicorp.com/hcp/docs/vault-secrets/end-of-sale-announcement).
@@ -28,7 +26,7 @@ This module lets you fetch all or selective secrets from a [HCP Vault Secrets](h
```tf
module "vault" {
source = "registry.coder.com/coder/hcp-vault-secrets/coder"
version = "1.0.32"
version = "1.0.34"
agent_id = coder_agent.example.id
app_name = "demo-app"
project_id = "aaa-bbb-ccc"
@@ -54,7 +52,7 @@ To fetch all secrets from the HCP Vault Secrets app, skip the `secrets` input.
```tf
module "vault" {
source = "registry.coder.com/coder/hcp-vault-secrets/coder"
version = "1.0.32"
version = "1.0.34"
agent_id = coder_agent.example.id
app_name = "demo-app"
project_id = "aaa-bbb-ccc"
@@ -68,7 +66,7 @@ To fetch selective secrets from the HCP Vault Secrets app, set the `secrets` inp
```tf
module "vault" {
source = "registry.coder.com/coder/hcp-vault-secrets/coder"
version = "1.0.32"
version = "1.0.34"
agent_id = coder_agent.example.id
app_name = "demo-app"
project_id = "aaa-bbb-ccc"
@@ -83,7 +81,7 @@ Set `client_id` and `client_secret` as module inputs.
```tf
module "vault" {
source = "registry.coder.com/coder/hcp-vault-secrets/coder"
version = "1.0.32"
version = "1.0.34"
agent_id = coder_agent.example.id
app_name = "demo-app"
project_id = "aaa-bbb-ccc"
@@ -2,7 +2,6 @@
display_name: JetBrains Gateway
description: Add a one-click button to launch JetBrains Gateway IDEs in the dashboard.
icon: ../../../../.icons/gateway.svg
maintainer_github: coder
verified: true
tags: [ide, jetbrains, parameter, gateway]
---
@@ -18,7 +17,7 @@ Consult the [JetBrains documentation](https://www.jetbrains.com/help/idea/prereq
module "jetbrains_gateway" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains-gateway/coder"
version = "1.2.1"
version = "1.2.2"
agent_id = coder_agent.example.id
folder = "/home/coder/example"
jetbrains_ides = ["CL", "GO", "IU", "PY", "WS"]
@@ -36,7 +35,7 @@ module "jetbrains_gateway" {
module "jetbrains_gateway" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains-gateway/coder"
version = "1.2.1"
version = "1.2.2"
agent_id = coder_agent.example.id
folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"]
@@ -50,7 +49,7 @@ module "jetbrains_gateway" {
module "jetbrains_gateway" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains-gateway/coder"
version = "1.2.1"
version = "1.2.2"
agent_id = coder_agent.example.id
folder = "/home/coder/example"
jetbrains_ides = ["IU", "PY"]
@@ -65,7 +64,7 @@ module "jetbrains_gateway" {
module "jetbrains_gateway" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains-gateway/coder"
version = "1.2.1"
version = "1.2.2"
agent_id = coder_agent.example.id
folder = "/home/coder/example"
jetbrains_ides = ["IU", "PY"]
@@ -90,7 +89,7 @@ module "jetbrains_gateway" {
module "jetbrains_gateway" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains-gateway/coder"
version = "1.2.1"
version = "1.2.2"
agent_id = coder_agent.example.id
folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"]
@@ -108,7 +107,7 @@ Due to the highest priority of the `ide_download_link` parameter in the `(jetbra
module "jetbrains_gateway" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains-gateway/coder"
version = "1.2.1"
version = "1.2.2"
agent_id = coder_agent.example.id
folder = "/home/coder/example"
jetbrains_ides = ["GO", "WS"]
+6 -7
View File
@@ -2,7 +2,6 @@
display_name: JetBrains Toolbox
description: Add JetBrains IDE integrations to your Coder workspaces with configurable options.
icon: ../../../../.icons/jetbrains.svg
maintainer_github: coder
verified: true
tags: [ide, jetbrains, parameter]
---
@@ -15,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.0"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
}
@@ -40,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.0"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
default = ["PY", "IU"] # Pre-configure GoLand and IntelliJ IDEA
@@ -53,7 +52,7 @@ module "jetbrains" {
module "jetbrains" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains/coder"
version = "1.0.0"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
# Show parameter with limited options
@@ -67,7 +66,7 @@ module "jetbrains" {
module "jetbrains" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains/coder"
version = "1.0.0"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
default = ["IU", "PY"]
@@ -82,7 +81,7 @@ module "jetbrains" {
module "jetbrains" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains/coder"
version = "1.0.0"
version = "1.0.2"
agent_id = coder_agent.example.id
folder = "/workspace/project"
@@ -108,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.0"
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
+3 -5
View File
@@ -2,8 +2,6 @@
display_name: JFrog (OAuth)
description: Install the JF CLI and authenticate with Artifactory using OAuth.
icon: ../../../../.icons/jfrog.svg
maintainer_github: coder
partner_github: jfrog
verified: true
tags: [integration, jfrog, helper]
---
@@ -18,7 +16,7 @@ Install the JF CLI and authenticate package managers with Artifactory using OAut
module "jfrog" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jfrog-oauth/coder"
version = "1.0.19"
version = "1.0.31"
agent_id = coder_agent.example.id
jfrog_url = "https://example.jfrog.io"
username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username"
@@ -47,7 +45,7 @@ Configure the Python pip package manager to fetch packages from Artifactory whil
module "jfrog" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jfrog-oauth/coder"
version = "1.0.19"
version = "1.0.31"
agent_id = coder_agent.example.id
jfrog_url = "https://example.jfrog.io"
username_field = "email"
@@ -76,7 +74,7 @@ The [JFrog extension](https://open-vsx.org/extension/JFrog/jfrog-vscode-extensio
module "jfrog" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jfrog-oauth/coder"
version = "1.0.19"
version = "1.0.31"
agent_id = coder_agent.example.id
jfrog_url = "https://example.jfrog.io"
username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username"
+4 -6
View File
@@ -2,8 +2,6 @@
display_name: JFrog (Token)
description: Install the JF CLI and authenticate with Artifactory using Artifactory terraform provider.
icon: ../../../../.icons/jfrog.svg
maintainer_github: coder
partner_github: jfrog
verified: true
tags: [integration, jfrog]
---
@@ -15,7 +13,7 @@ Install the JF CLI and authenticate package managers with Artifactory using Arti
```tf
module "jfrog" {
source = "registry.coder.com/coder/jfrog-token/coder"
version = "1.0.30"
version = "1.0.31"
agent_id = coder_agent.example.id
jfrog_url = "https://XXXX.jfrog.io"
artifactory_access_token = var.artifactory_access_token
@@ -42,7 +40,7 @@ For detailed instructions, please see this [guide](https://coder.com/docs/v2/lat
```tf
module "jfrog" {
source = "registry.coder.com/coder/jfrog-token/coder"
version = "1.0.30"
version = "1.0.31"
agent_id = coder_agent.example.id
jfrog_url = "https://YYYY.jfrog.io"
artifactory_access_token = var.artifactory_access_token # An admin access token
@@ -75,7 +73,7 @@ The [JFrog extension](https://open-vsx.org/extension/JFrog/jfrog-vscode-extensio
```tf
module "jfrog" {
source = "registry.coder.com/coder/jfrog-token/coder"
version = "1.0.30"
version = "1.0.31"
agent_id = coder_agent.example.id
jfrog_url = "https://XXXX.jfrog.io"
artifactory_access_token = var.artifactory_access_token
@@ -95,7 +93,7 @@ data "coder_workspace" "me" {}
module "jfrog" {
source = "registry.coder.com/coder/jfrog-token/coder"
version = "1.0.30"
version = "1.0.31"
agent_id = coder_agent.example.id
jfrog_url = "https://XXXX.jfrog.io"
artifactory_access_token = var.artifactory_access_token
@@ -2,7 +2,6 @@
display_name: Jupyter Notebook
description: A module that adds Jupyter Notebook in your Coder template.
icon: ../../../../.icons/jupyter.svg
maintainer_github: coder
verified: true
tags: [jupyter, ide, web]
---
@@ -17,7 +16,7 @@ A module that adds Jupyter Notebook in your Coder template.
module "jupyter-notebook" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jupyter-notebook/coder"
version = "1.1.0"
version = "1.2.0"
agent_id = coder_agent.example.id
}
```
@@ -48,13 +48,27 @@ variable "group" {
default = null
}
variable "requirements_path" {
type = string
description = "The path to requirements.txt with packages to preinstall"
default = ""
}
variable "pip_install_extra_packages" {
type = string
description = "List of extra packages to preinstall (example: numpy==1.26.4 pandas matplotlib<4 scikit-learn)"
default = ""
}
resource "coder_script" "jupyter-notebook" {
agent_id = var.agent_id
display_name = "jupyter-notebook"
icon = "/icon/jupyter.svg"
script = templatefile("${path.module}/run.sh", {
LOG_PATH : var.log_path,
PORT : var.port
PORT : var.port,
REQUIREMENTS_PATH : var.requirements_path,
PIP_INSTALL_EXTRA_PACKAGES : var.pip_install_extra_packages
})
run_on_start = true
}
@@ -20,6 +20,24 @@ else
echo "🥳 jupyter-notebook is already installed\n\n"
fi
# Install packages selected with REQUIREMENTS_PATH
if [ -n "${REQUIREMENTS_PATH}" ]; then
if [ -f "${REQUIREMENTS_PATH}" ]; then
echo "📄 Installing packages from ${REQUIREMENTS_PATH}..."
pipx -q runpip notebook install -r "${REQUIREMENTS_PATH}"
echo "🥳 Packages from ${REQUIREMENTS_PATH} have been installed\n\n"
else
echo "⚠️ REQUIREMENTS_PATH is set to '${REQUIREMENTS_PATH}' but the file does not exist!\n\n"
fi
fi
# Install packages selected with PIP_INSTALL_EXTRA_PACKAGES
if [ -n "${PIP_INSTALL_EXTRA_PACKAGES}" ]; then
echo "📦 Installing additional packages: ${PIP_INSTALL_EXTRA_PACKAGES}"
pipx -q runpip notebook install ${PIP_INSTALL_EXTRA_PACKAGES}
echo "🥳 Additional packages have been installed\n\n"
fi
echo "👷 Starting jupyter-notebook in background..."
echo "check logs at ${LOG_PATH}"
$HOME/.local/bin/jupyter-notebook --NotebookApp.ip='0.0.0.0' --ServerApp.port=${PORT} --no-browser --ServerApp.token='' --ServerApp.password='' > ${LOG_PATH} 2>&1 &
+1 -2
View File
@@ -2,7 +2,6 @@
display_name: JupyterLab
description: A module that adds JupyterLab in your Coder template.
icon: ../../../../.icons/jupyter.svg
maintainer_github: coder
verified: true
tags: [jupyter, ide, web]
---
@@ -17,7 +16,7 @@ A module that adds JupyterLab in your Coder template.
module "jupyterlab" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jupyterlab/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
}
```
+1 -2
View File
@@ -2,7 +2,6 @@
display_name: KasmVNC
description: A modern open source VNC server
icon: ../../../../.icons/kasmvnc.svg
maintainer_github: coder
verified: true
tags: [vnc, desktop, kasmvnc]
---
@@ -15,7 +14,7 @@ Automatically install [KasmVNC](https://kasmweb.com/kasmvnc) in a workspace, and
module "kasmvnc" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/kasmvnc/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
desktop_environment = "xfce"
subdomain = true
+51
View File
@@ -0,0 +1,51 @@
---
display_name: Kiro IDE
description: Add a one-click button to launch Kiro IDE
icon: ../../../../.icons/kiro.svg
verified: true
tags: [ide, kiro, ai, aws]
---
# Kiro IDE
Add a button to open any workspace with a single click in [Kiro IDE](https://kiro.dev).
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.
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.
```tf
module "kiro" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/kiro/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
}
```
## Examples
### Open in a specific directory
```tf
module "kiro" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/kiro/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
}
```
### Open with custom display name and order
```tf
module "kiro" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/kiro/coder"
version = "1.0.0"
agent_id = coder_agent.example.id
display_name = "Kiro AI IDE"
order = 1
}
```
+93
View File
@@ -0,0 +1,93 @@
import { describe, expect, it } from "bun:test";
import {
runTerraformApply,
runTerraformInit,
testRequiredVariables,
} from "~test";
describe("kiro", 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.kiro_url.value).toBe(
"kiro://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 === "kiro",
);
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.kiro_url.value).toBe(
"kiro://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.kiro_url.value).toBe(
"kiro://coder.coder-remote/open?owner=default&workspace=default&folder=/foo/bar&openRecent&url=https://mydeployment.coder.com&token=$SESSION_TOKEN",
);
});
it("custom slug and display_name", async () => {
const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo",
slug: "kiro-ai",
display_name: "Kiro AI IDE",
});
const coder_app = state.resources.find(
(res) => res.type === "coder_app" && res.name === "kiro",
);
expect(coder_app?.instances[0].attributes.slug).toBe("kiro-ai");
expect(coder_app?.instances[0].attributes.display_name).toBe("Kiro AI IDE");
});
it("sets order", async () => {
const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo",
order: "5",
});
const coder_app = state.resources.find(
(res) => res.type === "coder_app" && res.name === "kiro",
);
expect(coder_app?.instances[0].attributes.order).toBe(5);
});
it("sets group", async () => {
const state = await runTerraformApply(import.meta.dir, {
agent_id: "foo",
group: "AI IDEs",
});
const coder_app = state.resources.find(
(res) => res.type === "coder_app" && res.name === "kiro",
);
expect(coder_app?.instances[0].attributes.group).toBe("AI IDEs");
});
});
+81
View File
@@ -0,0 +1,81 @@
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 Kiro 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
}
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 = "kiro"
}
variable "display_name" {
type = string
description = "The display name of the app."
default = "Kiro IDE"
}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}
resource "coder_app" "kiro" {
agent_id = var.agent_id
external = true
icon = "/icon/kiro.svg"
slug = var.slug
display_name = var.display_name
order = var.order
group = var.group
url = join("", [
"kiro://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 "kiro_url" {
value = coder_app.kiro.url
description = "Kiro IDE URL."
}
@@ -2,7 +2,6 @@
display_name: RDP Desktop
description: Enable RDP on Windows and add a one-click Coder Desktop button for seamless access
icon: ../../../../.icons/rdp.svg
maintainer_github: coder
verified: true
supported_os: [windows]
tags: [rdp, windows, desktop, local]
@@ -25,7 +24,7 @@ This module enables Remote Desktop Protocol (RDP) on Windows workspaces and adds
module "rdp_desktop" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/local-windows-rdp/coder"
version = "1.0.1"
version = "1.0.2"
agent_id = coder_agent.main.id
agent_name = coder_agent.main.name
}
@@ -58,7 +57,7 @@ Uses default credentials (Username: `Administrator`, Password: `coderRDP!`):
module "rdp_desktop" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/local-windows-rdp/coder"
version = "1.0.1"
version = "1.0.2"
agent_id = coder_agent.main.id
agent_name = coder_agent.main.name
}
@@ -72,7 +71,7 @@ Specify a custom display name for the `coder_app` button:
module "rdp_desktop" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/local-windows-rdp/coder"
version = "1.0.1"
version = "1.0.2"
agent_id = coder_agent.windows.id
agent_name = "windows"
display_name = "Windows Desktop"
+1 -2
View File
@@ -2,7 +2,6 @@
display_name: Personalize
description: Allow developers to customize their workspace on start
icon: ../../../../.icons/personalize.svg
maintainer_github: coder
verified: true
tags: [helper, personalize]
---
@@ -15,7 +14,7 @@ Run a script on workspace start that allows developers to run custom commands to
module "personalize" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/personalize/coder"
version = "1.0.2"
version = "1.0.31"
agent_id = coder_agent.example.id
}
```
+2 -3
View File
@@ -2,7 +2,6 @@
display_name: Slack Me
description: Send a Slack message when a command finishes inside a workspace!
icon: ../../../../.icons/slack.svg
maintainer_github: coder
verified: true
tags: [helper, slack]
---
@@ -15,7 +14,7 @@ Add the `slackme` command to your workspace that DMs you on Slack when your comm
module "slackme" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/slackme/coder"
version = "1.0.2"
version = "1.0.31"
agent_id = coder_agent.example.id
auth_provider_id = "slack"
}
@@ -75,7 +74,7 @@ slackme npm run long-build
module "slackme" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/slackme/coder"
version = "1.0.2"
version = "1.0.31"
agent_id = coder_agent.example.id
auth_provider_id = "slack"
slack_message = <<EOF
@@ -2,8 +2,6 @@
display_name: Hashicorp Vault Integration (GitHub)
description: Authenticates with Vault using GitHub
icon: ../../../../.icons/vault.svg
maintainer_github: coder
partner_github: hashicorp
verified: true
tags: [hashicorp, integration, vault, github]
---
@@ -16,7 +14,7 @@ This module lets you authenticate with [Hashicorp Vault](https://www.vaultprojec
module "vault" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vault-github/coder"
version = "1.0.7"
version = "1.0.31"
agent_id = coder_agent.example.id
vault_addr = "https://vault.example.com"
}
@@ -48,7 +46,7 @@ To configure the Vault module, you must set up a Vault GitHub auth method. See t
module "vault" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vault-github/coder"
version = "1.0.7"
version = "1.0.31"
agent_id = coder_agent.example.id
vault_addr = "https://vault.example.com"
coder_github_auth_id = "my-github-auth-id"
@@ -61,7 +59,7 @@ module "vault" {
module "vault" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vault-github/coder"
version = "1.0.7"
version = "1.0.31"
agent_id = coder_agent.example.id
vault_addr = "https://vault.example.com"
coder_github_auth_id = "my-github-auth-id"
@@ -75,7 +73,7 @@ module "vault" {
module "vault" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vault-github/coder"
version = "1.0.7"
version = "1.0.31"
agent_id = coder_agent.example.id
vault_addr = "https://vault.example.com"
vault_cli_version = "1.15.0"
+5 -7
View File
@@ -2,8 +2,6 @@
display_name: Hashicorp Vault Integration (JWT)
description: Authenticates with Vault using a JWT from Coder's OIDC provider
icon: ../../../../.icons/vault.svg
maintainer_github: coder
partner_github: hashicorp
verified: true
tags: [hashicorp, integration, vault, jwt, oidc]
---
@@ -16,7 +14,7 @@ This module lets you authenticate with [Hashicorp Vault](https://www.vaultprojec
module "vault" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vault-jwt/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
vault_addr = "https://vault.example.com"
vault_jwt_role = "coder" # The Vault role to use for authentication
@@ -44,7 +42,7 @@ curl -H "X-Vault-Token: ${VAULT_TOKEN}" -X GET "${VAULT_ADDR}/v1/coder/secrets/d
module "vault" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vault-jwt/coder"
version = "1.0.31"
version = "1.1.1"
agent_id = coder_agent.example.id
vault_addr = "https://vault.example.com"
vault_jwt_auth_path = "oidc"
@@ -60,7 +58,7 @@ data "coder_workspace_owner" "me" {}
module "vault" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vault-jwt/coder"
version = "1.0.31"
version = "1.1.1"
agent_id = coder_agent.example.id
vault_addr = "https://vault.example.com"
vault_jwt_role = data.coder_workspace_owner.me.groups[0]
@@ -73,7 +71,7 @@ module "vault" {
module "vault" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vault-jwt/coder"
version = "1.0.31"
version = "1.1.1"
agent_id = coder_agent.example.id
vault_addr = "https://vault.example.com"
vault_jwt_role = "coder" # The Vault role to use for authentication
@@ -134,7 +132,7 @@ resource "jwt_signed_token" "vault" {
module "vault" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vault-jwt/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
vault_addr = "https://vault.example.com"
vault_jwt_role = "coder" # The Vault role to use for authentication
+2 -4
View File
@@ -2,8 +2,6 @@
display_name: Hashicorp Vault Integration (Token)
description: Authenticates with Vault using Token
icon: ../../../../.icons/vault.svg
maintainer_github: coder
partner_github: hashicorp
verified: true
tags: [hashicorp, integration, vault, token]
---
@@ -21,7 +19,7 @@ variable "vault_token" {
module "vault" {
source = "registry.coder.com/coder/vault-token/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
vault_token = var.token # optional
vault_addr = "https://vault.example.com"
@@ -75,7 +73,7 @@ variable "vault_token" {
module "vault" {
source = "registry.coder.com/coder/vault-token/coder"
version = "1.2.0"
version = "1.2.1"
agent_id = coder_agent.example.id
vault_addr = "https://vault.example.com"
vault_token = var.token
@@ -2,7 +2,6 @@
display_name: VS Code Desktop
description: Add a one-click button to launch VS Code Desktop
icon: ../../../../.icons/code.svg
maintainer_github: coder
verified: true
tags: [ide, vscode]
---
@@ -17,7 +16,7 @@ Uses the [Coder Remote VS Code Extension](https://github.com/coder/vscode-coder)
module "vscode" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vscode-desktop/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
}
```
@@ -30,7 +29,7 @@ module "vscode" {
module "vscode" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vscode-desktop/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
}
+5 -6
View File
@@ -2,7 +2,6 @@
display_name: VS Code Web
description: VS Code Web - Visual Studio Code in the browser
icon: ../../../../.icons/code.svg
maintainer_github: coder
verified: true
tags: [ide, vscode, web]
---
@@ -15,7 +14,7 @@ Automatically install [Visual Studio Code Server](https://code.visualstudio.com/
module "vscode-web" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vscode-web/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
accept_license = true
}
@@ -31,7 +30,7 @@ module "vscode-web" {
module "vscode-web" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vscode-web/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
install_prefix = "/home/coder/.vscode-web"
folder = "/home/coder"
@@ -45,7 +44,7 @@ module "vscode-web" {
module "vscode-web" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vscode-web/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
extensions = ["github.copilot", "ms-python.python", "ms-toolsai.jupyter"]
accept_license = true
@@ -60,7 +59,7 @@ Configure VS Code's [settings.json](https://code.visualstudio.com/docs/getstarte
module "vscode-web" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vscode-web/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
extensions = ["dracula-theme.theme-dracula"]
settings = {
@@ -78,7 +77,7 @@ By default, this module installs the latest. To pin a specific version, retrieve
module "vscode-web" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/vscode-web/coder"
version = "1.3.0"
version = "1.3.1"
agent_id = coder_agent.example.id
commit_id = "e54c774e0add60467559eb0d1e229c6452cf8447"
accept_license = true
+4 -5
View File
@@ -2,7 +2,6 @@
display_name: RDP Web
description: RDP Server and Web Client, powered by Devolutions Gateway
icon: ../../../../.icons/desktop.svg
maintainer_github: coder
verified: true
tags: [windows, rdp, web, desktop]
---
@@ -16,7 +15,7 @@ Enable Remote Desktop + a web based client on Windows workspaces, powered by [de
module "windows_rdp" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/windows-rdp/coder"
version = "1.2.2"
version = "1.2.3"
agent_id = resource.coder_agent.main.id
}
```
@@ -33,7 +32,7 @@ module "windows_rdp" {
module "windows_rdp" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/windows-rdp/coder"
version = "1.2.2"
version = "1.2.3"
agent_id = resource.coder_agent.main.id
}
```
@@ -44,7 +43,7 @@ module "windows_rdp" {
module "windows_rdp" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/windows-rdp/coder"
version = "1.2.2"
version = "1.2.3"
agent_id = resource.coder_agent.main.id
}
```
@@ -55,7 +54,7 @@ module "windows_rdp" {
module "windows_rdp" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/windows-rdp/coder"
version = "1.2.2"
version = "1.2.3"
agent_id = resource.coder_agent.main.id
devolutions_gateway_version = "2025.2.2" # Specify a specific version
}
+2 -3
View File
@@ -2,7 +2,6 @@
display_name: Windsurf Editor
description: Add a one-click button to launch Windsurf Editor
icon: ../../../../.icons/windsurf.svg
maintainer_github: coder
verified: true
tags: [ide, windsurf, ai]
---
@@ -17,7 +16,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.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
}
```
@@ -30,7 +29,7 @@ module "windsurf" {
module "windsurf" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/windsurf/coder"
version = "1.1.0"
version = "1.1.1"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
}
+4 -5
View File
@@ -2,7 +2,6 @@
display_name: Zed
description: Add a one-click button to launch Zed
icon: ../../../../.icons/zed.svg
maintainer_github: coder
verified: true
tags: [ide, zed, editor]
---
@@ -20,7 +19,7 @@ Zed is a high-performance, multiplayer code editor from the creators of Atom and
module "zed" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/zed/coder"
version = "1.0.0"
version = "1.0.1"
agent_id = coder_agent.example.id
}
```
@@ -33,7 +32,7 @@ module "zed" {
module "zed" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/zed/coder"
version = "1.0.0"
version = "1.0.1"
agent_id = coder_agent.example.id
folder = "/home/coder/project"
}
@@ -45,7 +44,7 @@ module "zed" {
module "zed" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/zed/coder"
version = "1.0.0"
version = "1.0.1"
agent_id = coder_agent.example.id
display_name = "Zed Editor"
order = 1
@@ -58,7 +57,7 @@ module "zed" {
module "zed" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/zed/coder"
version = "1.0.0"
version = "1.0.1"
agent_id = coder_agent.example.id
agent_name = coder_agent.example.name
}
@@ -2,7 +2,6 @@
display_name: AWS EC2 (Devcontainer)
description: Provision AWS EC2 VMs with a devcontainer as Coder workspaces
icon: ../../../../.icons/aws.svg
maintainer_github: coder
verified: true
tags: [vm, linux, aws, persistent, devcontainer]
---
@@ -2,7 +2,6 @@
display_name: AWS EC2 (Linux)
description: Provision AWS EC2 VMs as Coder workspaces
icon: ../../../../.icons/aws.svg
maintainer_github: coder
verified: true
tags: [vm, linux, aws, persistent-vm]
---
@@ -2,7 +2,6 @@
display_name: AWS EC2 (Windows)
description: Provision AWS EC2 VMs as Coder workspaces
icon: ../../../../.icons/aws.svg
maintainer_github: coder
verified: true
tags: [vm, windows, aws]
---
@@ -2,7 +2,6 @@
display_name: Azure VM (Linux)
description: Provision Azure VMs as Coder workspaces
icon: ../../../../.icons/azure.svg
maintainer_github: coder
verified: true
tags: [vm, linux, azure]
---
@@ -2,7 +2,6 @@
display_name: Azure VM (Windows)
description: Provision Azure VMs as Coder workspaces
icon: ../../../../.icons/azure.svg
maintainer_github: coder
verified: true
tags: [vm, windows, azure]
---
@@ -2,7 +2,6 @@
display_name: DigitalOcean Droplet (Linux)
description: Provision DigitalOcean Droplets as Coder workspaces
icon: ../../../../.icons/digital-ocean.svg
maintainer_github: coder
verified: true
tags: [vm, linux, digitalocean]
---
@@ -2,7 +2,6 @@
display_name: Docker (Devcontainer)
description: Provision envbuilder containers as Coder workspaces
icon: ../../../../.icons/docker.svg
maintainer_github: coder
verified: true
tags: [container, docker, devcontainer]
---
@@ -2,7 +2,6 @@
display_name: Docker Containers
description: Provision Docker containers as Coder workspaces
icon: ../../../../.icons/docker.svg
maintainer_github: coder
verified: true
tags: [docker, container]
---

Some files were not shown because too many files have changed in this diff Show More