This pull request enhances the VS Code Web module by improving how
machine settings are handled and merged, updating documentation to
clarify the settings behavior, and adding robust automated tests for the
new functionality. The most significant changes are grouped below.
**Machine Settings Handling and Merging:**
* Introduced a new `merge_settings` function in `run.sh` that merges
provided settings with any existing machine settings using `jq` or
`python3` if available, falling back gracefully if neither is present.
Settings are now passed as base64-encoded JSON to avoid quoting issues.
[[1]](diffhunk://#diff-c6d09ac3d801a2417c0e3cf8c2cd0f093ba2cf245bad8c213f70115c75276323R7-R54)
[[2]](diffhunk://#diff-c6d09ac3d801a2417c0e3cf8c2cd0f093ba2cf245bad8c213f70115c75276323L31-R76)
[[3]](diffhunk://#diff-0c7f0791e2c2556eb4ed7666ac44534ea3ff5c7f652e01716e5d7b5c31180d92L180-R184)
[[4]](diffhunk://#diff-0c7f0791e2c2556eb4ed7666ac44534ea3ff5c7f652e01716e5d7b5c31180d92R170-R173)
* Updated the `settings` variable in `main.tf` to clarify that it
applies to VS Code Web's Machine settings and will be merged with any
existing settings on startup.
**Documentation Improvements:**
* Updated the README to clarify that settings are merged with existing
machine settings, not simply overwritten, and added a note about the
requirements (`jq` or `python3`) and limitations regarding persistence
of user settings.
[[1]](diffhunk://#diff-24e2e305e46a08f8a30243bdc916241586e4561d97861b4397b14e871f9f085dL54-R56)
[[2]](diffhunk://#diff-24e2e305e46a08f8a30243bdc916241586e4561d97861b4397b14e871f9f085dR72-R73)
**Automated Testing:**
* Expanded `main.test.ts` to include integration tests that verify
settings file creation and merging behavior inside a container, as well
as improved error handling for invalid configuration combinations.
These changes collectively make machine settings management more robust,
user-friendly, and well-documented.
feat(coder/modules/claude-code): add enable_state_persistence variable
Expose the agentapi module's state persistence toggle so users can
control conversation state persistence across workspace restarts.
Enabled by default, set `enable_state_persistence = false` to disable.
Also bumps agentapi dependency from 2.0.0 to 2.2.0 and claude-code
to 4.8.0.
Refs coder/internal#1258
AgentAPI can now save and restore conversation state across workspace
restarts. The module exports env vars (AGENTAPI_STATE_FILE,
AGENTAPI_SAVE_STATE, AGENTAPI_LOAD_STATE, AGENTAPI_PID_FILE) that the
binary reads directly. No consumer module changes needed.
New variables: enable_state_persistence (default false),
state_file_path, pid_file_path. State and PID files default to
$HOME/<module_dir_name>/.
Requires agentapi >= v0.12.0. A shared version_at_least function in
lib.sh gates the env var exports and SIGUSR1 in the shutdown script.
Old binaries get a warning and graceful skip.
Shutdown script now does SIGUSR1 (state save), log snapshot capture
(existing, now fault-tolerant via subshell), then SIGTERM with wait.
Closes coder/internal#1257
Refs coder/internal#1256
Refs #696
Some Git providers (e.g. on-prem GitLab) disable HTTPS cloning by
default, which causes the dotfiles clone to silently fail during
workspace startup. Users see "Startup scripts are still running" but the
dotfiles folder is never populated.
This PR adds two small documentation touches:
1. **`main.tf` default description** — appends a one-liner suggesting
SSH URLs when HTTPS is restricted. This is what users see in the Coder
UI parameter prompt.
2. **`README.md`** — new "SSH vs HTTPS URLs" section with an example and
a brief explanation of why SSH URLs are more reliable during startup.
No logic changes, no new variables — just documentation.
---------
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
Co-authored-by: DevCats <christofer@coder.com>
## Summary
Terraform variable names should use underscores (`snake_case`), not
hyphens. Hyphens are technically valid in HCL but are [deprecated and
non-idiomatic](https://developer.hashicorp.com/terraform/language/values/variables).
This PR adds a variable name check into the existing
`terraform_validate.sh` script so it runs as part of the existing "Run
Terraform Validate" CI step — no new scripts or workflow changes needed.
## Changes
### `scripts/terraform_validate.sh` — added `validate_variable_names()`
- Scans `.tf` files in changed modules for `variable` declarations with
hyphens
- Fails with actionable fix suggestions (shows the snake_case
alternative)
- Runs after `terraform validate` in the same CI step
### Fix: `code-server` module — rename `machine-settings` →
`machine_settings`
- Renames the hyphenated variable and its reference in main.tf
- Bumps version `1.4.2` → `1.4.3`
- Updates all README examples
---
Created on behalf of @matifali
---------
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
Co-authored-by: DevCats <christofer@coder.com>
Terraform variable names should use underscores, not hyphens. Renames
the `add-project` variable to `add_project` in the mux module.
**Changes:**
- `main.tf`: Renamed variable declaration and references
- `README.md`: Updated example usage
Bumped version: 1.3.0 → 1.3.1
---
Generated with [Mux](https://mux.coder.com) using Claude
## Description
The URL validation regex in the dotfiles module was rejecting URLs
containing tilde (`~`) characters, which are commonly used in Bitbucket
Server for user repositories (e.g.
`ssh://git@bitbucket.example.org:7999/~username/repo.git`).
This adds `~` to the allowed character set in all three validation
regexes (for `default_dotfiles_uri`, `dotfiles_uri`, and the
`coder_parameter` validation).
## Type of Change
- [ ] New module
- [ ] New template
- [x] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other
## Module Information
**Path:** `registry/coder/modules/dotfiles`
**New version:** `v1.3.1`
**Breaking change:** [ ] Yes [x] No
## Testing & Validation
- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun fmt`)
- [ ] Changes tested locally
## Related Issues
Fixes#762
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
## Summary
Add two new customization variables to the Mux module so users can
control how Mux is installed:
### `package_manager` (default: `"auto"`)
Choose which Node package manager installs Mux:
- **`auto`** (default) — auto-detects `npm` → `pnpm` → `bun` in order,
falling back to a direct tarball download when none is available
- **`npm`**, **`pnpm`**, **`bun`** — force a specific package manager
(fails if not found on PATH)
### `registry_url` (default: `"https://registry.npmjs.org"`)
Override the npm registry URL for private registries or mirrors. All
previously hardcoded `registry.npmjs.org` references have been replaced
with this variable. The `--registry` flag is passed to whichever package
manager is used, and the tarball fallback path also uses it.
## Changes
| File | What changed |
|---|---|
| `main.tf` | Added `package_manager` and `registry_url` variables with
validation; pass both to template |
| `run.sh` | Rewrote install logic: PM auto-detection loop,
`case`/`esac` dispatch with PM-specific flags, replaced all hardcoded
registry URLs with `${REGISTRY_URL}` |
| `mux.tftest.hcl` | Added 6 new test cases: PM selection
(npm/pnpm/bun), invalid PM validation, custom registry URL,
trailing-slash stripping |
| `main.test.ts` | Updated expected log messages to match new generic
wording |
| `README.md` | Updated description, added Custom Package Manager and
Custom Registry examples, updated Notes section |
## Version
Bumped **1.2.0 → 1.3.0** (minor: new backward-compatible features).
## Validation
- ✅ `terraform validate` — clean
- ✅ `terraform test` — **15 passed, 0 failed**
- ✅ `terraform fmt` — clean
---
Generated with [Mux](https://mux.coder.com) using Claude
## Summary
- add a new `additional_arguments` module variable to pass extra
arguments to `mux server`
- parse `additional_arguments` in `run.sh` with quoted-group support so
values like paths with spaces are preserved
- keep existing `add-project` behavior while allowing additional
arbitrary flags
- add Terraform and Bun tests covering `additional_arguments` behavior
- document the new option in the module README and bump example version
references to `1.2.0`
## Why
The module previously only supported the `add-project` flag. This change
lets users pass additional `mux server` arguments without waiting for
new module variables.
## Validation
- `shellcheck --severity=warning --format=gcc
registry/coder/modules/mux/run.sh`
- `terraform -chdir=registry/coder/modules/mux test -verbose`
- `bun test registry/coder/modules/mux/main.test.ts`
## Breaking changes
None.
---
Generated with Mux (exec agent) using GPT-5.
## Description
In https://github.com/coder/registry/pull/279, I had accidentally made
the slug of the Positron Desktop app "cursor", and display name to be
"Cursor Desktop". This PR fixes that.
## Type of Change
- [ ] New module
- [ ] New template
- [x] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other
The log message showed ($i/15) where $i ranged from 1-150, making it
look like the counter overshot its maximum. This change extracts the
iteration count into a max_attempts variable and uses it consistently.
The existing README for the Azure Linux template only mentioned that the
VM is ephemeral and the managed disk is persistent, but did not explain
that the resource group, virtual network, subnet, and network interface
also persist when a workspace is stopped.
This led to confusion where users expected all Azure resources to be
cleaned up on stop, when in reality only the VM is destroyed.
## Changes
- Added the persistent networking/infrastructure resources to the
resource list
- Added "What happens on stop" section explaining which resources
persist and why
- Added "What happens on delete" section confirming all resources are
cleaned up
- Moved the existing note about ephemeral tools/files into a "Workspace
restarts" subsection for clarity
Created on behalf of @DevelopmentCats
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
Co-authored-by: DevCats <christofer@coder.com>
## Summary
Add per-workspace authentication token wiring to the Mux Coder module,
closing the last-mile deployment gap for cross-site WebSocket hijacking
(CSWSH) protection identified in coder/security#120.
## Background
When Mux runs as a Coder workspace app, it is accessible via Coder's
subdomain proxy (e.g., `mux--ws--user.apps.coder.com`). Without an auth
token, a malicious same-site origin (another user's workspace app on the
same `*.coder.com` domain) can hijack the WebSocket session and execute
arbitrary commands via the oRPC API.
The Mux application itself already implements:
- **Strict same-origin enforcement** for HTTP/CORS and WebSocket
upgrades (coder/mux#2418)
- **Auth token support** — the server reads `MUX_SERVER_AUTH_TOKEN` or
`--auth-token`, and the browser frontend extracts `?token=` from the URL
and persists it to localStorage
What was missing was module-level token generation and browser/backend
wiring.
## Implementation
- **`random_password.mux_auth_token`** generates a 64-character token
per module instance.
- **Backend wiring:** `run.sh` launches mux with a process-scoped
`MUX_SERVER_AUTH_TOKEN` environment variable.
- **Frontend wiring:** `coder_app.mux.url` includes `?token=<secret>` so
first launch from Coder passes the token to the browser for
bootstrap/persistence.
To avoid cross-instance breakage, this change intentionally does **not**
use a shared `coder_env` key. Multiple `coder/mux` module instances can
target the same `agent_id` (different `slug`/`port`), and a single
global env key would collide. Process-scoped env keeps each instance's
backend token aligned with its app URL token.
## Validation
- `terraform fmt -check -diff` in `registry/coder/modules/mux`
- `terraform test` in `registry/coder/modules/mux` (8 passed, 0 failed)
- Updated tests now verify the URL token value (not just prefix) and
verify the launch script sets `MUX_SERVER_AUTH_TOKEN` using the
generated token.
---
_Generated with `mux` • Model: `anthropic:claude-opus-4-6` • Thinking:
`xhigh`_
<!-- mux-attribution: model=anthropic:claude-opus-4-6 thinking=xhigh -->
## Description
The Agent Helper module is a building block for modules that need to run
multiple scripts in a specific order. It uses `coder exp sync` for
dependency management and is designed for orchestrating pre-install,
install, post-install, and start scripts.
## Type of Change
- [x] New module
- [ ] New template
- [ ] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other
## Module Information
<!-- Delete this section if not applicable -->
**Path:** `registry/coder/modules/agent-helper`
**New version:** `v1.0.0`
**Breaking change:** [x] Yes [ ] No
## Testing & Validation
- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun fmt`)
- [x] Changes tested locally
## Related Issues
Closes: https://github.com/coder/registry/issues/696
Closes: https://github.com/coder/registry/issues/698
---------
Co-authored-by: DevCats <christofer@coder.com>
## Description
Add's Validation to the dotfiles module in all input's to address
security issue pointed out in
https://github.com/coder/security/issues/119
<!-- Briefly describe what this PR does and why -->
## Type of Change
- [ ] New module
- [ ] New template
- [X] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other
## Module Information
<!-- Delete this section if not applicable -->
**Path:** `registry/coder/modules/dotfiles`
**New version:** `v1.2.4`
**Breaking change:** [ ] Yes [X] No
## Testing & Validation
- [Y] Tests pass (`bun test`)
- [Y] Code formatted (`bun fmt`)
- [ ] Changes tested locally
## Related Issues
https://github.com/coder/security/issues/119
<!-- Link related issues or write "None" if not applicable -->
---------
Co-authored-by: Jakub Domeracki <jakub@coder.com>
### Summary
Temporary workaround for non-deterministic PATH handling when using
`coder_env` across multiple modules
([coder/coder#21885](https://github.com/coder/coder/issues/21885)).
### Problem
When multiple modules define `coder_env` with the same `name` (e.g.,
`PATH`), the final value is non-deterministic due to Go map iteration
order. This caused PATH overwrites instead of appending, breaking Claude
Code discovery in workspaces using multiple modules.
### Solution
Replace `coder_env` PATH manipulation with script-based PATH handling:
- **Install script**: Exports PATH and adds claude binary directory to
shell profiles (`.profile`, `.bashrc`, `.zshrc`, fish) for interactive
shell access
- **Start script**: Exports PATH at script execution time
- **Symlink**: Creates symlink in `CODER_SCRIPT_BIN_DIR` as additional
fallback
- **Validation**: Prevents invalid configuration where
`claude_binary_path` is customized but `install_claude_code=true`
(official installer doesn't support custom paths)
### Changes
- Removed `coder_env` resource for PATH
- Added PATH export to `install.sh` and `start.sh`
- Added shell profile modifications for cross-shell compatibility (bash,
zsh, fish)
- Added variable validation for `claude_binary_path`
### Note
This is a temporary fix until
[coder/coder#21885](https://github.com/coder/coder/issues/21885) is
resolved with a proper `merge_strategy` attribute for `coder_env`.
## Type of Change
- [ ] New module
- [ ] New template
- [X] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other
## Module Information
<!-- Delete this section if not applicable -->
**Path:** `registry/coder/modules/claude-code`
**New version:** `v4.7.5`
**Breaking change:** [ ] Yes [X] No
## Testing & Validation
- [X] Tests pass (`bun test`)
- [X] Code formatted (`bun fmt`)
- [X] Changes tested locally
## Related Issues
([coder/coder#21885](https://github.com/coder/coder/issues/21885))
## Description
At the moment, the `CLAUDE_API_KEY` coder_env will always be created,
even if the variable itself is not. This can lead to the environment
variable being unset if it has been set outside of Terraform.
With this PR, we make the `claude_api_key` coder_env conditional, so it
will only be created if an API key has been set.
## Type of Change
- [ ] New module
- [ ] New template
- [x] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other
## Module Information
<!-- Delete this section if not applicable -->
**Path:** `registry/coder/modules/claude-code/main.tf`
**New version:** `v4.7.4`
**Breaking change:** [ ] Yes [x] No
## Testing & Validation
- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun fmt`)
- [x] Changes tested locally
## Related Issues
None
---------
Co-authored-by: 35C4n0r <70096901+35C4n0r@users.noreply.github.com>
Captures the last 10 messages from AgentAPI when task workspaces stop,
allowing users to view conversation history while the task is paused.
The shutdown script fetches messages, builds a payload with last 10
messages, truncates to 64KB if needed (removes old messages first, then
truncates content of the last message), and posts to the log snapshot
endpoint.
Gracefully handles non-task workspaces (skips), older Coder versions
without the endpoint (logs and continues), and empty message sets.
Enabled by default via task_log_snapshot variable. Task ID is
automatically resolved from data.coder_task when available.
Updates coder/internal#1257
## Description
- Update claude-code module to use binary installation incase of
specific version pinning unless use npm is specified.
- Add a deprecation warning in the install script and readme for npm.
## Type of Change
- [ ] New module
- [ ] New template
- [x] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other
## Module Information
<!-- Delete this section if not applicable -->
**Path:** `registry/coder/modules/claude-code`
**New version:** `v4.7.1`
**Breaking change:** [ ] Yes [x] No
## Testing & Validation
- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun fmt`)
- [x] Changes tested locally
## Related Issues
<!-- Link related issues or write "None" if not applicable -->
## Description
<!-- Briefly describe what this PR does and why -->
A draft that allow user connect existing linux system though coder by
ssh
## Type of Change
- [ ] New module
- [x] New template
- [ ] Bug fix
- [ ] Feature/enhancement
- [x] Documentation
- [ ] Other
## Template Information
<!-- Delete this section if not applicable -->
**Path:** `registry/IamTaoChen/templates/ssh-linux`
## Testing & Validation
- [ ] Tests pass (`bun test`)
- [x] Code formatted (`bun fmt`)
- [x] Changes tested locally
## Related Issues
<!-- Link related issues or write "None" if not applicable -->
---------
Co-authored-by: DevCats <christofer@coder.com>
## Summary
- Default `subdomain` to `true` so Mux uses subdomain routing by
default.
- Default `display_name` to `Mux`.
- Make `add-project` optional (`null` by default) and pass
`--add-project` to `mux server` when set.
- Bump mux module README example version to `1.0.8`.
## Notes
Changing the `subdomain` default may affect workspaces without wildcard
subdomain support configured (they can explicitly set `subdomain =
false`).
## Testing
- `terraform validate` (registry/coder/modules/mux)
- `terraform test -verbose` (registry/coder/modules/mux)
---
Generated with Mux (AI coding agent).
## Description
This PR adds a zizmor security scan to the CI pipeline to analyze new
and existing GitHub Actions workflows under .github/workflows/.
- Runs zizmor on PRs and fails the check when HIGH severity (or above)
issues are found, so they can block merges.
- Runs zizmor on main to produce security reporting (where applicable),
keeping visibility into findings over time.
- Intended to be added as a required status check so workflow-security
regressions can’t land unnoticed.
Reference: coder/registry#642 (comment) / zizmor-action
## Type of Change
- [ ] New module
- [ ] New template
- [ ] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [x] Other - CI / security tooling
## Testing & Validation
- Validation via PR check - opened a test PR with a deliberately risky
workflow and confirmed zizmor reports and blocks on HIGH findings
## Related Issues
coder/registry#642 (comment) / zizmor-action
## Description
Updates AGENTS.md to be more concise (~36 lines) while adding missing
commands and a PR review checklist based on recent PR feedback.
## Changes
- **Commands section**: Added `bun run tftest`, `bun run tstest`, single
test commands, and version-bump script
- **Structure section**: Added note that URLs must be relative (from
#639)
- **Code Style section**: Added `tf` vs `hcl` guidance and relative icon
paths
- **New PR Review Checklist**: Based on patterns from recent PRs
including:
- Version bumping requirements (#661, #617)
- Breaking changes documentation (#636)
- Graceful error handling in scripts (#658)
- Diagnostic logging for tests (#643)
- **AI attribution requirement**: PRs should note model/tool used
## Type of Change
- [ ] New module
- [ ] New template
- [ ] Bug fix
- [ ] Feature/enhancement
- [x] Documentation
- [ ] Other
---
Generated with
[Amp](https://ampcode.com/threads/T-019bcb7e-2e92-76f2-a1aa-2023ecdb0763)
using Claude Sonnet 4
## Description
Adds a `claude_path` variable to override the path that the `coder_env`
sets for claude-code.
Adds a `install_via_npm` variable to override the official installation
and use npm to install claude-code ( this doesn't change any behaviour,
simply just the options available to the user )
Model now uses `coder_env` to set the `ANTHROPIC_MODEL` env instead of
using the `--model` cli flag which did not set the anthropic model
globally in the workspace.
Normal Usage -> Official Installer
Specific Version Set -> NPM Install
Install Via NPM -> NPM Install
The idea with `claude_path` is that someone who wants to source claude
another way can install it and utilize that install in the module. If
install is true and a custom path is provided there is a tf precondition
that will disallow this.
<!-- Briefly describe what this PR does and why -->
## Type of Change
- [ ] New module
- [ ] New template
- [ ] Bug fix
- [X] Feature/enhancement
- [ ] Documentation
- [ ] Other
## Module Information
<!-- Delete this section if not applicable -->
**Path:** `registry/coder/modules/claude-code`
**New version:** `v4.4.0`
**Breaking change:** [ ] Yes [X] No
## Testing & Validation
- [X] Tests pass (`bun test`)
- [X] Code formatted (`bun fmt`)
- [X] Changes tested locally
## Related Issues
<!-- Link related issues or write "None" if not applicable -->
## Description
Adds e2e test for code-server that actually installs and health checks
code-server
<!-- Briefly describe what this PR does and why -->
## Type of Change
- [ ] New module
- [ ] New template
- [ ] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [X] Other
## Testing & Validation
- [X] Tests pass (`bun test`)
- [X] Code formatted (`bun fmt`)
- [X] Changes tested locally
## Related Issues
<!-- Link related issues or write "None" if not applicable -->
## Summary
Adds a `CODEOWNERS` file to enforce code review requirements for GitHub
Actions workflow changes.
- Creates `CODEOWNERS` file designating `@jdomeracki-coder` as owner of
`.github/` directory
- All changes to GitHub Actions workflows (`.github/` directory) now
require approval from the designated code owner
- Improves security posture by preventing unauthorized modifications to
CI/CD pipelines
## Why this change?
GitHub Actions workflows have elevated privileges and can access
repository secrets. Requiring explicit approval for workflow changes
helps prevent:
- Accidental or malicious modifications to CI/CD pipelines
- Unauthorized access to secrets
- Supply chain security vulnerabilities
## Test plan
- [x] Verify CODEOWNERS file is properly formatted
- [ ] Test that PRs modifying `.github/` directory require approval from
`@jdomeracki-coder`
- [ ] Confirm existing PRs not touching `.github/` continue to work
normally