From 94e41d3780bf027871643f66b8adbe43c99b8e69 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Wed, 25 Feb 2026 19:15:33 +0100 Subject: [PATCH 1/7] Add arbitrary mux server command argument parsing (#738) ## 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. --- registry/coder/modules/mux/README.md | 29 +++++++++--- registry/coder/modules/mux/main.test.ts | 56 +++++++++++++++++++++++ registry/coder/modules/mux/main.tf | 7 +++ registry/coder/modules/mux/mux.tftest.hcl | 14 ++++++ registry/coder/modules/mux/run.sh | 16 +++++++ 5 files changed, 115 insertions(+), 7 deletions(-) diff --git a/registry/coder/modules/mux/README.md b/registry/coder/modules/mux/README.md index b9cfafc0..69073926 100644 --- a/registry/coder/modules/mux/README.md +++ b/registry/coder/modules/mux/README.md @@ -14,7 +14,7 @@ Automatically install and run [Mux](https://github.com/coder/mux) in a Coder wor module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.1.0" + version = "1.2.0" agent_id = coder_agent.main.id } ``` @@ -37,7 +37,7 @@ module "mux" { module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.1.0" + version = "1.2.0" agent_id = coder_agent.main.id } ``` @@ -48,7 +48,7 @@ module "mux" { module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.1.0" + version = "1.2.0" agent_id = coder_agent.main.id # Default is "latest"; set to a specific version to pin install_version = "0.4.0" @@ -63,19 +63,34 @@ Start Mux with `mux server --add-project /path/to/project`: module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.1.0" + version = "1.2.0" agent_id = coder_agent.main.id add-project = "/path/to/project" } ``` +### Pass Arbitrary `mux server` Arguments + +Use `additional_arguments` to append additional arguments to `mux server`. +The module parses quoted values, so grouped arguments remain intact. + +```tf +module "mux" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/mux/coder" + version = "1.2.0" + agent_id = coder_agent.main.id + additional_arguments = "--open-mode pinned --add-project '/workspaces/my repo'" +} +``` + ### Custom Port ```tf module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.1.0" + version = "1.2.0" agent_id = coder_agent.main.id port = 8080 } @@ -89,7 +104,7 @@ Run an existing copy of Mux if found, otherwise install from npm: module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.1.0" + version = "1.2.0" agent_id = coder_agent.main.id use_cached = true } @@ -103,7 +118,7 @@ Run without installing from the network (requires Mux to be pre-installed): module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.1.0" + version = "1.2.0" agent_id = coder_agent.main.id install = false } diff --git a/registry/coder/modules/mux/main.test.ts b/registry/coder/modules/mux/main.test.ts index 96fae5e4..c1b6e238 100644 --- a/registry/coder/modules/mux/main.test.ts +++ b/registry/coder/modules/mux/main.test.ts @@ -1,6 +1,11 @@ import { describe, expect, it } from "bun:test"; import { executeScriptInContainer, + execContainer, + findResourceInstance, + readFileContainer, + removeContainer, + runContainer, runTerraformApply, runTerraformInit, testRequiredVariables, @@ -40,6 +45,57 @@ describe("mux", async () => { } }, 60000); + it("parses custom additional_arguments", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + install: false, + log_path: "/tmp/mux.log", + additional_arguments: + "--open-mode pinned --add-project '/workspaces/my repo'", + }); + + const instance = findResourceInstance(state, "coder_script"); + const id = await runContainer("alpine/curl"); + + try { + const setup = await execContainer(id, [ + "sh", + "-c", + `apk add --no-cache bash >/dev/null +mkdir -p /tmp/mux +cat <<'EOF' > /tmp/mux/mux +#!/usr/bin/env sh +i=1 +for arg in "$@"; do + echo "arg$i=$arg" + i=$((i + 1)) +done +EOF +chmod +x /tmp/mux/mux`, + ]); + expect(setup.exitCode).toBe(0); + + const output = await execContainer(id, ["sh", "-c", instance.script]); + if (output.exitCode !== 0) { + console.log("STDOUT:\n" + output.stdout); + console.log("STDERR:\n" + output.stderr); + } + expect(output.exitCode).toBe(0); + + await execContainer(id, ["sh", "-c", "sleep 1"]); + const log = await readFileContainer(id, "/tmp/mux.log"); + expect(log).toContain("arg1=server"); + expect(log).toContain("arg2=--port"); + expect(log).toContain("arg3=4000"); + expect(log).toContain("arg4=--open-mode"); + expect(log).toContain("arg5=pinned"); + expect(log).toContain("arg6=--add-project"); + expect(log).toContain("arg7=/workspaces/my repo"); + } finally { + await removeContainer(id); + } + }, 60000); + it("runs with npm present", async () => { const state = await runTerraformApply(import.meta.dir, { agent_id: "foo", diff --git a/registry/coder/modules/mux/main.tf b/registry/coder/modules/mux/main.tf index 1eeddecf..dbc585d8 100644 --- a/registry/coder/modules/mux/main.tf +++ b/registry/coder/modules/mux/main.tf @@ -55,6 +55,12 @@ variable "add-project" { default = null } +variable "additional_arguments" { + type = string + description = "Additional command-line arguments to pass to `mux server` (for example: `--add-project /path --open-mode pinned`)." + default = "" +} + variable "install_version" { type = string description = "The version or dist-tag of Mux to install." @@ -142,6 +148,7 @@ resource "coder_script" "mux" { PORT : var.port, LOG_PATH : var.log_path, ADD_PROJECT : var.add-project == null ? "" : var.add-project, + ADDITIONAL_ARGUMENTS : var.additional_arguments, INSTALL_PREFIX : var.install_prefix, OFFLINE : !var.install, USE_CACHED : var.use_cached, diff --git a/registry/coder/modules/mux/mux.tftest.hcl b/registry/coder/modules/mux/mux.tftest.hcl index af103ae2..688ddedb 100644 --- a/registry/coder/modules/mux/mux.tftest.hcl +++ b/registry/coder/modules/mux/mux.tftest.hcl @@ -79,6 +79,20 @@ run "auth_token_in_url" { } } +run "custom_additional_arguments" { + command = plan + + variables { + agent_id = "foo" + additional_arguments = "--open-mode pinned --add-project '/workspaces/my repo'" + } + + assert { + condition = strcontains(resource.coder_script.mux.script, "--open-mode pinned --add-project '/workspaces/my repo'") + error_message = "mux launch script must include the configured additional arguments" + } +} + run "custom_version" { command = plan diff --git a/registry/coder/modules/mux/run.sh b/registry/coder/modules/mux/run.sh index 0d0c6520..099448fb 100644 --- a/registry/coder/modules/mux/run.sh +++ b/registry/coder/modules/mux/run.sh @@ -20,6 +20,22 @@ function run_mux() { if [ -n "${ADD_PROJECT}" ]; then set -- "$@" --add-project "${ADD_PROJECT}" fi + + # Parse additional user-supplied server arguments while preserving quoted groups. + if [ -n "${ADDITIONAL_ARGUMENTS}" ]; then + local parsed_additional_arguments + if ! parsed_additional_arguments="$(printf "%s\n" "${ADDITIONAL_ARGUMENTS}" | xargs -n1 printf "%s\n" 2> /dev/null)"; then + echo "❌ Failed to parse additional_arguments. Ensure quotes are balanced." + exit 1 + fi + while IFS= read -r parsed_arg; do + [ -n "$parsed_arg" ] || continue + set -- "$@" "$parsed_arg" + done << EOF +$${parsed_additional_arguments} +EOF + fi + echo "🚀 Starting mux server on port $port_value..." echo "Check logs at ${LOG_PATH}!" MUX_SERVER_AUTH_TOKEN="$auth_token_value" PORT="$port_value" "$MUX_BINARY" "$@" > "${LOG_PATH}" 2>&1 & From b794b1edd91b1937c22d18781b907cf626d6ae43 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:40:40 +0100 Subject: [PATCH 2/7] feat(mux): add package_manager and registry_url variables (#761) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 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 --- registry/coder/modules/mux/README.md | 50 +++++++++--- registry/coder/modules/mux/main.test.ts | 4 +- registry/coder/modules/mux/main.tf | 20 +++++ registry/coder/modules/mux/mux.tftest.hcl | 93 +++++++++++++++++++++++ registry/coder/modules/mux/run.sh | 55 +++++++++++--- 5 files changed, 200 insertions(+), 22 deletions(-) diff --git a/registry/coder/modules/mux/README.md b/registry/coder/modules/mux/README.md index 69073926..eacf005a 100644 --- a/registry/coder/modules/mux/README.md +++ b/registry/coder/modules/mux/README.md @@ -8,13 +8,13 @@ tags: [ai, agents, development, multiplexer] # Mux -Automatically install and run [Mux](https://github.com/coder/mux) in a Coder workspace. By default, the module installs `mux@next` from npm (with a fallback to downloading the npm tarball if npm is unavailable). Mux is a desktop application for parallel agentic development that enables developers to run multiple AI agents simultaneously across isolated workspaces. +Automatically install and run [Mux](https://github.com/coder/mux) in a Coder workspace. By default, the module auto-detects an available package manager (`npm`, `pnpm`, or `bun`) to install `mux@next` (with a fallback to downloading the npm tarball if none is found). You can also force a specific package manager via `package_manager` and point to a custom registry with `registry_url`. Mux is a desktop application for parallel agentic development that enables developers to run multiple AI agents simultaneously across isolated workspaces. ```tf module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.2.0" + version = "1.3.0" agent_id = coder_agent.main.id } ``` @@ -37,7 +37,7 @@ module "mux" { module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.2.0" + version = "1.3.0" agent_id = coder_agent.main.id } ``` @@ -48,7 +48,7 @@ module "mux" { module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.2.0" + version = "1.3.0" agent_id = coder_agent.main.id # Default is "latest"; set to a specific version to pin install_version = "0.4.0" @@ -63,7 +63,7 @@ Start Mux with `mux server --add-project /path/to/project`: module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.2.0" + version = "1.3.0" agent_id = coder_agent.main.id add-project = "/path/to/project" } @@ -78,7 +78,7 @@ The module parses quoted values, so grouped arguments remain intact. module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.2.0" + version = "1.3.0" agent_id = coder_agent.main.id additional_arguments = "--open-mode pinned --add-project '/workspaces/my repo'" } @@ -90,12 +90,40 @@ module "mux" { module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.2.0" + version = "1.3.0" agent_id = coder_agent.main.id port = 8080 } ``` +### Custom Package Manager + +Force a specific package manager instead of auto-detection: + +```tf +module "mux" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/mux/coder" + version = "1.3.0" + agent_id = coder_agent.main.id + package_manager = "pnpm" # or "npm", "bun" +} +``` + +### Custom Registry + +Use a private or mirrored npm registry: + +```tf +module "mux" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/mux/coder" + version = "1.3.0" + agent_id = coder_agent.main.id + registry_url = "https://npm.pkg.github.com" +} +``` + ### Use Cached Installation Run an existing copy of Mux if found, otherwise install from npm: @@ -104,7 +132,7 @@ Run an existing copy of Mux if found, otherwise install from npm: module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.2.0" + version = "1.3.0" agent_id = coder_agent.main.id use_cached = true } @@ -118,7 +146,7 @@ Run without installing from the network (requires Mux to be pre-installed): module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.2.0" + version = "1.3.0" agent_id = coder_agent.main.id install = false } @@ -132,4 +160,6 @@ module "mux" { - Mux is currently in preview and you may encounter bugs - Requires internet connectivity for agent operations (unless `install` is set to false) -- Installs `mux@next` from npm by default (falls back to the npm tarball if npm is unavailable) +- Auto-detects `npm`, `pnpm`, or `bun` by default; set `package_manager` to force a specific one +- Installs `mux@next` from the npm registry by default; set `registry_url` to use a private or mirrored registry +- Falls back to a direct tarball download when no package manager is found diff --git a/registry/coder/modules/mux/main.test.ts b/registry/coder/modules/mux/main.test.ts index c1b6e238..cc2e70db 100644 --- a/registry/coder/modules/mux/main.test.ts +++ b/registry/coder/modules/mux/main.test.ts @@ -35,7 +35,7 @@ describe("mux", async () => { } expect(output.exitCode).toBe(0); const expectedLines = [ - "📥 npm not found; downloading tarball from npm registry...", + "📥 No package manager found; downloading tarball from registry...", "🥳 mux has been installed in /tmp/mux", "🚀 Starting mux server on port 4000...", "Check logs at /tmp/mux.log!", @@ -111,7 +111,7 @@ chmod +x /tmp/mux/mux`, expect(output.exitCode).toBe(0); const expectedLines = [ "📦 Installing mux via npm into /tmp/mux...", - "⏭️ Skipping npm lifecycle scripts with --ignore-scripts", + "⏭️ Skipping lifecycle scripts with --ignore-scripts", "🥳 mux has been installed in /tmp/mux", "🚀 Starting mux server on port 4000...", "Check logs at /tmp/mux.log!", diff --git a/registry/coder/modules/mux/main.tf b/registry/coder/modules/mux/main.tf index dbc585d8..7ca97ccc 100644 --- a/registry/coder/modules/mux/main.tf +++ b/registry/coder/modules/mux/main.tf @@ -67,6 +67,23 @@ variable "install_version" { default = "next" } +variable "package_manager" { + type = string + description = "Package manager to install Mux. 'auto' detects npm, pnpm, or bun (falling back to tarball download). Set to 'npm', 'pnpm', or 'bun' to force a specific one." + default = "auto" + validation { + condition = contains(["auto", "npm", "pnpm", "bun"], var.package_manager) + error_message = "The 'package_manager' variable must be one of: 'auto', 'npm', 'pnpm', 'bun'." + } +} + +variable "registry_url" { + type = string + description = "The npm-compatible registry URL to install Mux from. Override this for private registries or mirrors." + default = "https://registry.npmjs.org" +} + + variable "share" { type = string default = "owner" @@ -137,6 +154,7 @@ resource "random_password" "mux_auth_token" { locals { mux_auth_token = random_password.mux_auth_token.result + registry_url = trimsuffix(var.registry_url, "/") } resource "coder_script" "mux" { @@ -153,6 +171,8 @@ resource "coder_script" "mux" { OFFLINE : !var.install, USE_CACHED : var.use_cached, AUTH_TOKEN : local.mux_auth_token, + PACKAGE_MANAGER : var.package_manager, + REGISTRY_URL : local.registry_url, }) run_on_start = true diff --git a/registry/coder/modules/mux/mux.tftest.hcl b/registry/coder/modules/mux/mux.tftest.hcl index 688ddedb..42569997 100644 --- a/registry/coder/modules/mux/mux.tftest.hcl +++ b/registry/coder/modules/mux/mux.tftest.hcl @@ -121,3 +121,96 @@ run "use_cached_only_success" { use_cached = true } } + +# Custom package_manager should appear in generated script +run "custom_package_manager_npm" { + command = plan + + variables { + agent_id = "foo" + package_manager = "npm" + } + + assert { + condition = strcontains(resource.coder_script.mux.script, "PM_CMD=\"npm\"") + error_message = "mux script must set PM_CMD to the configured package manager" + } +} + +run "custom_package_manager_pnpm" { + command = plan + + variables { + agent_id = "foo" + package_manager = "pnpm" + } + + assert { + condition = strcontains(resource.coder_script.mux.script, "PM_CMD=\"pnpm\"") + error_message = "mux script must set PM_CMD to the configured package manager" + } +} + +run "custom_package_manager_bun" { + command = plan + + variables { + agent_id = "foo" + package_manager = "bun" + } + + assert { + condition = strcontains(resource.coder_script.mux.script, "PM_CMD=\"bun\"") + error_message = "mux script must set PM_CMD to the configured package manager" + } +} + +# Invalid package_manager should fail validation +run "invalid_package_manager" { + command = plan + + variables { + agent_id = "foo" + package_manager = "yarn" + } + + expect_failures = [ + var.package_manager + ] +} + +# Custom registry_url should appear in generated script +run "custom_registry_url" { + command = plan + + variables { + agent_id = "foo" + registry_url = "https://npm.example.com" + } + + assert { + condition = strcontains(resource.coder_script.mux.script, "https://npm.example.com") + error_message = "mux script must use the configured registry URL" + } + + assert { + condition = !strcontains(resource.coder_script.mux.script, "registry.npmjs.org") + error_message = "mux script must not contain hardcoded registry.npmjs.org when custom registry is set" + } +} + +# registry_url trailing slash should be stripped +run "registry_url_trailing_slash" { + command = plan + + variables { + agent_id = "foo" + registry_url = "https://npm.example.com/" + } + + assert { + condition = strcontains(resource.coder_script.mux.script, "https://npm.example.com/mux/") + error_message = "registry URL trailing slash must be stripped to avoid double slashes" + } +} + diff --git a/registry/coder/modules/mux/run.sh b/registry/coder/modules/mux/run.sh index 099448fb..2dbd5ea9 100644 --- a/registry/coder/modules/mux/run.sh +++ b/registry/coder/modules/mux/run.sh @@ -54,7 +54,7 @@ fi # If there is no cached install OR we don't want to use a cached install if [ ! -f "$MUX_BINARY" ] || [ "${USE_CACHED}" != true ]; then - printf "$${BOLD}Installing mux from npm...\n" + printf "$${BOLD}Installing mux...\n" # Clean up from other install (in case install prefix changed). if [ -n "$CODER_SCRIPT_BIN_DIR" ] && [ -e "$CODER_SCRIPT_BIN_DIR/mux" ]; then @@ -63,41 +63,76 @@ if [ ! -f "$MUX_BINARY" ] || [ "${USE_CACHED}" != true ]; then mkdir -p "$(dirname "$MUX_BINARY")" - if command -v npm > /dev/null 2>&1; then - echo "📦 Installing mux via npm into ${INSTALL_PREFIX}..." + # Determine which package manager to use + PM_CMD="" + if [ "${PACKAGE_MANAGER}" = "auto" ]; then + for pm in npm pnpm bun; do + if command -v "$pm" > /dev/null 2>&1; then + PM_CMD="$pm" + break + fi + done + else + PM_CMD="${PACKAGE_MANAGER}" + if ! command -v "$PM_CMD" > /dev/null 2>&1; then + echo "❌ Configured package manager '${PACKAGE_MANAGER}' not found on PATH" + exit 1 + fi + fi + + if [ -n "$PM_CMD" ]; then + echo "📦 Installing mux via $PM_CMD into ${INSTALL_PREFIX}..." NPM_WORKDIR="${INSTALL_PREFIX}/npm" mkdir -p "$NPM_WORKDIR" cd "$NPM_WORKDIR" || exit 1 if [ ! -f package.json ]; then echo '{}' > package.json fi - echo "⏭️ Skipping npm lifecycle scripts with --ignore-scripts" + echo "⏭️ Skipping lifecycle scripts with --ignore-scripts" PKG="mux" if [ -z "${VERSION}" ] || [ "${VERSION}" = "latest" ]; then PKG_SPEC="$PKG@latest" else PKG_SPEC="$PKG@${VERSION}" fi - if ! npm install --no-audit --no-fund --omit=dev --ignore-scripts "$PKG_SPEC"; then - echo "❌ Failed to install mux via npm" + INSTALL_OK=true + case "$PM_CMD" in + npm) + if ! npm install --no-audit --no-fund --omit=dev --ignore-scripts --registry "${REGISTRY_URL}" "$PKG_SPEC"; then + INSTALL_OK=false + fi + ;; + pnpm) + if ! pnpm add --ignore-scripts --registry "${REGISTRY_URL}" "$PKG_SPEC"; then + INSTALL_OK=false + fi + ;; + bun) + if ! bun add --ignore-scripts --registry "${REGISTRY_URL}" "$PKG_SPEC"; then + INSTALL_OK=false + fi + ;; + esac + if [ "$INSTALL_OK" != true ]; then + echo "❌ Failed to install mux via $PM_CMD" exit 1 fi # Determine the installed binary path BIN_DIR="$NPM_WORKDIR/node_modules/.bin" CANDIDATE="$BIN_DIR/mux" if [ ! -f "$CANDIDATE" ]; then - echo "❌ Could not locate mux binary after npm install" + echo "❌ Could not locate mux binary after $PM_CMD install" exit 1 fi chmod +x "$CANDIDATE" || true ln -sf "$CANDIDATE" "$MUX_BINARY" else - echo "📥 npm not found; downloading tarball from npm registry..." + echo "📥 No package manager found; downloading tarball from registry..." VERSION_TO_USE="${VERSION}" if [ -z "$VERSION_TO_USE" ]; then VERSION_TO_USE="next" fi - META_URL="https://registry.npmjs.org/mux/$VERSION_TO_USE" + META_URL="${REGISTRY_URL}/mux/$VERSION_TO_USE" META_JSON="$(curl -fsSL "$META_URL" || true)" if [ -z "$META_JSON" ]; then echo "❌ Failed to fetch npm metadata: $META_URL" @@ -136,7 +171,7 @@ if [ ! -f "$MUX_BINARY" ] || [ "${USE_CACHED}" != true ]; then echo "❌ Could not determine version for mux" exit 1 fi - TARBALL_URL="https://registry.npmjs.org/mux/-/mux-$VERSION_TO_USE.tgz" + TARBALL_URL="${REGISTRY_URL}/mux/-/mux-$VERSION_TO_USE.tgz" fi TMP_DIR="$(mktemp -d)" TAR_PATH="$TMP_DIR/mux.tgz" From 6ec506e9b60358e68b2a5e537c9f89f343cafbbf Mon Sep 17 00:00:00 2001 From: "blinkagent[bot]" <237617714+blinkagent[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 13:30:20 -0600 Subject: [PATCH 3/7] fix(dotfiles): allow tilde (~) in git repository URLs (#763) ## 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> --- registry/coder/modules/dotfiles/README.md | 12 ++++++------ registry/coder/modules/dotfiles/main.test.ts | 1 + registry/coder/modules/dotfiles/main.tf | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/registry/coder/modules/dotfiles/README.md b/registry/coder/modules/dotfiles/README.md index 9cb6a45d..c0042e3f 100644 --- a/registry/coder/modules/dotfiles/README.md +++ b/registry/coder/modules/dotfiles/README.md @@ -18,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.3.0" + version = "1.3.1" agent_id = coder_agent.example.id } ``` @@ -31,7 +31,7 @@ module "dotfiles" { module "dotfiles" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/dotfiles/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.example.id } ``` @@ -42,7 +42,7 @@ module "dotfiles" { module "dotfiles" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/dotfiles/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.example.id user = "root" } @@ -54,14 +54,14 @@ module "dotfiles" { module "dotfiles" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/dotfiles/coder" - version = "1.3.0" + version = "1.3.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.3.0" + version = "1.3.1" agent_id = coder_agent.example.id user = "root" dotfiles_uri = module.dotfiles.dotfiles_uri @@ -76,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.3.0" + version = "1.3.1" agent_id = coder_agent.example.id default_dotfiles_uri = "https://github.com/coder/dotfiles" } diff --git a/registry/coder/modules/dotfiles/main.test.ts b/registry/coder/modules/dotfiles/main.test.ts index 90fe91c8..8cde2510 100644 --- a/registry/coder/modules/dotfiles/main.test.ts +++ b/registry/coder/modules/dotfiles/main.test.ts @@ -26,6 +26,7 @@ describe("dotfiles", async () => { "git@github.com:coder/dotfiles.git", "git://github.com/coder/dotfiles.git", "ssh://git@github.com/coder/dotfiles.git", + "ssh://git@bitbucket.example.org:7999/~myusername/dotfiles.git", ]; for (const url of validUrls) { const state = await runTerraformApply(import.meta.dir, { diff --git a/registry/coder/modules/dotfiles/main.tf b/registry/coder/modules/dotfiles/main.tf index 40b1a4e0..4f566dea 100644 --- a/registry/coder/modules/dotfiles/main.tf +++ b/registry/coder/modules/dotfiles/main.tf @@ -40,7 +40,7 @@ variable "default_dotfiles_uri" { validation { condition = ( var.default_dotfiles_uri == "" || - can(regex("^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@-]+$", var.default_dotfiles_uri)) + can(regex("^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@~-]+$", var.default_dotfiles_uri)) ) error_message = "Must be a valid dotfiles repository URL (https, git@, or git://) without special characters." } @@ -55,7 +55,7 @@ variable "dotfiles_uri" { condition = ( var.dotfiles_uri == null || var.dotfiles_uri == "" || - can(regex("^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@-]+$", var.dotfiles_uri)) + can(regex("^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@~-]+$", var.dotfiles_uri)) ) error_message = "Must be a valid dotfiles repository URL (https, git@, or git://) without special characters." } @@ -102,7 +102,7 @@ data "coder_parameter" "dotfiles_uri" { icon = "/icon/dotfiles.svg" validation { - regex = "^$|^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@-]+$" + regex = "^$|^(https?://|ssh://|git@|git://)[a-zA-Z0-9._/:@~-]+$" error = "Must be a valid dotfiles repository URL (https, git@, or git://) without special characters." } } From 93e6094b1bdf733f9848dc97b53c8635f1c59f3b Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Fri, 27 Feb 2026 17:44:39 +0100 Subject: [PATCH 4/7] fix: rename add-project to add_project in mux module (#765) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- registry/coder/modules/mux/README.md | 22 +++++++++++----------- registry/coder/modules/mux/main.tf | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/registry/coder/modules/mux/README.md b/registry/coder/modules/mux/README.md index eacf005a..6a5c3b0f 100644 --- a/registry/coder/modules/mux/README.md +++ b/registry/coder/modules/mux/README.md @@ -14,7 +14,7 @@ Automatically install and run [Mux](https://github.com/coder/mux) in a Coder wor module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.main.id } ``` @@ -37,7 +37,7 @@ module "mux" { module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.main.id } ``` @@ -48,7 +48,7 @@ module "mux" { module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.main.id # Default is "latest"; set to a specific version to pin install_version = "0.4.0" @@ -63,9 +63,9 @@ Start Mux with `mux server --add-project /path/to/project`: module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.main.id - add-project = "/path/to/project" + add_project = "/path/to/project" } ``` @@ -78,7 +78,7 @@ The module parses quoted values, so grouped arguments remain intact. module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.main.id additional_arguments = "--open-mode pinned --add-project '/workspaces/my repo'" } @@ -90,7 +90,7 @@ module "mux" { module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.main.id port = 8080 } @@ -104,7 +104,7 @@ Force a specific package manager instead of auto-detection: module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.main.id package_manager = "pnpm" # or "npm", "bun" } @@ -118,7 +118,7 @@ Use a private or mirrored npm registry: module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.main.id registry_url = "https://npm.pkg.github.com" } @@ -132,7 +132,7 @@ Run an existing copy of Mux if found, otherwise install from npm: module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.main.id use_cached = true } @@ -146,7 +146,7 @@ Run without installing from the network (requires Mux to be pre-installed): module "mux" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/mux/coder" - version = "1.3.0" + version = "1.3.1" agent_id = coder_agent.main.id install = false } diff --git a/registry/coder/modules/mux/main.tf b/registry/coder/modules/mux/main.tf index 7ca97ccc..ba475b0c 100644 --- a/registry/coder/modules/mux/main.tf +++ b/registry/coder/modules/mux/main.tf @@ -49,7 +49,7 @@ variable "log_path" { default = "/tmp/mux.log" } -variable "add-project" { +variable "add_project" { type = string description = "Optional path to add/open as a project in Mux on startup." default = null @@ -165,7 +165,7 @@ resource "coder_script" "mux" { VERSION : var.install_version, PORT : var.port, LOG_PATH : var.log_path, - ADD_PROJECT : var.add-project == null ? "" : var.add-project, + ADD_PROJECT : var.add_project == null ? "" : var.add_project, ADDITIONAL_ARGUMENTS : var.additional_arguments, INSTALL_PREFIX : var.install_prefix, OFFLINE : !var.install, From eb38bc3092d2e55904da30d0bef3ae1e19b439db Mon Sep 17 00:00:00 2001 From: "blinkagent[bot]" <237617714+blinkagent[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:15:47 -0600 Subject: [PATCH 5/7] ci: add variable naming lint to terraform validate (#766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 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 --- registry/coder/modules/code-server/README.md | 16 ++++----- registry/coder/modules/code-server/main.tf | 4 +-- scripts/terraform_validate.sh | 38 ++++++++++++++++++++ 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/registry/coder/modules/code-server/README.md b/registry/coder/modules/code-server/README.md index 3312f979..fdb3f1a7 100644 --- a/registry/coder/modules/code-server/README.md +++ b/registry/coder/modules/code-server/README.md @@ -14,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.4.2" + version = "1.4.3" agent_id = coder_agent.example.id } ``` @@ -29,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.4.2" + version = "1.4.3" agent_id = coder_agent.example.id install_version = "4.106.3" } @@ -43,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.4.2" + version = "1.4.3" agent_id = coder_agent.example.id extensions = [ "dracula-theme.theme-dracula" @@ -61,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.4.2" + version = "1.4.3" agent_id = coder_agent.example.id extensions = ["dracula-theme.theme-dracula"] settings = { @@ -78,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.4.2" + version = "1.4.3" agent_id = coder_agent.example.id extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"] } @@ -92,7 +92,7 @@ You can pass additional command-line arguments to code-server using the `additio module "code-server" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/code-server/coder" - version = "1.4.2" + version = "1.4.3" agent_id = coder_agent.example.id additional_args = "--disable-workspace-trust" } @@ -108,7 +108,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.4.2" + version = "1.4.3" agent_id = coder_agent.example.id use_cached = true extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"] @@ -121,7 +121,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.4.2" + version = "1.4.3" agent_id = coder_agent.example.id offline = true } diff --git a/registry/coder/modules/code-server/main.tf b/registry/coder/modules/code-server/main.tf index f5651353..090b6a53 100644 --- a/registry/coder/modules/code-server/main.tf +++ b/registry/coder/modules/code-server/main.tf @@ -44,7 +44,7 @@ variable "settings" { default = {} } -variable "machine-settings" { +variable "machine_settings" { type = any description = "A map of template level machine settings to apply to code-server. This will be overwritten at each container start." default = {} @@ -167,7 +167,7 @@ resource "coder_script" "code-server" { INSTALL_PREFIX : var.install_prefix, // This is necessary otherwise the quotes are stripped! SETTINGS : replace(jsonencode(var.settings), "\"", "\\\""), - MACHINE_SETTINGS : replace(jsonencode(var.machine-settings), "\"", "\\\""), + MACHINE_SETTINGS : replace(jsonencode(var.machine_settings), "\"", "\\\""), OFFLINE : var.offline, USE_CACHED : var.use_cached, USE_CACHED_EXTENSIONS : var.use_cached_extensions, diff --git a/scripts/terraform_validate.sh b/scripts/terraform_validate.sh index 9126e28e..44f95b61 100755 --- a/scripts/terraform_validate.sh +++ b/scripts/terraform_validate.sh @@ -11,6 +11,34 @@ set -euo pipefail # # This script only validates changed modules. Documentation and template changes are ignored. +# Validates that Terraform variable names use underscores (snake_case) instead +# of hyphens. Hyphens are technically valid but deprecated and non-idiomatic. +# See: https://developer.hashicorp.com/terraform/language/values/variables +validate_variable_names() { + local dir="$1" + local found_issues=0 + + while IFS= read -r tf_file; do + while IFS= read -r match; do + local line_num + line_num=$(echo "$match" | cut -d: -f1) + local line_content + line_content=$(echo "$match" | cut -d: -f2-) + local var_name + var_name=$(echo "$line_content" | sed -n 's/.*variable "\([^"]*\)".*/\1/p') + + if [[ -n "$var_name" ]]; then + echo " ERROR: $tf_file:$line_num" + echo " Variable \"$var_name\" contains a hyphen." + echo " Rename to \"${var_name//-/_}\" (use underscores instead of hyphens)." + found_issues=$((found_issues + 1)) + fi + done < <(grep -n 'variable "[^"]*-[^"]*"' "$tf_file" 2> /dev/null || true) + done < <(find "$dir" -name '*.tf' -type f | sort) + + return "$found_issues" +} + validate_terraform_directory() { local dir="$1" echo "Running \`terraform validate\` in $dir" @@ -91,6 +119,16 @@ main() { fi done + echo "" + echo "==> Validating Terraform variable names use snake_case..." + for dir in $subdirs; do + if test -f "$dir/main.tf"; then + if ! validate_variable_names "$dir"; then + status=1 + fi + fi + done + exit $status } From a0a3783a519d873fec063cd9b29211694375c63a Mon Sep 17 00:00:00 2001 From: "blinkagent[bot]" <237617714+blinkagent[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:48:55 -0600 Subject: [PATCH 6/7] docs(dotfiles): add hint about using SSH URLs when HTTPS cloning is restricted (#757) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- registry/coder/modules/dotfiles/README.md | 26 +++++++++++++++++------ registry/coder/modules/dotfiles/main.tf | 2 +- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/registry/coder/modules/dotfiles/README.md b/registry/coder/modules/dotfiles/README.md index c0042e3f..c78b80c3 100644 --- a/registry/coder/modules/dotfiles/README.md +++ b/registry/coder/modules/dotfiles/README.md @@ -18,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.3.1" + version = "1.3.2" agent_id = coder_agent.example.id } ``` @@ -31,7 +31,7 @@ module "dotfiles" { module "dotfiles" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/dotfiles/coder" - version = "1.3.1" + version = "1.3.2" agent_id = coder_agent.example.id } ``` @@ -42,7 +42,7 @@ module "dotfiles" { module "dotfiles" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/dotfiles/coder" - version = "1.3.1" + version = "1.3.2" agent_id = coder_agent.example.id user = "root" } @@ -54,20 +54,34 @@ module "dotfiles" { module "dotfiles" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/dotfiles/coder" - version = "1.3.1" + version = "1.3.2" 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.3.1" + version = "1.3.2" agent_id = coder_agent.example.id user = "root" dotfiles_uri = module.dotfiles.dotfiles_uri } ``` +## SSH vs HTTPS URLs + +If your Git provider (e.g. GitLab, GitHub Enterprise) restricts HTTPS cloning, use an SSH URL instead: + +```text +# HTTPS (may fail if HTTP cloning is disabled) +https://gitlab.example.com/user/dotfiles.git + +# SSH (uses the workspace's SSH key) +git@gitlab.example.com:user/dotfiles.git +``` + +When a Git provider has HTTPS cloning disabled server-side, the clone will silently fail (the `.git` folder may exist but the working tree will be empty). SSH URLs avoid this because they authenticate with the workspace's SSH key instead of a token-based HTTPS flow. + ## Setting a default dotfiles repository You can set a default dotfiles repository for all users by setting the `default_dotfiles_uri` variable: @@ -76,7 +90,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.3.1" + version = "1.3.2" agent_id = coder_agent.example.id default_dotfiles_uri = "https://github.com/coder/dotfiles" } diff --git a/registry/coder/modules/dotfiles/main.tf b/registry/coder/modules/dotfiles/main.tf index 4f566dea..7b15a391 100644 --- a/registry/coder/modules/dotfiles/main.tf +++ b/registry/coder/modules/dotfiles/main.tf @@ -29,7 +29,7 @@ variable "agent_id" { variable "description" { type = string description = "A custom description for the dotfiles parameter. This is shown in the UI - and allows you to customize the instructions you give to your users." - default = "Enter a URL for a [dotfiles repository](https://dotfiles.github.io) to personalize your workspace" + default = "Enter a URL for a [dotfiles repository](https://dotfiles.github.io) to personalize your workspace. Use an SSH URL (e.g. `git@host:user/repo`) if your Git provider restricts HTTPS cloning." } variable "default_dotfiles_uri" { From 71a4cf20318e073056b58d691a3dad6499421152 Mon Sep 17 00:00:00 2001 From: Atif Ali Date: Mon, 2 Mar 2026 10:07:58 +0500 Subject: [PATCH 7/7] chore(coder/modules/mux): update Mux logo (#775) Update Mux logo --- .icons/mux.svg | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.icons/mux.svg b/.icons/mux.svg index 3ee3276d..70dff277 100644 --- a/.icons/mux.svg +++ b/.icons/mux.svg @@ -1 +1,11 @@ - \ No newline at end of file + + + + + + + + + + +