From 2148b513c42f4fea1c0b95fe6eabe73efc86ab75 Mon Sep 17 00:00:00 2001 From: Ammar Date: Fri, 14 Nov 2025 18:34:22 +0000 Subject: [PATCH 1/9] =?UTF-8?q?=F0=9F=A4=96=20chore:=20rename=20cmux=20ref?= =?UTF-8?q?s=20to=20mux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 +- .github/workflows/release.yml | 4 +- .gitignore | 2 +- README.md | 10 +- benchmarks/terminal_bench/README.md | 7 +- benchmarks/terminal_bench/mux_agent.py | 96 +++++++++---------- benchmarks/terminal_bench/mux_agent_test.py | 40 ++++---- benchmarks/terminal_bench/mux_payload.py | 6 +- benchmarks/terminal_bench/mux_setup.sh.j2 | 26 ++--- docs/benchmarking.md | 32 +++---- docs/theme/custom.css | 4 +- public/service-worker.js | 4 +- scripts/check_pr_reviews.sh | 4 +- scripts/extract_pr_logs.sh | 2 +- src/browser/App.stories.tsx | 90 +++++++++-------- src/browser/App.tsx | 2 +- src/browser/api.ts | 2 +- src/browser/components/AIView.tsx | 3 +- .../components/ChatInput/CreationControls.tsx | 4 +- src/browser/components/ChatInput/index.tsx | 6 +- .../components/CommandPalette.stories.tsx | 2 +- src/browser/components/Modal.stories.tsx | 2 +- src/browser/components/ProjectSidebar.tsx | 2 +- src/browser/components/SecretsModal.tsx | 2 +- src/browser/components/TitleBar.tsx | 4 +- src/browser/hooks/useAutoCompactContinue.ts | 18 ++-- src/browser/stores/GitStatusStore.test.ts | 18 ++-- src/browser/stores/WorkspaceStore.test.ts | 2 +- src/browser/stores/WorkspaceStore.ts | 10 +- src/browser/utils/chatCommands.test.ts | 12 +-- src/browser/utils/chatCommands.ts | 4 +- .../messages/StreamingMessageAggregator.ts | 10 +- src/browser/utils/ui/runtimeBadge.test.ts | 12 +-- src/cli/debug/agentSessionCli.ts | 2 +- src/cli/debug/git-status.ts | 12 +-- src/cli/debug/list-workspaces.ts | 2 +- src/cli/server.ts | 4 +- src/common/constants/events.ts | 18 ++-- src/common/constants/paths.ts | 15 +-- src/common/constants/workspace.ts | 2 +- src/common/telemetry/client.ts | 2 +- src/common/telemetry/lifecycle.ts | 2 +- src/common/types/ipc.ts | 2 +- src/common/types/message.ts | 4 +- src/common/types/project.ts | 6 +- src/common/types/runtime.ts | 2 +- src/common/types/workspace.ts | 2 +- src/common/utils/compaction/handler.ts | 10 +- src/common/utils/paths.ts | 8 +- src/desktop/main.ts | 7 +- src/node/bench/headlessEnvironment.ts | 2 +- src/node/config.test.ts | 2 +- src/node/config.ts | 2 +- src/node/git.test.ts | 2 +- src/node/runtime/Runtime.ts | 12 +-- src/node/runtime/SSHRuntime.test.ts | 4 +- src/node/runtime/SSHRuntime.ts | 4 +- src/node/runtime/sshConnectionPool.test.ts | 6 +- src/node/runtime/sshConnectionPool.ts | 2 +- src/node/services/ExtensionMetadataService.ts | 2 +- src/node/services/agentSession.ts | 4 +- src/node/services/aiService.ts | 18 ++-- src/node/services/historyService.test.ts | 2 +- src/node/services/initStateManager.test.ts | 2 +- src/node/services/ipcMain.ts | 2 +- src/node/services/log.ts | 6 +- src/node/services/streamManager.ts | 8 +- src/node/services/tempDir.ts | 2 +- src/node/services/tools/bash.ts | 2 +- src/node/services/tools/fileCommon.test.ts | 6 +- src/node/services/tools/fileCommon.ts | 2 +- src/node/utils/eventStore.test.ts | 2 +- src/node/utils/main/instructionFiles.ts | 2 +- src/node/utils/main/tokenizer.test.ts | 2 +- src/node/utils/pathUtils.test.ts | 8 +- src/node/utils/paths.test.ts | 26 ++--- src/node/utils/sessionFile.ts | 2 +- tests/ipcMain/sendMessage.test.ts | 14 +-- tests/runtime/ssh-server/Dockerfile | 2 +- vscode/Makefile | 12 +-- vscode/bun.lock | 2 +- vscode/esbuild.config.js | 14 +-- vscode/scripts/create-icon.sh | 5 + vscode/src/extension.ts | 4 +- vscode/src/{cmuxConfig.ts => muxConfig.ts} | 12 +-- vscode/src/workspaceOpener.ts | 2 +- vscode/tsconfig.json | 2 +- 87 files changed, 381 insertions(+), 366 deletions(-) rename vscode/src/{cmuxConfig.ts => muxConfig.ts} (81%) diff --git a/.env.example b/.env.example index 446d199bb7..5a410a9254 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -# Environment variables for cmux development +# Environment variables for mux development # API Keys for AI providers # Required for integration tests when TEST_INTEGRATION=1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2bee684d03..c1234e146b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -93,7 +93,9 @@ jobs: with: fetch-depth: 0 # Required for git describe to find tags - - uses: ./.github/actions/setup-cmux + - uses: ./.github/actions/setup-mux + with: + install-imagemagick: true - name: Install GNU Make (for build) run: choco install -y make diff --git a/.gitignore b/.gitignore index 95ebafe918..a71f312051 100644 --- a/.gitignore +++ b/.gitignore @@ -108,7 +108,7 @@ runs/ __pycache__ tmpfork -.cmux-agent-cli +.mux-agent-cli storybook-static/ *.tgz src/test-workspaces/ diff --git a/README.md b/README.md index ba7ea30dcd..90cc9c0d8b 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ # mux - coding agent multiplexer -[![CI](https://github.com/coder/cmux/actions/workflows/ci.yml/badge.svg)](https://github.com/coder/cmux/actions/workflows/ci.yml) -[![Build](https://github.com/coder/cmux/actions/workflows/build.yml/badge.svg?event=merge_group)](https://github.com/coder/cmux/actions/workflows/build.yml?query=event:merge_group) -[![Download](https://img.shields.io/badge/Download-Releases-purple)](https://github.com/coder/cmux/releases) +[![CI](https://github.com/coder/mux/actions/workflows/ci.yml/badge.svg)](https://github.com/coder/mux/actions/workflows/ci.yml) +[![Build](https://github.com/coder/mux/actions/workflows/build.yml/badge.svg?event=merge_group)](https://github.com/coder/mux/actions/workflows/build.yml?query=event:merge_group) +[![Download](https://img.shields.io/badge/Download-Releases-purple)](https://github.com/coder/mux/releases) [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE) @@ -51,10 +51,10 @@ like [opportunistic compaction](https://cmux.io/context-management.html) and [mo ## Install > [!WARNING] -> cmux is in a Preview state. You will encounter bugs and performance issues. +> mux is in a Preview state. You will encounter bugs and performance issues. > It's still possible to be highly productive. We are using it almost exclusively for our own development. -Download pre-built binaries from [the releases page](https://github.com/coder/cmux/releases) for +Download pre-built binaries from [the releases page](https://github.com/coder/mux/releases) for macOS and Linux. [More on installation →](https://cmux.io/install.html) diff --git a/benchmarks/terminal_bench/README.md b/benchmarks/terminal_bench/README.md index 31af9f1a84..499932bc29 100644 --- a/benchmarks/terminal_bench/README.md +++ b/benchmarks/terminal_bench/README.md @@ -1,6 +1,6 @@ # Terminal-Bench Integration -This directory contains the cmux agent adapter for [Terminal-Bench](https://github.com/benediktstroebl/terminal-bench), a benchmarking framework for evaluating agentic CLI/terminal capabilities. +This directory contains the mux agent adapter for [Terminal-Bench](https://github.com/benediktstroebl/terminal-bench), a benchmarking framework for evaluating agentic CLI/terminal capabilities. ## Quick Start @@ -57,7 +57,7 @@ TB_TIMEOUT=600 make benchmark-terminal TB_SAMPLE_SIZE=5 ## Agent Configuration -The cmux agent supports the following kwargs (passed via `--agent-kwarg`): +The mux agent supports the following kwargs (passed via `--agent-kwarg`): - `model_name`: Model to use (e.g., `anthropic:claude-sonnet-4-5`, `openai:gpt-5-codex`) - `thinking_level`: Thinking level (`off`, `low`, `medium`, `high`) @@ -103,6 +103,7 @@ Based on analysis of the Oct 30 nightly run (15-minute timeout): - `mux_agent.py`: Main agent adapter implementing Terminal-Bench's agent interface - `mux-run.sh`: Shell script that sets up environment and invokes mux CLI -- `mux_payload.py`: Helper to package the mux app for containerized execution +- `mux_payload.py`: Helper to package mux app for containerized execution +- `mux_payload.py`: Helper to package mux app for containerized execution - `mux_setup.sh.j2`: Jinja2 template for agent installation script - `sample_tasks.py`: Utility to randomly sample tasks from dataset diff --git a/benchmarks/terminal_bench/mux_agent.py b/benchmarks/terminal_bench/mux_agent.py index 237e18f4e2..ff9bf71e4d 100644 --- a/benchmarks/terminal_bench/mux_agent.py +++ b/benchmarks/terminal_bench/mux_agent.py @@ -17,12 +17,12 @@ class MuxAgent(AbstractInstalledAgent): """ - Minimal Terminal-Bench adapter that installs cmux into the task container and - forwards the benchmark instruction to the cmux headless runner. + Minimal Terminal-Bench adapter that installs mux into the task container and + forwards the benchmark instruction to the mux headless runner. """ - _ARCHIVE_NAME = "cmux-app.tar.gz" - _RUNNER_NAME = "cmux-run.sh" + _ARCHIVE_NAME = "mux-app.tar.gz" + _RUNNER_NAME = "mux-run.sh" _DEFAULT_TRUNK = "main" _DEFAULT_MODEL = "anthropic:claude-sonnet-4-5" _DEFAULT_PROJECT_CANDIDATES = "/workspace:/app:/workspaces:/root/project" @@ -50,18 +50,18 @@ class MuxAgent(AbstractInstalledAgent): ) _CONFIG_ENV_KEYS: Sequence[str] = ( - "CMUX_AGENT_GIT_URL", - "CMUX_BUN_INSTALL_URL", - "CMUX_PROJECT_PATH", - "CMUX_PROJECT_CANDIDATES", - "CMUX_TRUNK", - "CMUX_MODEL", - "CMUX_TIMEOUT_MS", - "CMUX_THINKING_LEVEL", - "CMUX_CONFIG_ROOT", - "CMUX_APP_ROOT", - "CMUX_WORKSPACE_ID", - "CMUX_MODE", + "MUX_AGENT_GIT_URL", + "MUX_BUN_INSTALL_URL", + "MUX_PROJECT_PATH", + "MUX_PROJECT_CANDIDATES", + "MUX_TRUNK", + "MUX_MODEL", + "MUX_TIMEOUT_MS", + "MUX_THINKING_LEVEL", + "MUX_CONFIG_ROOT", + "MUX_APP_ROOT", + "MUX_WORKSPACE_ID", + "MUX_MODE", ) def __init__( @@ -72,18 +72,18 @@ def __init__( **kwargs: Any, ) -> None: super().__init__(**kwargs) - repo_root_env = os.environ.get("CMUX_AGENT_REPO_ROOT") + repo_root_env = os.environ.get("MUX_AGENT_REPO_ROOT") repo_root = ( Path(repo_root_env).resolve() if repo_root_env else Path(__file__).resolve().parents[2] ) if not repo_root.exists(): - raise RuntimeError(f"cmux repo root {repo_root} does not exist") + raise RuntimeError(f"mux repo root {repo_root} does not exist") runner_path = Path(__file__).with_name(self._RUNNER_NAME) if not runner_path.is_file(): - raise RuntimeError(f"cmux runner script missing at {runner_path}") + raise RuntimeError(f"mux runner script missing at {runner_path}") self._runner_path = runner_path self._repo_root = repo_root @@ -95,7 +95,7 @@ def __init__( @staticmethod def name() -> str: - return "cmux" + return "mux" @property def _env(self) -> dict[str, str]: @@ -106,63 +106,61 @@ def _env(self) -> dict[str, str]: if value: env[key] = value - env.setdefault("CMUX_TRUNK", self._DEFAULT_TRUNK) - env.setdefault("CMUX_MODEL", self._DEFAULT_MODEL) - env.setdefault("CMUX_CONFIG_ROOT", "/root/.cmux") - env.setdefault("CMUX_APP_ROOT", "/opt/cmux-app") - env.setdefault("CMUX_WORKSPACE_ID", "cmux-bench") - env.setdefault("CMUX_THINKING_LEVEL", "high") - env.setdefault("CMUX_MODE", "exec") - env.setdefault("CMUX_PROJECT_CANDIDATES", self._DEFAULT_PROJECT_CANDIDATES) + env.setdefault("MUX_TRUNK", self._DEFAULT_TRUNK) + env.setdefault("MUX_MODEL", self._DEFAULT_MODEL) + env.setdefault("MUX_CONFIG_ROOT", "/root/.mux") + env.setdefault("MUX_APP_ROOT", "/opt/mux-app") + env.setdefault("MUX_WORKSPACE_ID", "mux-bench") + env.setdefault("MUX_THINKING_LEVEL", "high") + env.setdefault("MUX_MODE", "exec") + env.setdefault("MUX_PROJECT_CANDIDATES", self._DEFAULT_PROJECT_CANDIDATES) - model_value = self._model_name or env["CMUX_MODEL"] + model_value = self._model_name or env["MUX_MODEL"] model_value = model_value.strip() if not model_value: - raise ValueError("CMUX_MODEL must be a non-empty string") + raise ValueError("MUX_MODEL must be a non-empty string") if "/" in model_value and ":" not in model_value: provider, model_name = model_value.split("/", 1) model_value = f"{provider}:{model_name}" - env["CMUX_MODEL"] = model_value + env["MUX_MODEL"] = model_value - thinking_value = self._thinking_level or env["CMUX_THINKING_LEVEL"] + thinking_value = self._thinking_level or env["MUX_THINKING_LEVEL"] normalized_thinking = thinking_value.strip().lower() if normalized_thinking not in {"off", "low", "medium", "high"}: - raise ValueError( - "CMUX_THINKING_LEVEL must be one of off, low, medium, high" - ) - env["CMUX_THINKING_LEVEL"] = normalized_thinking + raise ValueError("MUX_THINKING_LEVEL must be one of off, low, medium, high") + env["MUX_THINKING_LEVEL"] = normalized_thinking - mode_value = self._mode or env["CMUX_MODE"] + mode_value = self._mode or env["MUX_MODE"] normalized_mode = mode_value.strip().lower() if normalized_mode in {"exec", "execute"}: - env["CMUX_MODE"] = "exec" + env["MUX_MODE"] = "exec" elif normalized_mode == "plan": - env["CMUX_MODE"] = "plan" + env["MUX_MODE"] = "plan" else: - raise ValueError("CMUX_MODE must be one of plan, exec, or execute") + raise ValueError("MUX_MODE must be one of plan, exec, or execute") # These env vars are all set with defaults above, no need to validate for key in ( - "CMUX_CONFIG_ROOT", - "CMUX_APP_ROOT", - "CMUX_WORKSPACE_ID", - "CMUX_PROJECT_CANDIDATES", + "MUX_CONFIG_ROOT", + "MUX_APP_ROOT", + "MUX_WORKSPACE_ID", + "MUX_PROJECT_CANDIDATES", ): env[key] = env[key].strip() - if timeout_value := env.get("CMUX_TIMEOUT_MS"): + if timeout_value := env.get("MUX_TIMEOUT_MS"): if not timeout_value.strip().isdigit(): - raise ValueError("CMUX_TIMEOUT_MS must be an integer") + raise ValueError("MUX_TIMEOUT_MS must be an integer") - if project_path := env.get("CMUX_PROJECT_PATH"): + if project_path := env.get("MUX_PROJECT_PATH"): if not project_path.strip(): - raise ValueError("CMUX_PROJECT_PATH must be non-empty when provided") + raise ValueError("MUX_PROJECT_PATH must be non-empty when provided") return env @property def _install_agent_script_path(self) -> Path: - return self._get_templated_script_path("cmux_setup.sh.j2") + return self._get_templated_script_path("mux_setup.sh.j2") def perform_task( self, diff --git a/benchmarks/terminal_bench/mux_agent_test.py b/benchmarks/terminal_bench/mux_agent_test.py index c2040e5af6..973943f8b5 100644 --- a/benchmarks/terminal_bench/mux_agent_test.py +++ b/benchmarks/terminal_bench/mux_agent_test.py @@ -8,20 +8,20 @@ @pytest.fixture(autouse=True) -def _clear_cmux_env(monkeypatch: pytest.MonkeyPatch) -> None: +def _clear_mux_env(monkeypatch: pytest.MonkeyPatch) -> None: keys = [ - "CMUX_AGENT_GIT_URL", - "CMUX_BUN_INSTALL_URL", - "CMUX_PROJECT_PATH", - "CMUX_PROJECT_CANDIDATES", - "CMUX_TRUNK", - "CMUX_MODEL", - "CMUX_TIMEOUT_MS", - "CMUX_THINKING_LEVEL", - "CMUX_CONFIG_ROOT", - "CMUX_APP_ROOT", - "CMUX_WORKSPACE_ID", - "CMUX_MODE", + "MUX_AGENT_GIT_URL", + "MUX_BUN_INSTALL_URL", + "MUX_PROJECT_PATH", + "MUX_PROJECT_CANDIDATES", + "MUX_TRUNK", + "MUX_MODEL", + "MUX_TIMEOUT_MS", + "MUX_THINKING_LEVEL", + "MUX_CONFIG_ROOT", + "MUX_APP_ROOT", + "MUX_WORKSPACE_ID", + "MUX_MODE", ] for key in keys: monkeypatch.delenv(key, raising=False) @@ -32,20 +32,20 @@ def _repo_root() -> Path: def test_env_defaults_are_normalized(monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setenv("CMUX_AGENT_REPO_ROOT", str(_repo_root())) + monkeypatch.setenv("MUX_AGENT_REPO_ROOT", str(_repo_root())) agent = MuxAgent(model_name="anthropic/claude-sonnet-4-5") env = agent._env - assert env["CMUX_MODEL"] == "anthropic:claude-sonnet-4-5" - assert env["CMUX_THINKING_LEVEL"] == "high" - assert env["CMUX_MODE"] == "exec" - assert env["CMUX_PROJECT_CANDIDATES"] == agent._DEFAULT_PROJECT_CANDIDATES + assert env["MUX_MODEL"] == "anthropic:claude-sonnet-4-5" + assert env["MUX_THINKING_LEVEL"] == "high" + assert env["MUX_MODE"] == "exec" + assert env["MUX_PROJECT_CANDIDATES"] == agent._DEFAULT_PROJECT_CANDIDATES def test_timeout_must_be_numeric(monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setenv("CMUX_AGENT_REPO_ROOT", str(_repo_root())) - monkeypatch.setenv("CMUX_TIMEOUT_MS", "not-a-number") + monkeypatch.setenv("MUX_AGENT_REPO_ROOT", str(_repo_root())) + monkeypatch.setenv("MUX_TIMEOUT_MS", "not-a-number") agent = MuxAgent() with pytest.raises(ValueError): diff --git a/benchmarks/terminal_bench/mux_payload.py b/benchmarks/terminal_bench/mux_payload.py index c98093c6f6..74ffc8c073 100644 --- a/benchmarks/terminal_bench/mux_payload.py +++ b/benchmarks/terminal_bench/mux_payload.py @@ -10,9 +10,9 @@ def build_app_archive(repo_root: Path, include_paths: Iterable[str]) -> bytes: - """Pack the cmux workspace into a gzipped tarball.""" + """Pack the mux workspace into a gzipped tarball.""" if not repo_root.exists(): - raise FileNotFoundError(f"cmux repo root {repo_root} not found") + raise FileNotFoundError(f"mux repo root {repo_root} not found") buffer = io.BytesIO() with tarfile.open(fileobj=buffer, mode="w:gz") as archive: @@ -30,7 +30,7 @@ def stage_payload( archive_name: str, runner_path: Path, ) -> None: - """Copy the cmux bundle and runner into the task container.""" + """Copy the mux bundle and runner into the task container.""" with tempfile.NamedTemporaryFile(suffix=".tar.gz", delete=False) as temp_file: temp_file.write(archive_bytes) temp_path = Path(temp_file.name) diff --git a/benchmarks/terminal_bench/mux_setup.sh.j2 b/benchmarks/terminal_bench/mux_setup.sh.j2 index 61ed08266c..6230f48ebe 100644 --- a/benchmarks/terminal_bench/mux_setup.sh.j2 +++ b/benchmarks/terminal_bench/mux_setup.sh.j2 @@ -30,30 +30,30 @@ export PATH="${BUN_INSTALL}/bin:${PATH}" if ! command -v bun >/dev/null 2>&1; then log "installing bun" - curl -fsSL "${CMUX_BUN_INSTALL_URL:-https://bun.sh/install}" | bash + curl -fsSL "${MUX_BUN_INSTALL_URL:-https://bun.sh/install}" | bash fi -CMUX_APP_ROOT="${CMUX_APP_ROOT:-/opt/mux-app}" -CMUX_CONFIG_ROOT="${CMUX_CONFIG_ROOT:-/root/.mux}" -CMUX_AGENT_VERSION="{{ version if version is not none else '' }}" +MUX_APP_ROOT="${MUX_APP_ROOT:-/opt/mux-app}" +MUX_CONFIG_ROOT="${MUX_CONFIG_ROOT:-/root/.mux}" +MUX_AGENT_VERSION="{{ version if version is not none else '' }}" -rm -rf "${CMUX_APP_ROOT}" -if [[ -n "${CMUX_AGENT_VERSION}" ]]; then - : "${CMUX_AGENT_GIT_URL:?CMUX_AGENT_GIT_URL required when version is set}" - log "cloning mux from ${CMUX_AGENT_GIT_URL} @ ${CMUX_AGENT_VERSION}" - git clone --depth 1 --branch "${CMUX_AGENT_VERSION}" "${CMUX_AGENT_GIT_URL}" "${CMUX_APP_ROOT}" +rm -rf "${MUX_APP_ROOT}" +if [[ -n "${MUX_AGENT_VERSION}" ]]; then + : "${MUX_AGENT_GIT_URL:?MUX_AGENT_GIT_URL required when version is set}" + log "cloning mux from ${MUX_AGENT_GIT_URL} @ ${MUX_AGENT_VERSION}" + git clone --depth 1 --branch "${MUX_AGENT_VERSION}" "${MUX_AGENT_GIT_URL}" "${MUX_APP_ROOT}" else log "extracting mux archive" - mkdir -p "${CMUX_APP_ROOT}" - tar -xzf "/installed-agent/mux-app.tar.gz" -C "${CMUX_APP_ROOT}" + mkdir -p "${MUX_APP_ROOT}" + tar -xzf "/installed-agent/mux-app.tar.gz" -C "${MUX_APP_ROOT}" fi -cd "${CMUX_APP_ROOT}" +cd "${MUX_APP_ROOT}" log "installing mux dependencies via bun" bun install --frozen-lockfile -mkdir -p "${CMUX_CONFIG_ROOT}" +mkdir -p "${MUX_CONFIG_ROOT}" chmod +x /installed-agent/mux-run.sh diff --git a/docs/benchmarking.md b/docs/benchmarking.md index f1ab92df21..4afbf2f064 100644 --- a/docs/benchmarking.md +++ b/docs/benchmarking.md @@ -10,18 +10,18 @@ mux ships with a headless adapter for [Terminal-Bench](https://www.tbench.ai/). Optional environment overrides: -| Variable | Purpose | Default | -| ---------------------- | --------------------------------------------------------- | -------------------------------------- | -| `CMUX_AGENT_REPO_ROOT` | Path copied into each task container | repo root inferred from the agent file | -| `CMUX_TRUNK` | Branch checked out when preparing the project | `main` | -| `CMUX_WORKSPACE_ID` | Workspace identifier used inside mux | `mux-bench` | -| `CMUX_MODEL` | Preferred model (supports `provider/model` syntax) | `anthropic/claude-sonnet-4-5` | -| `CMUX_THINKING_LEVEL` | Optional reasoning level (`off`, `low`, `medium`, `high`) | `high` | -| `CMUX_MODE` | Starting mode (`plan` or `exec`) | `exec` | -| `CMUX_TIMEOUT_MS` | Optional stream timeout in milliseconds | no timeout | -| `CMUX_CONFIG_ROOT` | Location for mux session data inside the container | `/root/.mux` | -| `CMUX_APP_ROOT` | Path where the mux sources are staged | `/opt/mux-app` | -| `CMUX_PROJECT_PATH` | Explicit project directory inside the task container | auto-detected from common paths | +| Variable | Purpose | Default | +| --------------------- | --------------------------------------------------------- | -------------------------------------- | +| `MUX_AGENT_REPO_ROOT` | Path copied into each task container | repo root inferred from the agent file | +| `MUX_TRUNK` | Branch checked out when preparing the project | `main` | +| `MUX_WORKSPACE_ID` | Workspace identifier used inside mux | `mux-bench` | +| `MUX_MODEL` | Preferred model (supports `provider/model` syntax) | `anthropic/claude-sonnet-4-5` | +| `MUX_THINKING_LEVEL` | Optional reasoning level (`off`, `low`, `medium`, `high`) | `high` | +| `MUX_MODE` | Starting mode (`plan` or `exec`) | `exec` | +| `MUX_TIMEOUT_MS` | Optional stream timeout in milliseconds | no timeout | +| `MUX_CONFIG_ROOT` | Location for mux session data inside the container | `/root/.mux` | +| `MUX_APP_ROOT` | Path where the mux sources are staged | `/opt/mux-app` | +| `MUX_PROJECT_PATH` | Explicit project directory inside the task container | auto-detected from common paths | ## Running Terminal-Bench @@ -65,12 +65,12 @@ The adapter lives in `benchmarks/terminal_bench/mux_agent.py`. For each task it: 1. Copies the mux repository (package manifests + `src/`) into `/tmp/mux-app` inside the container. 2. Ensures Bun exists, then runs `bun install --frozen-lockfile`. -3. Launches `src/debug/agentSessionCli.ts` to prepare workspace metadata and stream the instruction, storing state under `CMUX_CONFIG_ROOT` (default `/root/.mux`). +3. Launches `src/debug/agentSessionCli.ts` to prepare workspace metadata and stream the instruction, storing state under `MUX_CONFIG_ROOT` (default `/root/.mux`). -`CMUX_MODEL` accepts either the mux colon form (`anthropic:claude-sonnet-4-5`) or the Terminal-Bench slash form (`anthropic/claude-sonnet-4-5`); the adapter normalises whichever you provide. +`MUX_MODEL` accepts either the mux colon form (`anthropic:claude-sonnet-4-5`) or the Terminal-Bench slash form (`anthropic/claude-sonnet-4-5`); the adapter normalises whichever you provide. ## Troubleshooting - **`command not found: bun`** – ensure the container can reach Bun’s install script, or pre-install Bun in your base image. The adapter aborts if the install step fails. -- **Workspace creation errors** – set `CMUX_PROJECT_PATH` to the project directory inside the task container if auto-discovery misses it. -- **Streaming timeouts** – pass `--n-tasks 1` while iterating on fixes, or set `CMUX_TIMEOUT_MS=180000` to reinstate a timeout if needed. +- **Workspace creation errors** – set `MUX_PROJECT_PATH` to the project directory inside the task container if auto-discovery misses it. +- **Streaming timeouts** – pass `--n-tasks 1` while iterating on fixes, or set `MUX_TIMEOUT_MS=180000` to reinstate a timeout if needed. diff --git a/docs/theme/custom.css b/docs/theme/custom.css index 8c48e22b9f..a920becd83 100644 --- a/docs/theme/custom.css +++ b/docs/theme/custom.css @@ -1,4 +1,4 @@ -/* cmux Documentation Theme — cohesive with the desktop app +/* mux Documentation Theme — cohesive with the desktop app --------------------------------------------------------- Goals - Honor the app's color tokens and typography @@ -550,7 +550,7 @@ details[open] > summary::before { -/* Code block wrapper with line numbers and copy button (from cmux app) */ +/* Code block wrapper with line numbers and copy button (from mux app) */ .code-block-wrapper { position: relative; margin: 0.75em 0; diff --git a/public/service-worker.js b/public/service-worker.js index 961d9f0262..5bc7122d68 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,5 +1,5 @@ -// cmux Service Worker for PWA support -const CACHE_NAME = "cmux-v1"; +// mux Service Worker for PWA support +const CACHE_NAME = "mux-v1"; const urlsToCache = ["/", "/index.html"]; // Install event - cache core assets diff --git a/scripts/check_pr_reviews.sh b/scripts/check_pr_reviews.sh index 4dcc7c4cc6..fd5fe9dfbb 100755 --- a/scripts/check_pr_reviews.sh +++ b/scripts/check_pr_reviews.sh @@ -15,7 +15,7 @@ PR_NUMBER="$1" # Query for unresolved review threads UNRESOLVED=$(gh api graphql -f query=" { - repository(owner: \"coder\", name: \"cmux\") { + repository(owner: \"coder\", name: \"mux\") { pullRequest(number: $PR_NUMBER) { reviewThreads(first: 100) { nodes { @@ -42,7 +42,7 @@ if [ -n "$UNRESOLVED" ]; then echo "To resolve a comment thread, use:" echo "$UNRESOLVED" | jq -r '" ./scripts/resolve_pr_comment.sh \(.thread_id)"' echo "" - echo "View PR: https://github.com/coder/cmux/pull/$PR_NUMBER" + echo "View PR: https://github.com/coder/mux/pull/$PR_NUMBER" exit 1 fi diff --git a/scripts/extract_pr_logs.sh b/scripts/extract_pr_logs.sh index 3d9cfe49db..3ea5efbf2c 100755 --- a/scripts/extract_pr_logs.sh +++ b/scripts/extract_pr_logs.sh @@ -132,7 +132,7 @@ for JOB_ID in $JOB_IDS; do while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do # Use gh api to fetch logs (works for individual completed jobs even if run is in progress) - if gh api "/repos/coder/cmux/actions/jobs/$JOB_ID/logs" 2>/dev/null; then + if gh api "/repos/coder/mux/actions/jobs/$JOB_ID/logs" 2>/dev/null; then break else RETRY_COUNT=$((RETRY_COUNT + 1)) diff --git a/src/browser/App.stories.tsx b/src/browser/App.stories.tsx index b03c5f51c6..d6e661172b 100644 --- a/src/browser/App.stories.tsx +++ b/src/browser/App.stories.tsx @@ -170,14 +170,14 @@ export const SingleProject: Story = { "/home/user/projects/my-app", { workspaces: [ - { path: "/home/user/.cmux/src/my-app/main", id: "a1b2c3d4e5", name: "main" }, + { path: "/home/user/.mux/src/my-app/main", id: "a1b2c3d4e5", name: "main" }, { - path: "/home/user/.cmux/src/my-app/feature-auth", + path: "/home/user/.mux/src/my-app/feature-auth", id: "f6g7h8i9j0", name: "feature/auth", }, { - path: "/home/user/.cmux/src/my-app/bugfix", + path: "/home/user/.mux/src/my-app/bugfix", id: "k1l2m3n4o5", name: "bugfix/memory-leak", }, @@ -192,7 +192,7 @@ export const SingleProject: Story = { name: "main", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/main", + namedWorkspacePath: "/home/user/.mux/src/my-app/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, { @@ -200,11 +200,11 @@ export const SingleProject: Story = { name: "feature/auth", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/feature-auth", + namedWorkspacePath: "/home/user/.mux/src/my-app/feature-auth", runtimeConfig: { type: "ssh", host: "dev-server.example.com", - srcBaseDir: "/home/user/.cmux/src", + srcBaseDir: "/home/user/.mux/src", }, }, { @@ -212,7 +212,7 @@ export const SingleProject: Story = { name: "bugfix/memory-leak", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/bugfix", + namedWorkspacePath: "/home/user/.mux/src/my-app/bugfix", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ]; @@ -229,9 +229,9 @@ export const MultipleProjects: Story = { "/home/user/projects/frontend", { workspaces: [ - { path: "/home/user/.cmux/src/frontend/main", id: "1a2b3c4d5e", name: "main" }, + { path: "/home/user/.mux/src/frontend/main", id: "1a2b3c4d5e", name: "main" }, { - path: "/home/user/.cmux/src/frontend/redesign", + path: "/home/user/.mux/src/frontend/redesign", id: "2b3c4d5e6f", name: "redesign", }, @@ -242,10 +242,10 @@ export const MultipleProjects: Story = { "/home/user/projects/backend", { workspaces: [ - { path: "/home/user/.cmux/src/backend/main", id: "3c4d5e6f7a", name: "main" }, - { path: "/home/user/.cmux/src/backend/api-v2", id: "4d5e6f7a8b", name: "api-v2" }, + { path: "/home/user/.mux/src/backend/main", id: "3c4d5e6f7a", name: "main" }, + { path: "/home/user/.mux/src/backend/api-v2", id: "4d5e6f7a8b", name: "api-v2" }, { - path: "/home/user/.cmux/src/backend/db-migration", + path: "/home/user/.mux/src/backend/db-migration", id: "5e6f7a8b9c", name: "db-migration", }, @@ -255,9 +255,7 @@ export const MultipleProjects: Story = { [ "/home/user/projects/mobile", { - workspaces: [ - { path: "/home/user/.cmux/src/mobile/main", id: "6f7a8b9c0d", name: "main" }, - ], + workspaces: [{ path: "/home/user/.mux/src/mobile/main", id: "6f7a8b9c0d", name: "main" }], }, ], ]); @@ -268,7 +266,7 @@ export const MultipleProjects: Story = { name: "main", projectPath: "/home/user/projects/frontend", projectName: "frontend", - namedWorkspacePath: "/home/user/.cmux/src/frontend/main", + namedWorkspacePath: "/home/user/.mux/src/frontend/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, { @@ -276,7 +274,7 @@ export const MultipleProjects: Story = { name: "redesign", projectPath: "/home/user/projects/frontend", projectName: "frontend", - namedWorkspacePath: "/home/user/.cmux/src/frontend/redesign", + namedWorkspacePath: "/home/user/.mux/src/frontend/redesign", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, { @@ -284,7 +282,7 @@ export const MultipleProjects: Story = { name: "main", projectPath: "/home/user/projects/backend", projectName: "backend", - namedWorkspacePath: "/home/user/.cmux/src/backend/main", + namedWorkspacePath: "/home/user/.mux/src/backend/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, { @@ -292,11 +290,11 @@ export const MultipleProjects: Story = { name: "api-v2", projectPath: "/home/user/projects/backend", projectName: "backend", - namedWorkspacePath: "/home/user/.cmux/src/backend/api-v2", + namedWorkspacePath: "/home/user/.mux/src/backend/api-v2", runtimeConfig: { type: "ssh", host: "prod-server.example.com", - srcBaseDir: "/home/user/.cmux/src", + srcBaseDir: "/home/user/.mux/src", }, }, { @@ -304,11 +302,11 @@ export const MultipleProjects: Story = { name: "db-migration", projectPath: "/home/user/projects/backend", projectName: "backend", - namedWorkspacePath: "/home/user/.cmux/src/backend/db-migration", + namedWorkspacePath: "/home/user/.mux/src/backend/db-migration", runtimeConfig: { type: "ssh", host: "staging.example.com", - srcBaseDir: "/home/user/.cmux/src", + srcBaseDir: "/home/user/.mux/src", }, }, { @@ -316,7 +314,7 @@ export const MultipleProjects: Story = { name: "main", projectPath: "/home/user/projects/mobile", projectName: "mobile", - namedWorkspacePath: "/home/user/.cmux/src/mobile/main", + namedWorkspacePath: "/home/user/.mux/src/mobile/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ]; @@ -347,7 +345,7 @@ export const ManyWorkspaces: Story = { "/home/user/projects/big-app", { workspaces: workspaceNames.map((name) => ({ - path: `/home/user/.cmux/src/big-app/${name}`, + path: `/home/user/.mux/src/big-app/${name}`, id: `big-app-${name}`, name, })), @@ -360,7 +358,7 @@ export const ManyWorkspaces: Story = { name, projectPath: "/home/user/projects/big-app", projectName: "big-app", - namedWorkspacePath: `/home/user/.cmux/src/big-app/${name}`, + namedWorkspacePath: `/home/user/.mux/src/big-app/${name}`, runtimeConfig: DEFAULT_RUNTIME_CONFIG, })); @@ -415,22 +413,22 @@ export const ActiveWorkspaceWithChat: Story = { "/home/user/projects/my-app", { workspaces: [ - { path: "/home/user/.cmux/src/my-app/feature", id: workspaceId, name: "feature/auth" }, + { path: "/home/user/.mux/src/my-app/feature", id: workspaceId, name: "feature/auth" }, { - path: "/home/user/.cmux/src/my-app/streaming", + path: "/home/user/.mux/src/my-app/streaming", id: streamingWorkspaceId, name: "feature/streaming", }, - { path: "/home/user/.cmux/src/my-app/main", id: "ws-clean", name: "main" }, - { path: "/home/user/.cmux/src/my-app/ahead", id: "ws-ahead", name: "feature/new-ui" }, - { path: "/home/user/.cmux/src/my-app/behind", id: "ws-behind", name: "feature/api" }, - { path: "/home/user/.cmux/src/my-app/dirty", id: "ws-dirty", name: "bugfix/crash" }, + { path: "/home/user/.mux/src/my-app/main", id: "ws-clean", name: "main" }, + { path: "/home/user/.mux/src/my-app/ahead", id: "ws-ahead", name: "feature/new-ui" }, + { path: "/home/user/.mux/src/my-app/behind", id: "ws-behind", name: "feature/api" }, + { path: "/home/user/.mux/src/my-app/dirty", id: "ws-dirty", name: "bugfix/crash" }, { - path: "/home/user/.cmux/src/my-app/diverged", + path: "/home/user/.mux/src/my-app/diverged", id: "ws-diverged", name: "refactor/db", }, - { path: "/home/user/.cmux/src/my-app/ssh-remote", id: "ws-ssh", name: "deploy/prod" }, + { path: "/home/user/.mux/src/my-app/ssh-remote", id: "ws-ssh", name: "deploy/prod" }, ], }, ], @@ -449,7 +447,7 @@ export const ActiveWorkspaceWithChat: Story = { name: "feature/auth", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/feature", + namedWorkspacePath: "/home/user/.mux/src/my-app/feature", runtimeConfig: DEFAULT_RUNTIME_CONFIG, createdAt: new Date(NOW - 7200000).toISOString(), // 2 hours ago }, @@ -459,7 +457,7 @@ export const ActiveWorkspaceWithChat: Story = { name: "feature/streaming", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/streaming", + namedWorkspacePath: "/home/user/.mux/src/my-app/streaming", runtimeConfig: DEFAULT_RUNTIME_CONFIG, createdAt: new Date(NOW - 3600000).toISOString(), // 1 hour ago }, @@ -469,7 +467,7 @@ export const ActiveWorkspaceWithChat: Story = { name: "main", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/main", + namedWorkspacePath: "/home/user/.mux/src/my-app/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, createdAt: new Date(NOW - 10800000).toISOString(), // 3 hours ago }, @@ -479,7 +477,7 @@ export const ActiveWorkspaceWithChat: Story = { name: "feature/new-ui", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/ahead", + namedWorkspacePath: "/home/user/.mux/src/my-app/ahead", runtimeConfig: DEFAULT_RUNTIME_CONFIG, createdAt: new Date(NOW - 14400000).toISOString(), // 4 hours ago }, @@ -489,7 +487,7 @@ export const ActiveWorkspaceWithChat: Story = { name: "feature/api", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/behind", + namedWorkspacePath: "/home/user/.mux/src/my-app/behind", runtimeConfig: DEFAULT_RUNTIME_CONFIG, createdAt: new Date(NOW - 18000000).toISOString(), // 5 hours ago }, @@ -499,7 +497,7 @@ export const ActiveWorkspaceWithChat: Story = { name: "bugfix/crash", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/dirty", + namedWorkspacePath: "/home/user/.mux/src/my-app/dirty", runtimeConfig: DEFAULT_RUNTIME_CONFIG, createdAt: new Date(NOW - 21600000).toISOString(), // 6 hours ago }, @@ -509,7 +507,7 @@ export const ActiveWorkspaceWithChat: Story = { name: "refactor/db", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/diverged", + namedWorkspacePath: "/home/user/.mux/src/my-app/diverged", runtimeConfig: DEFAULT_RUNTIME_CONFIG, createdAt: new Date(NOW - 25200000).toISOString(), // 7 hours ago }, @@ -519,11 +517,11 @@ export const ActiveWorkspaceWithChat: Story = { name: "deploy/prod", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/ssh-remote", + namedWorkspacePath: "/home/user/.mux/src/my-app/ssh-remote", runtimeConfig: { type: "ssh", host: "prod.example.com", - srcBaseDir: "/home/deploy/.cmux/src", + srcBaseDir: "/home/deploy/.mux/src", }, createdAt: new Date(NOW - 28800000).toISOString(), // 8 hours ago }, @@ -1205,7 +1203,7 @@ main workspaceId: workspaceId, projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/feature", + namedWorkspacePath: "/home/user/.mux/src/my-app/feature", }) ); @@ -1237,7 +1235,7 @@ export const MarkdownTables: Story = { name: "feature", projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/feature", + namedWorkspacePath: "/home/user/.mux/src/my-app/feature", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ]; @@ -1248,7 +1246,7 @@ export const MarkdownTables: Story = { "/home/user/projects/my-app", { workspaces: [ - { path: "/home/user/.cmux/src/my-app/feature", id: workspaceId, name: "feature" }, + { path: "/home/user/.mux/src/my-app/feature", id: workspaceId, name: "feature" }, ], }, ], @@ -1401,7 +1399,7 @@ These tables should render cleanly without any disruptive copy or download actio workspaceId: workspaceId, projectPath: "/home/user/projects/my-app", projectName: "my-app", - namedWorkspacePath: "/home/user/.cmux/src/my-app/feature", + namedWorkspacePath: "/home/user/.mux/src/my-app/feature", }) ); diff --git a/src/browser/App.tsx b/src/browser/App.tsx index 6afb546e1a..6860fa693f 100644 --- a/src/browser/App.tsx +++ b/src/browser/App.tsx @@ -131,7 +131,7 @@ function AppInner() { // Update window title with workspace name const metadata = workspaceMetadata.get(selectedWorkspace.workspaceId); const workspaceName = metadata?.name ?? selectedWorkspace.workspaceId; - const title = `${workspaceName} - ${selectedWorkspace.projectName} - cmux`; + const title = `${workspaceName} - ${selectedWorkspace.projectName} - mux`; void window.api.window.setTitle(title); } else { // Clear hash when no workspace selected diff --git a/src/browser/api.ts b/src/browser/api.ts index ff8f0a66b0..449e57e238 100644 --- a/src/browser/api.ts +++ b/src/browser/api.ts @@ -1,5 +1,5 @@ /** - * Browser API client. Used when running cmux in server mode. + * Browser API client. Used when running mux in server mode. */ import { IPC_CHANNELS, getChatChannel } from "@/common/constants/ipc-constants"; import type { IPCApi } from "@/common/types/ipc"; diff --git a/src/browser/components/AIView.tsx b/src/browser/components/AIView.tsx index c1d7030fd3..2dfa3a3efc 100644 --- a/src/browser/components/AIView.tsx +++ b/src/browser/components/AIView.tsx @@ -383,7 +383,7 @@ const AIViewInner: React.FC = ({

💡 Tip: Add a{" "} - .cmux/init + .mux/init {" "} hook to your project to run setup commands
@@ -399,6 +399,7 @@ const AIViewInner: React.FC = ({ msg.type !== "workspace-init" && msg.historyId === editCutoffHistoryId; + return (

Runtime:
- • Local: git worktree in ~/.cmux/src -
• SSH: remote clone in ~/cmux on SSH host + • Local: git worktree in ~/.mux/src +
• SSH: remote clone in ~/mux on SSH host
diff --git a/src/browser/components/ChatInput/index.tsx b/src/browser/components/ChatInput/index.tsx index 9063281622..2dd851af94 100644 --- a/src/browser/components/ChatInput/index.tsx +++ b/src/browser/components/ChatInput/index.tsx @@ -665,7 +665,7 @@ export const ChatInput: React.FC = (props) => { // When editing a /compact command, regenerate the actual summarization request let actualMessageText = messageText; - let cmuxMetadata: MuxFrontendMetadata | undefined; + let muxMetadata: MuxFrontendMetadata | undefined; let compactionOptions = {}; if (editingMessage && messageText.startsWith("/")) { @@ -683,7 +683,7 @@ export const ChatInput: React.FC = (props) => { sendMessageOptions, }); actualMessageText = regeneratedText; - cmuxMetadata = metadata; + muxMetadata = metadata; compactionOptions = sendOptions; } } @@ -705,7 +705,7 @@ export const ChatInput: React.FC = (props) => { ...compactionOptions, editMessageId: editingMessage?.id, imageParts: imageParts.length > 0 ? imageParts : undefined, - cmuxMetadata, + muxMetadata, } ); diff --git a/src/browser/components/CommandPalette.stories.tsx b/src/browser/components/CommandPalette.stories.tsx index ad5b22da85..b18680a329 100644 --- a/src/browser/components/CommandPalette.stories.tsx +++ b/src/browser/components/CommandPalette.stories.tsx @@ -105,7 +105,7 @@ const mockCommands: CommandAction[] = [ { id: "help.docs", title: "Open Documentation", - subtitle: "View cmux documentation", + subtitle: "View mux documentation", section: "Help", keywords: ["help", "docs", "documentation"], run: () => action("command-executed")("help.docs"), diff --git a/src/browser/components/Modal.stories.tsx b/src/browser/components/Modal.stories.tsx index cb8fce0c0f..acaf82af21 100644 --- a/src/browser/components/Modal.stories.tsx +++ b/src/browser/components/Modal.stories.tsx @@ -106,7 +106,7 @@ export const WithInfoBox: Story = { <>

- This operation will create a new workspace at ~/cmux/project/branch + This operation will create a new workspace at ~/mux/project/branch

Existing files will not be affected.

diff --git a/src/browser/components/ProjectSidebar.tsx b/src/browser/components/ProjectSidebar.tsx index 45eaf60ac5..938ff073f8 100644 --- a/src/browser/components/ProjectSidebar.tsx +++ b/src/browser/components/ProjectSidebar.tsx @@ -347,7 +347,7 @@ const ProjectSidebarInner: React.FC = ({ }; // UI preference: project order persists in localStorage - const [projectOrder, setProjectOrder] = usePersistedState("cmux:projectOrder", []); + const [projectOrder, setProjectOrder] = usePersistedState("mux:projectOrder", []); // Build a stable signature of the project keys so effects don't fire on Map identity churn const projectPathsSignature = React.useMemo(() => { diff --git a/src/browser/components/SecretsModal.tsx b/src/browser/components/SecretsModal.tsx index 28522b56be..d7b5e3a13d 100644 --- a/src/browser/components/SecretsModal.tsx +++ b/src/browser/components/SecretsModal.tsx @@ -132,7 +132,7 @@ const SecretsModal: React.FC = ({ >

- Secrets are stored in ~/.cmux/secrets.json (kept away from source code) but + Secrets are stored in ~/.mux/secrets.json (kept away from source code) but namespaced per project.

Secrets are injected as environment variables to compute commands (e.g. Bash)

diff --git a/src/browser/components/TitleBar.tsx b/src/browser/components/TitleBar.tsx index 12a83d5e19..42a68798b4 100644 --- a/src/browser/components/TitleBar.tsx +++ b/src/browser/components/TitleBar.tsx @@ -179,7 +179,7 @@ export function TitleBar() { // Always add releases link as defense-in-depth lines.push( - + View all releases ); @@ -248,7 +248,7 @@ export function TitleBar() { )}
- cmux {gitDescribe ?? "(dev)"} + mux {gitDescribe ?? "(dev)"}
diff --git a/src/browser/hooks/useAutoCompactContinue.ts b/src/browser/hooks/useAutoCompactContinue.ts index dbb881ba0f..d9de923a5e 100644 --- a/src/browser/hooks/useAutoCompactContinue.ts +++ b/src/browser/hooks/useAutoCompactContinue.ts @@ -42,11 +42,11 @@ export function useAutoCompactContinue() { for (const [workspaceId, state] of newStates) { // Detect if workspace is in "single compacted message" state // Skip workspace-init messages since they're UI-only metadata - const cmuxMessages = state.messages.filter((m) => m.type !== "workspace-init"); + const muxMessages = state.messages.filter((m) => m.type !== "workspace-init"); const isSingleCompacted = - cmuxMessages.length === 1 && - cmuxMessages[0]?.type === "assistant" && - cmuxMessages[0].isCompacted === true; + muxMessages.length === 1 && + muxMessages[0]?.type === "assistant" && + muxMessages[0].isCompacted === true; if (!isSingleCompacted) { // Workspace no longer in compacted state - no action needed @@ -57,17 +57,17 @@ export function useAutoCompactContinue() { // After compaction, history is replaced with a single summary message // The summary message has compaction-result metadata with the continueMessage - const summaryMessage = state.cmuxMessages[0]; // Single compacted message - const cmuxMeta = summaryMessage?.metadata?.cmuxMetadata; + const summaryMessage = state.muxMessages[0]; // Single compacted message + const muxMeta = summaryMessage?.metadata?.muxMetadata; const continueMessage = - cmuxMeta?.type === "compaction-result" ? cmuxMeta.continueMessage : undefined; + muxMeta?.type === "compaction-result" ? muxMeta.continueMessage : undefined; if (!continueMessage) continue; // Prefer compaction-request ID for idempotency; fall back to summary message ID const idForGuard = - cmuxMeta?.type === "compaction-result" && cmuxMeta.requestId - ? `req:${cmuxMeta.requestId}` + muxMeta?.type === "compaction-result" && muxMeta.requestId + ? `req:${muxMeta.requestId}` : `msg:${summaryMessage.id}`; // Have we already processed this specific compaction result? diff --git a/src/browser/stores/GitStatusStore.test.ts b/src/browser/stores/GitStatusStore.test.ts index 81656182d7..e7695c610a 100644 --- a/src/browser/stores/GitStatusStore.test.ts +++ b/src/browser/stores/GitStatusStore.test.ts @@ -74,7 +74,7 @@ describe("GitStatusStore", () => { name: "main", projectName: "test-project", projectPath: "/home/user/test-project", - namedWorkspacePath: "/home/user/.cmux/src/test-project/main", + namedWorkspacePath: "/home/user/.mux/src/test-project/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ], @@ -96,7 +96,7 @@ describe("GitStatusStore", () => { name: "main", projectName: "test-project", projectPath: "/home/user/test-project", - namedWorkspacePath: "/home/user/.cmux/src/test-project/main", + namedWorkspacePath: "/home/user/.mux/src/test-project/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ], @@ -107,7 +107,7 @@ describe("GitStatusStore", () => { name: "feature", projectName: "test-project", projectPath: "/home/user/test-project", - namedWorkspacePath: "/home/user/.cmux/src/test-project/feature", + namedWorkspacePath: "/home/user/.mux/src/test-project/feature", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ], @@ -130,7 +130,7 @@ describe("GitStatusStore", () => { name: "main", projectName: "test-project", projectPath: "/home/user/test-project", - namedWorkspacePath: "/home/user/.cmux/src/test-project/main", + namedWorkspacePath: "/home/user/.mux/src/test-project/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ], @@ -155,7 +155,7 @@ describe("GitStatusStore", () => { name: "main", projectName: "test-project", projectPath: "/home/user/test-project", - namedWorkspacePath: "/home/user/.cmux/src/test-project/main", + namedWorkspacePath: "/home/user/.mux/src/test-project/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ], @@ -181,7 +181,7 @@ describe("GitStatusStore", () => { name: "main", projectName: "test-project", projectPath: "/home/user/test-project", - namedWorkspacePath: "/home/user/.cmux/src/test-project/main", + namedWorkspacePath: "/home/user/.mux/src/test-project/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ], @@ -211,7 +211,7 @@ describe("GitStatusStore", () => { name: "main", projectName: "test-project", projectPath: "/home/user/test-project", - namedWorkspacePath: "/home/user/.cmux/src/test-project/main", + namedWorkspacePath: "/home/user/.mux/src/test-project/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ], @@ -239,7 +239,7 @@ describe("GitStatusStore", () => { name: "main", projectName: "test-project", projectPath: "/home/user/test-project", - namedWorkspacePath: "/home/user/.cmux/src/test-project/main", + namedWorkspacePath: "/home/user/.mux/src/test-project/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ], @@ -268,7 +268,7 @@ describe("GitStatusStore", () => { name: "main", projectName: "test-project", projectPath: "/home/user/test-project", - namedWorkspacePath: "/home/user/.cmux/src/test-project/main", + namedWorkspacePath: "/home/user/.mux/src/test-project/main", runtimeConfig: DEFAULT_RUNTIME_CONFIG, }, ], diff --git a/src/browser/stores/WorkspaceStore.test.ts b/src/browser/stores/WorkspaceStore.test.ts index 1f43424577..e085810f4c 100644 --- a/src/browser/stores/WorkspaceStore.test.ts +++ b/src/browser/stores/WorkspaceStore.test.ts @@ -256,7 +256,7 @@ describe("WorkspaceStore", () => { canInterrupt: false, isCompacting: false, loading: true, // loading because not caught up - cmuxMessages: [], + muxMessages: [], currentModel: null, }); // Should have recency based on createdAt diff --git a/src/browser/stores/WorkspaceStore.ts b/src/browser/stores/WorkspaceStore.ts index e74167627c..7dfe3be2d9 100644 --- a/src/browser/stores/WorkspaceStore.ts +++ b/src/browser/stores/WorkspaceStore.ts @@ -35,7 +35,7 @@ export interface WorkspaceState { canInterrupt: boolean; isCompacting: boolean; loading: boolean; - cmuxMessages: MuxMessage[]; + muxMessages: MuxMessage[]; currentModel: string | null; recencyTimestamp: number | null; todos: TodoItem[]; @@ -308,7 +308,7 @@ export class WorkspaceStore { canInterrupt: activeStreams.length > 0, isCompacting: aggregator.isCompacting(), loading: !hasMessages && !isCaughtUp, - cmuxMessages: messages, + muxMessages: messages, currentModel: aggregator.getCurrentModel() ?? null, recencyTimestamp: aggregator.getRecencyTimestamp(), todos: aggregator.getCurrentTodos(), @@ -639,9 +639,9 @@ export class WorkspaceStore { // Extract continueMessage from compaction-request before history gets replaced const compactRequestMsg = findCompactionRequestMessage(aggregator); - const cmuxMeta = compactRequestMsg?.metadata?.cmuxMetadata; + const muxMeta = compactRequestMsg?.metadata?.muxMetadata; const continueMessage = - cmuxMeta?.type === "compaction-request" ? cmuxMeta.parsed.continueMessage : undefined; + muxMeta?.type === "compaction-request" ? muxMeta.parsed.continueMessage : undefined; const summaryMessage = createMuxMessage( `summary-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`, @@ -663,7 +663,7 @@ export class WorkspaceStore { ? (metadata.systemMessageTokens as number | undefined) : undefined, // Store continueMessage in summary so it survives history replacement - cmuxMetadata: continueMessage + muxMetadata: continueMessage ? { type: "compaction-result", continueMessage, requestId: compactRequestMsg?.id } : { type: "normal" }, } diff --git a/src/browser/utils/chatCommands.test.ts b/src/browser/utils/chatCommands.test.ts index b72d92ba97..57385f0af8 100644 --- a/src/browser/utils/chatCommands.test.ts +++ b/src/browser/utils/chatCommands.test.ts @@ -18,7 +18,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "user@host", - srcBaseDir: "~/cmux", + srcBaseDir: "~/mux", }); }); @@ -27,7 +27,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "User@Host.Example.Com", - srcBaseDir: "~/cmux", + srcBaseDir: "~/mux", }); }); @@ -36,7 +36,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "user@host", - srcBaseDir: "~/cmux", + srcBaseDir: "~/mux", }); }); @@ -51,7 +51,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "hostname", - srcBaseDir: "~/cmux", + srcBaseDir: "~/mux", }); }); @@ -61,7 +61,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "dev.example.com", - srcBaseDir: "~/cmux", + srcBaseDir: "~/mux", }); }); @@ -71,7 +71,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "root@hostname", - srcBaseDir: "~/cmux", + srcBaseDir: "~/mux", }); }); diff --git a/src/browser/utils/chatCommands.ts b/src/browser/utils/chatCommands.ts index e150f49d0f..39f63800b2 100644 --- a/src/browser/utils/chatCommands.ts +++ b/src/browser/utils/chatCommands.ts @@ -57,7 +57,7 @@ export function parseRuntimeString( return { type: RUNTIME_MODE.SSH, host: hostPart, - srcBaseDir: "~/cmux", // Default remote base directory (tilde will be resolved by backend) + srcBaseDir: "~/mux", // Default remote base directory (tilde will be resolved by backend) }; } @@ -236,7 +236,7 @@ export async function executeCompaction(options: CompactionOptions): Promise m.role === "user"); - const isCompacting = lastUserMsg?.metadata?.cmuxMetadata?.type === "compaction-request"; + const isCompacting = lastUserMsg?.metadata?.muxMetadata?.type === "compaction-request"; const context: StreamingContext = { startTime: Date.now(), @@ -755,12 +755,12 @@ export class StreamingMessageAggregator { })); // Check if this is a compaction request message - const cmuxMeta = message.metadata?.cmuxMetadata; + const muxMeta = message.metadata?.muxMetadata; const compactionRequest = - cmuxMeta?.type === "compaction-request" + muxMeta?.type === "compaction-request" ? { - rawCommand: cmuxMeta.rawCommand, - parsed: cmuxMeta.parsed, + rawCommand: muxMeta.rawCommand, + parsed: muxMeta.parsed, } : undefined; diff --git a/src/browser/utils/ui/runtimeBadge.test.ts b/src/browser/utils/ui/runtimeBadge.test.ts index f34519057b..ce8621402f 100644 --- a/src/browser/utils/ui/runtimeBadge.test.ts +++ b/src/browser/utils/ui/runtimeBadge.test.ts @@ -10,7 +10,7 @@ describe("extractSshHostname", () => { it("should return null for local runtime", () => { const config: RuntimeConfig = { type: "local", - srcBaseDir: "/home/user/.cmux/src", + srcBaseDir: "/home/user/.mux/src", }; expect(extractSshHostname(config)).toBeNull(); }); @@ -19,7 +19,7 @@ describe("extractSshHostname", () => { const config: RuntimeConfig = { type: "ssh", host: "myserver", - srcBaseDir: "/home/user/.cmux/src", + srcBaseDir: "/home/user/.mux/src", }; expect(extractSshHostname(config)).toBe("myserver"); }); @@ -28,7 +28,7 @@ describe("extractSshHostname", () => { const config: RuntimeConfig = { type: "ssh", host: "user@myserver.example.com", - srcBaseDir: "/home/user/.cmux/src", + srcBaseDir: "/home/user/.mux/src", }; expect(extractSshHostname(config)).toBe("myserver.example.com"); }); @@ -37,7 +37,7 @@ describe("extractSshHostname", () => { const config: RuntimeConfig = { type: "ssh", host: "myserver:2222", - srcBaseDir: "/home/user/.cmux/src", + srcBaseDir: "/home/user/.mux/src", }; expect(extractSshHostname(config)).toBe("myserver"); }); @@ -46,7 +46,7 @@ describe("extractSshHostname", () => { const config: RuntimeConfig = { type: "ssh", host: "user@myserver.example.com:2222", - srcBaseDir: "/home/user/.cmux/src", + srcBaseDir: "/home/user/.mux/src", }; expect(extractSshHostname(config)).toBe("myserver.example.com"); }); @@ -55,7 +55,7 @@ describe("extractSshHostname", () => { const config: RuntimeConfig = { type: "ssh", host: "my-server-alias", - srcBaseDir: "/home/user/.cmux/src", + srcBaseDir: "/home/user/.mux/src", }; expect(extractSshHostname(config)).toBe("my-server-alias"); }); diff --git a/src/cli/debug/agentSessionCli.ts b/src/cli/debug/agentSessionCli.ts index 184fb201af..09c5726c8b 100644 --- a/src/cli/debug/agentSessionCli.ts +++ b/src/cli/debug/agentSessionCli.ts @@ -194,7 +194,7 @@ async function main(): Promise { // Log model selection for terminal-bench verification if (!suppressHumanOutput) { - console.error(`[cmux-cli] Using model: ${model}`); + console.error(`[mux-cli] Using model: ${model}`); } const humanStream = process.stdout; diff --git a/src/cli/debug/git-status.ts b/src/cli/debug/git-status.ts index c9e98a38a2..caae6f4830 100644 --- a/src/cli/debug/git-status.ts +++ b/src/cli/debug/git-status.ts @@ -17,12 +17,12 @@ import { getMuxSrcDir } from "@/common/constants/paths"; function findWorkspaces(): Array<{ id: string; path: string }> { const workspaces: Array<{ id: string; path: string }> = []; - const cmuxSrcDir = getMuxSrcDir(); + const muxSrcDir = getMuxSrcDir(); try { - const projects = readdirSync(cmuxSrcDir); + const projects = readdirSync(muxSrcDir); for (const project of projects) { - const projectPath = join(cmuxSrcDir, project); + const projectPath = join(muxSrcDir, project); if (!statSync(projectPath).isDirectory()) continue; const branches = readdirSync(projectPath); @@ -122,16 +122,16 @@ function testGitStatus(workspaceId: string, workspacePath: string) { } export function gitStatusCommand(workspaceId?: string) { - const cmuxSrcDir = getMuxSrcDir(); + const muxSrcDir = getMuxSrcDir(); console.log("🔍 Git Status Debug Tool"); - console.log("Finding workspaces in:", cmuxSrcDir); + console.log("Finding workspaces in:", muxSrcDir); console.log(); const workspaces = findWorkspaces(); console.log(`Found ${workspaces.length} workspaces\n`); if (workspaces.length === 0) { - console.log("No workspaces found! Check that ~/.cmux/src/ contains workspace directories."); + console.log("No workspaces found! Check that ~/.mux/src/ contains workspace directories."); process.exit(1); } diff --git a/src/cli/debug/list-workspaces.ts b/src/cli/debug/list-workspaces.ts index 61eaebeb4a..7dfe4e7d0b 100644 --- a/src/cli/debug/list-workspaces.ts +++ b/src/cli/debug/list-workspaces.ts @@ -32,7 +32,7 @@ export function listWorkspacesCommand() { console.log("\n=== Testing findWorkspace ===\n"); // Test finding specific workspaces by ID - const testCases = ["cmux-colors", "cmux-main", "cmux-fix", "cmux-markdown"]; + const testCases = ["mux-colors", "mux-main", "mux-fix", "mux-markdown"]; for (const workspaceId of testCases) { const result = defaultConfig.findWorkspace(workspaceId); diff --git a/src/cli/server.ts b/src/cli/server.ts index 4b29866f0e..e8a0d02ea3 100644 --- a/src/cli/server.ts +++ b/src/cli/server.ts @@ -5,7 +5,7 @@ import { Config } from "@/node/config"; import { IPC_CHANNELS } from "@/common/constants/ipc-constants"; import { IpcMain } from "@/node/services/ipcMain"; -import { migrateCmuxToMux } from "@/common/constants/paths"; +import { migrateLegacyMuxHome } from "@/common/constants/paths"; import cors from "cors"; import type { BrowserWindow, IpcMain as ElectronIpcMain } from "electron"; import express from "express"; @@ -145,7 +145,7 @@ const httpIpcMain = new HttpIpcMainAdapter(app); // Initialize async services and register handlers (async () => { // Migrate from .cmux to .mux directory structure if needed - migrateCmuxToMux(); + migrateLegacyMuxHome(); // Initialize config and IPC service const config = new Config(); diff --git a/src/common/constants/events.ts b/src/common/constants/events.ts index d249cbe870..6e04f1c219 100644 --- a/src/common/constants/events.ts +++ b/src/common/constants/events.ts @@ -12,19 +12,19 @@ export const CUSTOM_EVENTS = { * Event to show a toast notification when thinking level changes * Detail: { workspaceId: string, level: ThinkingLevel } */ - THINKING_LEVEL_TOAST: "cmux:thinkingLevelToast", + THINKING_LEVEL_TOAST: "mux:thinkingLevelToast", /** * Event to insert text into the chat input * Detail: { text: string } */ - INSERT_TO_CHAT_INPUT: "cmux:insertToChatInput", + INSERT_TO_CHAT_INPUT: "mux:insertToChatInput", /** * Event to open the model selector * No detail */ - OPEN_MODEL_SELECTOR: "cmux:openModelSelector", + OPEN_MODEL_SELECTOR: "mux:openModelSelector", /** * Event to trigger resume check for a workspace @@ -37,24 +37,28 @@ export const CUSTOM_EVENTS = { * * useResumeManager handles this idempotently - safe to emit multiple times */ - RESUME_CHECK_REQUESTED: "cmux:resumeCheckRequested", + RESUME_CHECK_REQUESTED: "mux:resumeCheckRequested", /** * Event to switch to a different workspace after fork * Detail: { workspaceId: string, projectPath: string, projectName: string, workspacePath: string, branch: string } */ - WORKSPACE_FORK_SWITCH: "cmux:workspaceForkSwitch", + WORKSPACE_FORK_SWITCH: "mux:workspaceForkSwitch", /** * Event to execute a command from the command palette * Detail: { commandId: string } */ - EXECUTE_COMMAND: "cmux:executeCommand", +<<<<<<< HEAD + EXECUTE_COMMAND: "mux:executeCommand", /** * Event to enter the chat-based workspace creation experience. * Detail: { projectPath: string, startMessage?: string, model?: string, trunkBranch?: string, runtime?: string } */ - START_WORKSPACE_CREATION: "cmux:startWorkspaceCreation", + START_WORKSPACE_CREATION: "mux:startWorkspaceCreation", +======= + EXECUTE_COMMAND: "mux:executeCommand", +>>>>>>> a3cb9358 (🤖 chore: rename cmux refs to mux) } as const; /** diff --git a/src/common/constants/paths.ts b/src/common/constants/paths.ts index 045a658185..f4ca660b57 100644 --- a/src/common/constants/paths.ts +++ b/src/common/constants/paths.ts @@ -2,17 +2,20 @@ import { existsSync, renameSync, symlinkSync } from "fs"; import { homedir } from "os"; import { join } from "path"; +const LEGACY_MUX_DIR_NAME = ".cmux"; +const MUX_DIR_NAME = ".mux"; + /** - * Migrate from .cmux to .mux directory structure. - * Called on startup to ensure backward compatibility. + * Migrate from the legacy ~/.cmux directory into ~/.mux for rebranded installs. + * Called on startup to preserve data created by earlier releases. * * If .mux exists, nothing happens (already migrated). * If .cmux exists but .mux doesn't, moves .cmux → .mux and creates symlink. * This ensures old scripts/tools referencing ~/.cmux continue working. */ -export function migrateCmuxToMux(): void { - const oldPath = join(homedir(), ".cmux"); - const newPath = join(homedir(), ".mux"); +export function migrateLegacyMuxHome(): void { + const oldPath = join(homedir(), LEGACY_MUX_DIR_NAME); + const newPath = join(homedir(), MUX_DIR_NAME); // If .mux exists, we're done (already migrated or fresh install) if (existsSync(newPath)) { @@ -45,7 +48,7 @@ export function getMuxHome(): string { return process.env.MUX_ROOT; } - const baseName = ".mux"; + const baseName = MUX_DIR_NAME; // Use -dev suffix only when explicitly in development mode // eslint-disable-next-line no-restricted-syntax, no-restricted-globals const suffix = process.env.NODE_ENV === "development" ? "-dev" : ""; diff --git a/src/common/constants/workspace.ts b/src/common/constants/workspace.ts index c45cc0c678..04f6e3e341 100644 --- a/src/common/constants/workspace.ts +++ b/src/common/constants/workspace.ts @@ -6,5 +6,5 @@ import type { RuntimeConfig } from "@/common/types/runtime"; */ export const DEFAULT_RUNTIME_CONFIG: RuntimeConfig = { type: "local", - srcBaseDir: "~/.cmux/src", + srcBaseDir: "~/.mux/src", } as const; diff --git a/src/common/telemetry/client.ts b/src/common/telemetry/client.ts index fe548e90c9..8b42021dbd 100644 --- a/src/common/telemetry/client.ts +++ b/src/common/telemetry/client.ts @@ -46,7 +46,7 @@ let isInitialized = false; // Storage key for telemetry enabled preference const TELEMETRY_ENABLED_KEY = "mux_telemetry_enabled"; -const LEGACY_TELEMETRY_KEY = "cmux_telemetry_enabled"; +const LEGACY_TELEMETRY_KEY = "mux_telemetry_enabled"; /** * Check if telemetry is enabled by user preference diff --git a/src/common/telemetry/lifecycle.ts b/src/common/telemetry/lifecycle.ts index a4fb04ab40..875e2bacd7 100644 --- a/src/common/telemetry/lifecycle.ts +++ b/src/common/telemetry/lifecycle.ts @@ -13,7 +13,7 @@ import { trackEvent, getBaseTelemetryProperties } from "./index"; */ function checkFirstLaunch(): boolean { const key = "mux_first_launch_complete"; - const legacyKey = "cmux_first_launch_complete"; + const legacyKey = "mux_first_launch_complete"; // Check new key first const hasLaunchedBefore = localStorage.getItem(key); diff --git a/src/common/types/ipc.ts b/src/common/types/ipc.ts index ce91019d68..07824b7729 100644 --- a/src/common/types/ipc.ts +++ b/src/common/types/ipc.ts @@ -188,7 +188,7 @@ export interface SendMessageOptions { maxOutputTokens?: number; providerOptions?: MuxProviderOptions; mode?: string; // Mode name - frontend narrows to specific values, backend accepts any string - cmuxMetadata?: MuxFrontendMetadata; // Frontend-defined metadata, backend treats as black-box + muxMetadata?: MuxFrontendMetadata; // Frontend-defined metadata, backend treats as black-box } // API method signatures (shared between main and preload) diff --git a/src/common/types/message.ts b/src/common/types/message.ts index c388b57e16..2c381419a9 100644 --- a/src/common/types/message.ts +++ b/src/common/types/message.ts @@ -11,7 +11,7 @@ export interface CompactionRequestData { continueMessage?: string; } -// Frontend-specific metadata stored in cmuxMetadata field +// Frontend-specific metadata stored in muxMetadata field // Backend stores this as-is without interpretation (black-box) export type MuxFrontendMetadata = | { @@ -45,7 +45,9 @@ export interface MuxMetadata { toolPolicy?: ToolPolicy; // Tool policy active when this message was sent (user messages only) mode?: string; // The mode (plan/exec/etc) active when this message was sent (assistant messages only) cmuxMetadata?: MuxFrontendMetadata; // Frontend-defined metadata, backend treats as black-box + muxMetadata?: MuxFrontendMetadata; // Frontend-defined metadata, backend treats as black-box historicalUsage?: ChatUsageDisplay; // Cumulative usage from all messages before this compaction (only present on compaction summaries) + } // Extended tool part type that supports interrupted tool calls (input-available state) diff --git a/src/common/types/project.ts b/src/common/types/project.ts index 90689337a6..29ca5d449c 100644 --- a/src/common/types/project.ts +++ b/src/common/types/project.ts @@ -10,7 +10,7 @@ import type { RuntimeConfig } from "./runtime"; * * NEW FORMAT (preferred, used for all new workspaces): * { - * "path": "~/.cmux/src/project/workspace-id", // Kept for backward compat + * "path": "~/.mux/src/project/workspace-id", // Kept for backward compat * "id": "a1b2c3d4e5", // Stable workspace ID * "name": "feature-branch", // User-facing name * "createdAt": "2024-01-01T00:00:00Z", // Creation timestamp @@ -19,10 +19,10 @@ import type { RuntimeConfig } from "./runtime"; * * LEGACY FORMAT (old workspaces, still supported): * { - * "path": "~/.cmux/src/project/workspace-id" // Only field present + * "path": "~/.mux/src/project/workspace-id" // Only field present * } * - * For legacy entries, metadata is read from ~/.cmux/sessions/{workspaceId}/metadata.json + * For legacy entries, metadata is read from ~/.mux/sessions/{workspaceId}/metadata.json */ export interface Workspace { /** Absolute path to workspace directory - REQUIRED for backward compatibility */ diff --git a/src/common/types/runtime.ts b/src/common/types/runtime.ts index bd408dcb81..085b702b9d 100644 --- a/src/common/types/runtime.ts +++ b/src/common/types/runtime.ts @@ -17,7 +17,7 @@ export const SSH_RUNTIME_PREFIX = "ssh "; export type RuntimeConfig = | { type: "local"; - /** Base directory where all workspaces are stored (e.g., ~/.cmux/src) */ + /** Base directory where all workspaces are stored (e.g., ~/.mux/src) */ srcBaseDir: string; } | { diff --git a/src/common/types/workspace.ts b/src/common/types/workspace.ts index cd338ee73e..8e079214fe 100644 --- a/src/common/types/workspace.ts +++ b/src/common/types/workspace.ts @@ -24,7 +24,7 @@ export const WorkspaceMetadataSchema = z.object({ * Can be changed via rename operation * * For legacy workspaces created before stable IDs: - * - id and name are the same (e.g., "cmux-stable-ids") + * - id and name are the same (e.g., "mux-stable-ids") * For new workspaces: * - id is a random 10 hex char string (e.g., "a1b2c3d4e5") * - name is the branch/workspace name (e.g., "feature-branch") diff --git a/src/common/utils/compaction/handler.ts b/src/common/utils/compaction/handler.ts index e8d54101f6..adcc68bed3 100644 --- a/src/common/utils/compaction/handler.ts +++ b/src/common/utils/compaction/handler.ts @@ -20,7 +20,7 @@ import { getCancelledCompactionKey } from "@/common/constants/storage"; export function isCompactingStream(aggregator: StreamingMessageAggregator): boolean { const messages = aggregator.getAllMessages(); const lastUserMsg = [...messages].reverse().find((m) => m.role === "user"); - return lastUserMsg?.metadata?.cmuxMetadata?.type === "compaction-request"; + return lastUserMsg?.metadata?.muxMetadata?.type === "compaction-request"; } /** @@ -33,7 +33,7 @@ export function findCompactionRequestMessage( return ( [...messages] .reverse() - .find((m) => m.role === "user" && m.metadata?.cmuxMetadata?.type === "compaction-request") ?? + .find((m) => m.role === "user" && m.metadata?.muxMetadata?.type === "compaction-request") ?? null ); } @@ -45,10 +45,10 @@ export function getCompactionCommand(aggregator: StreamingMessageAggregator): st const compactionMsg = findCompactionRequestMessage(aggregator); if (!compactionMsg) return null; - const cmuxMeta = compactionMsg.metadata?.cmuxMetadata; - if (cmuxMeta?.type !== "compaction-request") return null; + const muxMeta = compactionMsg.metadata?.muxMetadata; + if (muxMeta?.type !== "compaction-request") return null; - return cmuxMeta.rawCommand ?? null; + return muxMeta.rawCommand ?? null; } /** diff --git a/src/common/utils/paths.ts b/src/common/utils/paths.ts index 4d32371a2d..24fbd55bef 100644 --- a/src/common/utils/paths.ts +++ b/src/common/utils/paths.ts @@ -151,7 +151,7 @@ export class PlatformPaths { * * @example * // Unix - * abbreviate("/home/user/Projects/cmux") // => "/h/u/P/cmux" + * abbreviate("/home/user/Projects/mux") // => "/h/u/P/mux" * * // Windows * abbreviate("C:\\Users\\john\\Documents\\project") // => "C:\\U\\j\\D\\project" @@ -187,7 +187,7 @@ export class PlatformPaths { * @returns Object with dirPath (including trailing separator) and basename * * @example - * splitAbbreviated("/h/u/P/cmux") // => { dirPath: "/h/u/P/", basename: "cmux" } + * splitAbbreviated("/h/u/P/mux") // => { dirPath: "/h/u/P/", basename: "mux" } */ static splitAbbreviated(filePath: string): { dirPath: string; basename: string } { if (!filePath || typeof filePath !== "string") { @@ -218,8 +218,8 @@ export class PlatformPaths { * @returns Project name (final directory component) * * @example - * getProjectName("/home/user/projects/cmux") // => "cmux" - * getProjectName("C:\\Users\\john\\projects\\cmux") // => "cmux" + * getProjectName("/home/user/projects/mux") // => "mux" + * getProjectName("C:\\Users\\john\\projects\\mux") // => "mux" */ static getProjectName(projectPath: string): string { return this.basename(projectPath) || "unknown"; diff --git a/src/desktop/main.ts b/src/desktop/main.ts index 84e4c536f8..7915ebdd84 100644 --- a/src/desktop/main.ts +++ b/src/desktop/main.ts @@ -14,11 +14,12 @@ import { } from "electron"; import * as fs from "fs"; import * as path from "path"; +<<<<<<< HEAD:src/desktop/main.ts import type { Config } from "@/node/config"; import type { IpcMain } from "@/node/services/ipcMain"; import { VERSION } from "@/version"; import { IPC_CHANNELS } from "@/common/constants/ipc-constants"; -import { getMuxHome, migrateCmuxToMux } from "@/common/constants/paths"; +import { getMuxHome, migrateLegacyMuxHome } from "@/common/constants/paths"; import { log } from "@/node/services/log"; import { parseDebugUpdater } from "@/common/utils/env"; import assert from "@/common/utils/assert"; @@ -369,7 +370,7 @@ function createWindow() { contextIsolation: true, preload: path.join(__dirname, "../preload.js"), }, - title: "cmux - coder multiplexer", + title: "mux - coder multiplexer", // Hide menu bar on Linux by default (like VS Code) // User can press Alt to toggle it autoHideMenuBar: process.platform === "linux", @@ -493,7 +494,7 @@ if (gotTheLock) { console.log("App ready, creating window..."); // Migrate from .cmux to .mux directory structure if needed - migrateCmuxToMux(); + migrateLegacyMuxHome(); // Install React DevTools in development if (!app.isPackaged && installExtension && REACT_DEVELOPER_TOOLS) { diff --git a/src/node/bench/headlessEnvironment.ts b/src/node/bench/headlessEnvironment.ts index 8289bc3821..29828c843e 100644 --- a/src/node/bench/headlessEnvironment.ts +++ b/src/node/bench/headlessEnvironment.ts @@ -67,7 +67,7 @@ async function establishRootDir(providedRootDir?: string): Promise<{ }; } - const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "cmux-headless-")); + const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "mux-headless-")); return { rootDir: tempRoot, dispose: async () => { diff --git a/src/node/config.test.ts b/src/node/config.test.ts index 3056cad139..d4b0a1d891 100644 --- a/src/node/config.test.ts +++ b/src/node/config.test.ts @@ -9,7 +9,7 @@ describe("Config", () => { beforeEach(() => { // Create a temporary directory for each test - tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "cmux-test-")); + tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "mux-test-")); config = new Config(tempDir); }); diff --git a/src/node/config.ts b/src/node/config.ts index 429c26bd6f..a0f92fcc88 100644 --- a/src/node/config.ts +++ b/src/node/config.ts @@ -451,7 +451,7 @@ export class Config { const jsonString = JSON.stringify(config, null, 2); // Add a comment header to the file - const contentWithComments = `// Providers configuration for cmux + const contentWithComments = `// Providers configuration for mux // Configure your AI providers here // Example: // { diff --git a/src/node/git.test.ts b/src/node/git.test.ts index 86e18d1658..92be2576d2 100644 --- a/src/node/git.test.ts +++ b/src/node/git.test.ts @@ -17,7 +17,7 @@ describe("createWorktree", () => { beforeAll(async () => { // Create a temporary git repository for testing - tempGitRepo = await fs.mkdtemp(path.join(os.tmpdir(), "cmux-git-test-")); + tempGitRepo = await fs.mkdtemp(path.join(os.tmpdir(), "mux-git-test-")); await execAsync(`git init`, { cwd: tempGitRepo }); await execAsync(`git config user.email "test@example.com"`, { cwd: tempGitRepo }); await execAsync(`git config user.name "Test User"`, { cwd: tempGitRepo }); diff --git a/src/node/runtime/Runtime.ts b/src/node/runtime/Runtime.ts index 0f050fdea3..4e01a0ceb9 100644 --- a/src/node/runtime/Runtime.ts +++ b/src/node/runtime/Runtime.ts @@ -13,8 +13,8 @@ * PATH TERMINOLOGY & HIERARCHY * * srcBaseDir (base directory for all workspaces): - * - Where cmux stores ALL workspace directories - * - Local: ~/.cmux/src (tilde expanded to full path by LocalRuntime) + * - Where mux stores ALL workspace directories + * - Local: ~/.mux/src (tilde expanded to full path by LocalRuntime) * - SSH: /home/user/workspace (must be absolute path, no tilde allowed) * * Workspace Path Computation: @@ -27,11 +27,11 @@ * Example: "feature-123" or "main" * * Full Example (Local): - * srcBaseDir: ~/.cmux/src (expanded to /home/user/.cmux/src) + * srcBaseDir: ~/.mux/src (expanded to /home/user/.mux/src) * projectPath: /Users/me/git/my-project (local git repo) * projectName: my-project (extracted) * workspaceName: feature-123 - * → Workspace: /home/user/.cmux/src/my-project/feature-123 + * → Workspace: /home/user/.mux/src/my-project/feature-123 * * Full Example (SSH): * srcBaseDir: /home/user/workspace (absolute path required) @@ -248,11 +248,11 @@ export interface Runtime { * * @example * // LocalRuntime - * await runtime.resolvePath("~/cmux") // => "/home/user/cmux" + * await runtime.resolvePath("~/mux") // => "/home/user/mux" * await runtime.resolvePath("./relative") // => "/current/dir/relative" * * // SSHRuntime - * await runtime.resolvePath("~/cmux") // => "/home/user/cmux" (via SSH shell expansion) + * await runtime.resolvePath("~/mux") // => "/home/user/mux" (via SSH shell expansion) */ resolvePath(path: string): Promise; diff --git a/src/node/runtime/SSHRuntime.test.ts b/src/node/runtime/SSHRuntime.test.ts index 4ee0f8ccc6..1ffdb2810e 100644 --- a/src/node/runtime/SSHRuntime.test.ts +++ b/src/node/runtime/SSHRuntime.test.ts @@ -7,7 +7,7 @@ describe("SSHRuntime constructor", () => { expect(() => { new SSHRuntime({ host: "example.com", - srcBaseDir: "~/cmux", + srcBaseDir: "~/mux", }); }).not.toThrow(); }); @@ -26,7 +26,7 @@ describe("SSHRuntime constructor", () => { expect(() => { new SSHRuntime({ host: "example.com", - srcBaseDir: "/home/user/cmux", + srcBaseDir: "/home/user/mux", }); }).not.toThrow(); }); diff --git a/src/node/runtime/SSHRuntime.ts b/src/node/runtime/SSHRuntime.ts index ea27d04cb6..22588e8737 100644 --- a/src/node/runtime/SSHRuntime.ts +++ b/src/node/runtime/SSHRuntime.ts @@ -557,7 +557,7 @@ export class SSHRuntime implements Runtime { // Use timestamp-based bundle path to avoid conflicts (simpler than $$) const timestamp = Date.now(); - const bundleTempPath = `~/.cmux-bundle-${timestamp}.bundle`; + const bundleTempPath = `~/.mux-bundle-${timestamp}.bundle`; try { // Step 1: Get origin URL from local repository (if it exists) @@ -569,7 +569,7 @@ export class SSHRuntime implements Runtime { const { stdout } = await proc.result; const url = stdout.trim(); // Only use URL if it's not a bundle path (avoids propagating bundle paths) - if (url && !url.includes(".bundle") && !url.includes(".cmux-bundle")) { + if (url && !url.includes(".bundle") && !url.includes(".mux-bundle")) { originUrl = url; } } catch (error) { diff --git a/src/node/runtime/sshConnectionPool.test.ts b/src/node/runtime/sshConnectionPool.test.ts index 9b3536ce96..cfc7072c6c 100644 --- a/src/node/runtime/sshConnectionPool.test.ts +++ b/src/node/runtime/sshConnectionPool.test.ts @@ -80,7 +80,7 @@ describe("sshConnectionPool", () => { const controlPath = getControlPath(config); expect(controlPath).toContain(os.tmpdir()); - expect(controlPath).toMatch(/cmux-ssh-[a-f0-9]{12}$/); + expect(controlPath).toMatch(/mux-ssh-[a-f0-9]{12}$/); }); test("missing port defaults to 22 in hash calculation", () => { @@ -129,8 +129,8 @@ describe("username isolation", () => { // The path should be deterministic for this user expect(controlPath).toBe(getControlPath(config)); - const expectedPrefix = path.join(os.tmpdir(), "cmux-ssh-"); + const expectedPrefix = path.join(os.tmpdir(), "mux-ssh-"); expect(controlPath.startsWith(expectedPrefix)).toBe(true); - expect(controlPath).toMatch(/cmux-ssh-[a-f0-9]{12}$/); + expect(controlPath).toMatch(/mux-ssh-[a-f0-9]{12}$/); }); }); diff --git a/src/node/runtime/sshConnectionPool.ts b/src/node/runtime/sshConnectionPool.ts index 7e3bdf2f53..e3e597dd0f 100644 --- a/src/node/runtime/sshConnectionPool.ts +++ b/src/node/runtime/sshConnectionPool.ts @@ -31,7 +31,7 @@ import type { SSHRuntimeConfig } from "./SSHRuntime"; export function getControlPath(config: SSHRuntimeConfig): string { const key = makeConnectionKey(config); const hash = hashKey(key); - return path.join(os.tmpdir(), `cmux-ssh-${hash}`); + return path.join(os.tmpdir(), `mux-ssh-${hash}`); } /** diff --git a/src/node/services/ExtensionMetadataService.ts b/src/node/services/ExtensionMetadataService.ts index e990980389..843fc080dd 100644 --- a/src/node/services/ExtensionMetadataService.ts +++ b/src/node/services/ExtensionMetadataService.ts @@ -16,7 +16,7 @@ import { * - streaming: Boolean indicating if workspace has an active stream * - lastModel: Last model used in this workspace * - * File location: ~/.cmux/extensionMetadata.json + * File location: ~/.mux/extensionMetadata.json * * Design: * - Stateless: reads from disk on every operation, no in-memory cache diff --git a/src/node/services/agentSession.ts b/src/node/services/agentSession.ts index 4384ec948b..1bafc91c21 100644 --- a/src/node/services/agentSession.ts +++ b/src/node/services/agentSession.ts @@ -214,7 +214,7 @@ export class AgentSession { let derivedProjectName: string; if (isUnderSrcBaseDir) { - // Standard worktree mode: workspace is under ~/.cmux/src/project/branch + // Standard worktree mode: workspace is under ~/.mux/src/project/branch derivedProjectPath = path.dirname(normalizedWorkspacePath); workspaceName = PlatformPaths.basename(normalizedWorkspacePath); derivedProjectName = @@ -304,7 +304,7 @@ export class AgentSession { { timestamp: Date.now(), toolPolicy: options?.toolPolicy, - cmuxMetadata: options?.cmuxMetadata, // Pass through frontend metadata as black-box + muxMetadata: options?.muxMetadata, // Pass through frontend metadata as black-box }, additionalParts ); diff --git a/src/node/services/aiService.ts b/src/node/services/aiService.ts index 644f8142bc..766d00a13b 100644 --- a/src/node/services/aiService.ts +++ b/src/node/services/aiService.ts @@ -252,7 +252,7 @@ export class AIService extends EventEmitter { */ private async createModel( modelString: string, - cmuxProviderOptions?: MuxProviderOptions + muxProviderOptions?: MuxProviderOptions ): Promise> { try { // Parse model string (format: "provider:model-id") @@ -296,7 +296,7 @@ export class AIService extends EventEmitter { } // Add 1M context beta header if requested - const use1MContext = cmuxProviderOptions?.anthropic?.use1MContext; + const use1MContext = muxProviderOptions?.anthropic?.use1MContext; const existingHeaders = providerConfig.headers as Record | undefined; const headers = use1MContext && existingHeaders @@ -325,8 +325,8 @@ export class AIService extends EventEmitter { // This is a temporary override until @ai-sdk/openai supports passing // truncation via providerOptions. Safe because it only targets the // OpenAI Responses endpoint and leaves other providers untouched. - // Can be disabled via cmuxProviderOptions for testing purposes. - const disableAutoTruncation = cmuxProviderOptions?.openai?.disableAutoTruncation ?? false; + // Can be disabled via muxProviderOptions for testing purposes. + const disableAutoTruncation = muxProviderOptions?.openai?.disableAutoTruncation ?? false; const fetchWithOpenAITruncation = Object.assign( async ( input: Parameters[0], @@ -501,7 +501,7 @@ export class AIService extends EventEmitter { * @param abortSignal Optional signal to abort the stream * @param additionalSystemInstructions Optional additional system instructions to append * @param maxOutputTokens Optional maximum tokens for model output - * @param cmuxProviderOptions Optional provider-specific options + * @param muxProviderOptions Optional provider-specific options * @param mode Optional mode name - affects system message via Mode: sections in AGENTS.md * @returns Promise that resolves when streaming completes or fails */ @@ -514,7 +514,7 @@ export class AIService extends EventEmitter { abortSignal?: AbortSignal, additionalSystemInstructions?: string, maxOutputTokens?: number, - cmuxProviderOptions?: MuxProviderOptions, + muxProviderOptions?: MuxProviderOptions, mode?: string ): Promise> { try { @@ -533,7 +533,7 @@ export class AIService extends EventEmitter { await this.partialService.commitToHistory(workspaceId); // Create model instance with early API key validation - const modelResult = await this.createModel(modelString, cmuxProviderOptions); + const modelResult = await this.createModel(modelString, muxProviderOptions); if (!modelResult.success) { return Err(modelResult.error); } @@ -711,10 +711,10 @@ export class AIService extends EventEmitter { const forceContextLimitError = modelString.startsWith("openai:") && - cmuxProviderOptions?.openai?.forceContextLimitError === true; + muxProviderOptions?.openai?.forceContextLimitError === true; const simulateToolPolicyNoop = modelString.startsWith("openai:") && - cmuxProviderOptions?.openai?.simulateToolPolicyNoop === true; + muxProviderOptions?.openai?.simulateToolPolicyNoop === true; if (forceContextLimitError) { const errorMessage = diff --git a/src/node/services/historyService.test.ts b/src/node/services/historyService.test.ts index 71540a1613..f160d47bba 100644 --- a/src/node/services/historyService.test.ts +++ b/src/node/services/historyService.test.ts @@ -13,7 +13,7 @@ describe("HistoryService", () => { beforeEach(async () => { // Create a temporary directory for test files - tempDir = path.join(os.tmpdir(), `cmux-test-${Date.now()}-${Math.random()}`); + tempDir = path.join(os.tmpdir(), `mux-test-${Date.now()}-${Math.random()}`); await fs.mkdir(tempDir, { recursive: true }); // Create a Config with the temp directory diff --git a/src/node/services/initStateManager.test.ts b/src/node/services/initStateManager.test.ts index 5c84097c90..b520b33479 100644 --- a/src/node/services/initStateManager.test.ts +++ b/src/node/services/initStateManager.test.ts @@ -12,7 +12,7 @@ describe("InitStateManager", () => { let manager: InitStateManager; beforeEach(async () => { - // Create temp directory as cmux root + // Create temp directory as mux root tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "init-state-test-")); // Create sessions directory diff --git a/src/node/services/ipcMain.ts b/src/node/services/ipcMain.ts index 1a50f7b511..7e711a82a1 100644 --- a/src/node/services/ipcMain.ts +++ b/src/node/services/ipcMain.ts @@ -1123,7 +1123,7 @@ export class IpcMain { const projectSecrets = this.config.getProjectSecrets(metadata.projectPath); // Create scoped temp directory for this IPC call - using tempDir = new DisposableTempDir("cmux-ipc-bash"); + using tempDir = new DisposableTempDir("mux-ipc-bash"); // Create runtime and compute workspace path // Runtime owns the path computation logic diff --git a/src/node/services/log.ts b/src/node/services/log.ts index ee625e8986..8640f57c25 100644 --- a/src/node/services/log.ts +++ b/src/node/services/log.ts @@ -1,5 +1,5 @@ /** - * Pipe-safe logging utilities for cmux + * Pipe-safe logging utilities for mux * * These functions wrap console.log/error with EPIPE protection to prevent * crashes when stdout/stderr pipes are closed (e.g., when piping to head/tail). @@ -74,7 +74,7 @@ function getCallerLocation(): string { if (match) { const [, filePath, lineNum] = match; // Strip the full path to just show relative path from project root - const relativePath = filePath.replace(/^.*\/cmux\//, ""); + const relativePath = filePath.replace(/^.*\/mux\//, ""); return `${relativePath}:${lineNum}`; } } @@ -212,7 +212,7 @@ export const log = { /** * Dump an object to a JSON file for debugging (only when MUX_DEBUG is set) - * Files are written to ~/.cmux/debug_obj/ + * Files are written to ~/.mux/debug_obj/ * * @param filename - Name of the file (e.g., "model_messages.json" or "workspace/data.json") * @param obj - Object to serialize and dump diff --git a/src/node/services/streamManager.ts b/src/node/services/streamManager.ts index 5b59f56ebf..d412fef810 100644 --- a/src/node/services/streamManager.ts +++ b/src/node/services/streamManager.ts @@ -243,7 +243,7 @@ export class StreamManager extends EventEmitter { /** * Create a temporary directory for a stream token - * Use ~/.cmux-tmp instead of system temp directory (e.g., /var/folders/...) + * Use ~/.mux-tmp instead of system temp directory (e.g., /var/folders/...) * because macOS user-scoped temp paths are extremely long, which leads to: * - Agent mistakes when copying/manipulating paths * - Harder to read in tool outputs @@ -254,7 +254,7 @@ export class StreamManager extends EventEmitter { public async createTempDirForStream(streamToken: StreamToken, runtime: Runtime): Promise { // Create directory and get absolute path (works for both local and remote) // Use 'cd' + 'pwd' to resolve ~ to absolute path - const command = `mkdir -p ~/.cmux-tmp/${streamToken} && cd ~/.cmux-tmp/${streamToken} && pwd`; + const command = `mkdir -p ~/.mux-tmp/${streamToken} && cd ~/.mux-tmp/${streamToken} && pwd`; const result = await execBuffered(runtime, command, { cwd: "/", timeout: 10, @@ -262,11 +262,11 @@ export class StreamManager extends EventEmitter { if (result.exitCode !== 0) { throw new Error( - `Failed to create temp directory ~/.cmux-tmp/${streamToken}: exit code ${result.exitCode}` + `Failed to create temp directory ~/.mux-tmp/${streamToken}: exit code ${result.exitCode}` ); } - // Return absolute path (e.g., "/home/user/.cmux-tmp/abc123") + // Return absolute path (e.g., "/home/user/.mux-tmp/abc123") return result.stdout.trim(); } diff --git a/src/node/services/tempDir.ts b/src/node/services/tempDir.ts index 38111c8c0e..074915edc1 100644 --- a/src/node/services/tempDir.ts +++ b/src/node/services/tempDir.ts @@ -9,7 +9,7 @@ import * as os from "os"; export class DisposableTempDir implements Disposable { public readonly path: string; - constructor(prefix = "cmux-temp") { + constructor(prefix = "mux-temp") { // Create unique temp directory const id = Math.random().toString(16).substring(2, 10); this.path = path.join(os.tmpdir(), `${prefix}-${id}`); diff --git a/src/node/services/tools/bash.ts b/src/node/services/tools/bash.ts index 96b53532ca..8a4b298c47 100644 --- a/src/node/services/tools/bash.ts +++ b/src/node/services/tools/bash.ts @@ -414,7 +414,7 @@ ${script}`; const fileId = Math.random().toString(16).substring(2, 10); // Write to runtime temp directory (managed by StreamManager) // Use path.posix.join to preserve forward slashes for SSH runtime - // (config.runtimeTempDir is always a POSIX path like /home/user/.cmux-tmp/token) + // (config.runtimeTempDir is always a POSIX path like /home/user/.mux-tmp/token) const overflowPath = path.posix.join(config.runtimeTempDir, `bash-${fileId}.txt`); const fullOutput = lines.join("\n"); diff --git a/src/node/services/tools/fileCommon.test.ts b/src/node/services/tools/fileCommon.test.ts index 4c9dd9dfe9..139835a7e4 100644 --- a/src/node/services/tools/fileCommon.test.ts +++ b/src/node/services/tools/fileCommon.test.ts @@ -215,14 +215,14 @@ describe("fileCommon", () => { const sshRuntime = createRuntime({ type: "ssh", host: "user@localhost", - srcBaseDir: "/home/user/cmux", + srcBaseDir: "/home/user/mux", identityFile: "/tmp/fake-key", }); - const sshCwd = "/home/user/cmux/project/branch"; + const sshCwd = "/home/user/mux/project/branch"; // Should auto-correct absolute paths with redundant prefix on SSH too const result = validateNoRedundantPrefix( - "/home/user/cmux/project/branch/src/file.ts", + "/home/user/mux/project/branch/src/file.ts", sshCwd, sshRuntime ); diff --git a/src/node/services/tools/fileCommon.ts b/src/node/services/tools/fileCommon.ts index 3c5c95fb89..10179b1be9 100644 --- a/src/node/services/tools/fileCommon.ts +++ b/src/node/services/tools/fileCommon.ts @@ -111,7 +111,7 @@ export function validatePathInCwd( ): { error: string } | null { // TODO: Make path validation runtime-aware instead of skipping for SSH. // For now, skip local path validation for SSH runtimes since: - // 1. Node's path module doesn't understand remote paths (~/cmux/branch) + // 1. Node's path module doesn't understand remote paths (~/mux/branch) // 2. The runtime's own file operations will fail on invalid paths anyway if (runtime instanceof SSHRuntime) { return null; diff --git a/src/node/utils/eventStore.test.ts b/src/node/utils/eventStore.test.ts index 0960f92a85..5f9e79f532 100644 --- a/src/node/utils/eventStore.test.ts +++ b/src/node/utils/eventStore.test.ts @@ -51,7 +51,7 @@ describe("EventStore", () => { } mockConfig = { - cmuxDir: path.join(__dirname, "../.."), + muxDir: path.join(__dirname, "../.."), sessionsDir: testSessionDir, getSessionDir: (workspaceId: string) => path.join(testSessionDir, workspaceId), } as unknown as Config; diff --git a/src/node/utils/main/instructionFiles.ts b/src/node/utils/main/instructionFiles.ts index 5cb9c941f2..f21fe2c181 100644 --- a/src/node/utils/main/instructionFiles.ts +++ b/src/node/utils/main/instructionFiles.ts @@ -157,7 +157,7 @@ export async function readInstructionSetFromRuntime( * All found instruction sets are returned as separate segments. * * This allows for layered instructions where: - * - Global instructions (~/.cmux/AGENTS.md) apply to all projects + * - Global instructions (~/.mux/AGENTS.md) apply to all projects * - Project instructions (workspace/AGENTS.md) add project-specific context * * @param directories - List of directories to search, in priority order diff --git a/src/node/utils/main/tokenizer.test.ts b/src/node/utils/main/tokenizer.test.ts index 29d8be5092..86df88711c 100644 --- a/src/node/utils/main/tokenizer.test.ts +++ b/src/node/utils/main/tokenizer.test.ts @@ -29,7 +29,7 @@ describe("tokenizer", () => { }); test("countTokens returns stable values", async () => { - const text = "cmux-tokenizer-smoke-test"; + const text = "mux-tokenizer-smoke-test"; const first = await countTokens(model, text); const second = await countTokens(model, text); expect(first).toBeGreaterThan(0); diff --git a/src/node/utils/pathUtils.test.ts b/src/node/utils/pathUtils.test.ts index 2f8d86e7b7..3d925a98f9 100644 --- a/src/node/utils/pathUtils.test.ts +++ b/src/node/utils/pathUtils.test.ts @@ -45,7 +45,7 @@ describe("pathUtils", () => { beforeEach(() => { // Create a temporary directory for testing - tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "cmux-path-test-")); + tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "mux-path-test-")); }); afterEach(() => { @@ -65,7 +65,7 @@ describe("pathUtils", () => { it("should expand tilde and validate", async () => { // Create a test directory in home with .git - const testDir = path.join(os.homedir(), `cmux-test-git-${Date.now()}`); + const testDir = path.join(os.homedir(), `mux-test-git-${Date.now()}`); // eslint-disable-next-line local/no-sync-fs-methods -- Test setup only fs.mkdirSync(testDir, { recursive: true }); // eslint-disable-next-line local/no-sync-fs-methods -- Test setup only @@ -81,7 +81,7 @@ describe("pathUtils", () => { }); it("should return error for non-existent path", async () => { - const nonExistentPath = "/this/path/definitely/does/not/exist/cmux-test-12345"; + const nonExistentPath = "/this/path/definitely/does/not/exist/mux-test-12345"; const result = await validateProjectPath(nonExistentPath); expect(result.valid).toBe(false); expect(result.error).toContain("does not exist"); @@ -98,7 +98,7 @@ describe("pathUtils", () => { }); it("should handle tilde path to non-existent directory", async () => { - const nonExistentTildePath = "~/this-directory-should-not-exist-cmux-test-12345"; + const nonExistentTildePath = "~/this-directory-should-not-exist-mux-test-12345"; const result = await validateProjectPath(nonExistentTildePath); expect(result.valid).toBe(false); expect(result.error).toContain("does not exist"); diff --git a/src/node/utils/paths.test.ts b/src/node/utils/paths.test.ts index 43c77402e0..3cff7f8dbb 100644 --- a/src/node/utils/paths.test.ts +++ b/src/node/utils/paths.test.ts @@ -18,12 +18,12 @@ describe("PlatformPaths", () => { describe("parse", () => { test("parses absolute path on current platform", () => { - const testPath = path.join("/", "home", "user", "projects", "cmux"); + const testPath = path.join("/", "home", "user", "projects", "mux"); const result = PlatformPaths.parse(testPath); expect(result.segments).toContain("home"); expect(result.segments).toContain("user"); expect(result.segments).toContain("projects"); - expect(result.basename).toBe("cmux"); + expect(result.basename).toBe("mux"); }); test("parses relative path", () => { @@ -40,11 +40,11 @@ describe("PlatformPaths", () => { describe("abbreviate", () => { test("abbreviates path", () => { - const testPath = path.join("/", "home", "user", "Projects", "coder", "cmux"); + const testPath = path.join("/", "home", "user", "Projects", "coder", "mux"); const result = PlatformPaths.abbreviate(testPath); // Should end with the full basename - expect(result.endsWith("cmux")).toBe(true); + expect(result.endsWith("mux")).toBe(true); // Should be shorter than original (segments abbreviated) expect(result.length).toBeLessThan(testPath.length); @@ -64,9 +64,9 @@ describe("PlatformPaths", () => { describe("splitAbbreviated", () => { test("splits abbreviated path", () => { - const testPath = path.join("/", "h", "u", "P", "c", "cmux"); + const testPath = path.join("/", "h", "u", "P", "c", "mux"); const result = PlatformPaths.splitAbbreviated(testPath); - expect(result.basename).toBe("cmux"); + expect(result.basename).toBe("mux"); expect(result.dirPath.endsWith(path.sep)).toBe(true); }); @@ -80,12 +80,12 @@ describe("PlatformPaths", () => { describe("formatHome", () => { test("replaces home directory with tilde on Unix", () => { const home = os.homedir(); - const testPath = path.join(home, "projects", "cmux"); + const testPath = path.join(home, "projects", "mux"); const result = PlatformPaths.formatHome(testPath); // On Unix-like systems, should use tilde if (process.platform !== "win32") { - expect(result).toBe("~/projects/cmux"); + expect(result).toBe("~/projects/mux"); } else { // On Windows, should keep full path expect(result).toContain(home); @@ -107,8 +107,8 @@ describe("PlatformPaths", () => { test("expands tilde with path", () => { const home = os.homedir(); const sep = path.sep; - const result = PlatformPaths.expandHome(`~${sep}projects${sep}cmux`); - expect(result).toBe(path.join(home, "projects", "cmux")); + const result = PlatformPaths.expandHome(`~${sep}projects${sep}mux`); + expect(result).toBe(path.join(home, "projects", "mux")); }); test("leaves absolute paths unchanged", () => { @@ -123,12 +123,12 @@ describe("PlatformPaths", () => { describe("getProjectName", () => { test("extracts project name from path", () => { - const testPath = path.join("/", "home", "user", "projects", "cmux"); - expect(PlatformPaths.getProjectName(testPath)).toBe("cmux"); + const testPath = path.join("/", "home", "user", "projects", "mux"); + expect(PlatformPaths.getProjectName(testPath)).toBe("mux"); }); test("handles relative paths", () => { - expect(PlatformPaths.getProjectName("projects/cmux")).toBe("cmux"); + expect(PlatformPaths.getProjectName("projects/mux")).toBe("mux"); }); test("returns 'unknown' for empty path", () => { diff --git a/src/node/utils/sessionFile.ts b/src/node/utils/sessionFile.ts index 707b6473fc..b253138201 100644 --- a/src/node/utils/sessionFile.ts +++ b/src/node/utils/sessionFile.ts @@ -10,7 +10,7 @@ import { workspaceFileLocks } from "@/node/utils/concurrency/workspaceFileLocks" * Provides consistent file locking, error handling, and path resolution. * * Used by PartialService, InitStateManager, and other services that need - * to persist state to ~/.cmux/sessions/{workspaceId}/. + * to persist state to ~/.mux/sessions/{workspaceId}/. */ export class SessionFileManager { private readonly config: Config; diff --git a/tests/ipcMain/sendMessage.test.ts b/tests/ipcMain/sendMessage.test.ts index 2e21488225..11a34c0b16 100644 --- a/tests/ipcMain/sendMessage.test.ts +++ b/tests/ipcMain/sendMessage.test.ts @@ -1459,7 +1459,7 @@ These are general instructions that apply to all modes. "Test message with metadata", { model: "openai:gpt-4", // Valid format but provider not configured - will fail after storing message - cmuxMetadata: testMetadata, + muxMetadata: testMetadata, } ); @@ -1486,14 +1486,14 @@ These are general instructions that apply to all modes. // Verify metadata was preserved exactly as sent (black-box) expect(userMessage).toHaveProperty("metadata"); const metadata = (userMessage as any).metadata; - expect(metadata).toHaveProperty("cmuxMetadata"); - expect(metadata.cmuxMetadata).toEqual(testMetadata); + expect(metadata).toHaveProperty("muxMetadata"); + expect(metadata.muxMetadata).toEqual(testMetadata); // Verify structured fields are accessible - expect(metadata.cmuxMetadata.type).toBe("compaction-request"); - expect(metadata.cmuxMetadata.rawCommand).toBe("/compact -c continue working"); - expect(metadata.cmuxMetadata.parsed.continueMessage).toBe("continue working"); - expect(metadata.cmuxMetadata.parsed.maxOutputTokens).toBe(5000); + expect(metadata.muxMetadata.type).toBe("compaction-request"); + expect(metadata.muxMetadata.rawCommand).toBe("/compact -c continue working"); + expect(metadata.muxMetadata.parsed.continueMessage).toBe("continue working"); + expect(metadata.muxMetadata.parsed.maxOutputTokens).toBe(5000); } finally { await cleanup(); } diff --git a/tests/runtime/ssh-server/Dockerfile b/tests/runtime/ssh-server/Dockerfile index f019acefc0..21117baedb 100644 --- a/tests/runtime/ssh-server/Dockerfile +++ b/tests/runtime/ssh-server/Dockerfile @@ -1,7 +1,7 @@ FROM alpine:latest # Install OpenSSH server, git, and bash -# bash is required for remote command execution (cmux forces bash to avoid shell compatibility issues) +# bash is required for remote command execution (mux forces bash to avoid shell compatibility issues) RUN apk add --no-cache openssh-server git bash # Create test user diff --git a/vscode/Makefile b/vscode/Makefile index 51b2d5fe57..723e7bfece 100644 --- a/vscode/Makefile +++ b/vscode/Makefile @@ -1,6 +1,6 @@ # VS Code Extension Build System # ============================== -# Isolated build system for the cmux VS Code/Cursor extension +# Isolated build system for the mux VS Code/Cursor extension .PHONY: all build install clean help @@ -24,22 +24,22 @@ node_modules/.installed: package.json ## Build extension package build: node_modules/.installed ## Build VS Code extension (.vsix) @echo "Building VS Code extension with esbuild..." - @rm -rf out cmux-0.1.0.vsix + @rm -rf out mux-0.1.0.vsix @bun run compile @npx @vscode/vsce package --no-dependencies - @echo "✓ Extension packaged: cmux-0.1.0.vsix (bundle size: ~27 KB)" + @echo "✓ Extension packaged: mux-0.1.0.vsix (bundle size: ~27 KB)" ## Install extension locally install: build ## Build and install extension locally @echo "Installing extension..." @if command -v code >/dev/null 2>&1; then \ - code --install-extension cmux-0.1.0.vsix --force && \ + code --install-extension mux-0.1.0.vsix --force && \ echo "✓ Extension installed in VS Code"; \ else \ echo "⚠ VS Code CLI (code) not found, skipping"; \ fi @if command -v cursor >/dev/null 2>&1; then \ - cursor --install-extension cmux-0.1.0.vsix --force && \ + cursor --install-extension mux-0.1.0.vsix --force && \ echo "✓ Extension installed in Cursor"; \ else \ echo "⚠ Cursor CLI (cursor) not found, skipping"; \ @@ -49,5 +49,5 @@ install: build ## Build and install extension locally ## Clean build artifacts clean: ## Clean build artifacts @echo "Cleaning extension build artifacts..." - @rm -rf out cmux-0.1.0.vsix node_modules/.installed + @rm -rf out mux-0.1.0.vsix node_modules/.installed @echo "✓ Clean complete" diff --git a/vscode/bun.lock b/vscode/bun.lock index 08480136e1..3639bc9ce2 100644 --- a/vscode/bun.lock +++ b/vscode/bun.lock @@ -2,7 +2,7 @@ "lockfileVersion": 1, "workspaces": { "": { - "name": "cmux", + "name": "mux", "devDependencies": { "@types/node": "^20.0.0", "@types/vscode": "^1.85.0", diff --git a/vscode/esbuild.config.js b/vscode/esbuild.config.js index 9dc5245727..7dcfc44297 100644 --- a/vscode/esbuild.config.js +++ b/vscode/esbuild.config.js @@ -1,14 +1,14 @@ const esbuild = require("esbuild"); const path = require("path"); -// Plugin to resolve cmux/* imports from parent directory +// Plugin to resolve mux/* imports from parent directory // and resolve npm dependencies from main app's node_modules -const cmuxResolverPlugin = { - name: "cmux-resolver", +const muxResolverPlugin = { + name: "mux-resolver", setup(build) { - // Resolve cmux/* imports to parent src directory - build.onResolve({ filter: /^cmux\// }, (args) => { - const subpath = args.path.replace(/^cmux\//, ""); + // Resolve mux/* imports to parent src directory + build.onResolve({ filter: /^mux\// }, (args) => { + const subpath = args.path.replace(/^mux\//, ""); return { path: path.resolve(__dirname, "..", "src", subpath + ".ts"), }; @@ -27,7 +27,7 @@ esbuild format: "cjs", minify: true, sourcemap: true, - plugins: [cmuxResolverPlugin], + plugins: [muxResolverPlugin], // Resolve @ alias from main app to relative paths alias: { "@": path.resolve(__dirname, "../src"), diff --git a/vscode/scripts/create-icon.sh b/vscode/scripts/create-icon.sh index dd58b80f90..29b6ae8984 100755 --- a/vscode/scripts/create-icon.sh +++ b/vscode/scripts/create-icon.sh @@ -1,5 +1,10 @@ #!/usr/bin/env bash +# Create icon.png from the mux logo for the VS Code extension # Create icon.png from the cmux logo for the VS Code extension +======= +#!/bin/bash +# Create icon.png from the mux logo for the VS Code extension +>>>>>>> 8dda7f224 (🤖 chore: rename cmux refs to mux) set -e diff --git a/vscode/src/extension.ts b/vscode/src/extension.ts index 2ff6d34f73..ca6d4af965 100644 --- a/vscode/src/extension.ts +++ b/vscode/src/extension.ts @@ -1,7 +1,7 @@ import * as vscode from "vscode"; -import { getAllWorkspaces, WorkspaceWithContext } from "./cmuxConfig"; +import { getAllWorkspaces, WorkspaceWithContext } from "./muxConfig"; import { openWorkspace } from "./workspaceOpener"; -import { formatRelativeTime } from "cmux/browser/utils/ui/dateTime"; +import { formatRelativeTime } from "mux/utils/ui/dateTime"; /** * Format workspace for display in QuickPick diff --git a/vscode/src/cmuxConfig.ts b/vscode/src/muxConfig.ts similarity index 81% rename from vscode/src/cmuxConfig.ts rename to vscode/src/muxConfig.ts index 2b03ea723e..1985f66d36 100644 --- a/vscode/src/cmuxConfig.ts +++ b/vscode/src/muxConfig.ts @@ -1,10 +1,10 @@ import * as path from "path"; import * as os from "os"; -import { Config } from "cmux/node/config"; -import type { WorkspaceMetadata } from "cmux/common/types/workspace"; -import { type ExtensionMetadata, readExtensionMetadata } from "cmux/node/utils/extensionMetadata"; -import { getProjectName } from "cmux/node/utils/runtime/helpers"; -import { createRuntime } from "cmux/node/runtime/runtimeFactory"; +import { Config } from "mux/config"; +import type { WorkspaceMetadata } from "mux/types/workspace"; +import { type ExtensionMetadata, readExtensionMetadata } from "mux/utils/extensionMetadata"; +import { getProjectName } from "mux/utils/runtime/helpers"; +import { createRuntime } from "mux/runtime/runtimeFactory"; /** * Workspace with extension metadata for display in VS Code extension. @@ -16,7 +16,7 @@ export interface WorkspaceWithContext extends WorkspaceMetadata { } /** - * Get all workspaces from cmux config, enriched with extension metadata. + * Get all workspaces from mux config, enriched with extension metadata. * Uses main app's Config class to read workspace metadata, then enriches * with extension-specific data (recency, streaming status). */ diff --git a/vscode/src/workspaceOpener.ts b/vscode/src/workspaceOpener.ts index 7cf4d4482c..9ba115b6be 100644 --- a/vscode/src/workspaceOpener.ts +++ b/vscode/src/workspaceOpener.ts @@ -1,5 +1,5 @@ import * as vscode from "vscode"; -import { WorkspaceWithContext, getWorkspacePath } from "./cmuxConfig"; +import { WorkspaceWithContext, getWorkspacePath } from "./muxConfig"; /** * Check if a Remote-SSH extension is installed diff --git a/vscode/tsconfig.json b/vscode/tsconfig.json index 0a60f54a54..a262710ce9 100644 --- a/vscode/tsconfig.json +++ b/vscode/tsconfig.json @@ -12,7 +12,7 @@ "resolveJsonModule": true, "baseUrl": ".", "paths": { - "cmux/*": ["../src/*"], + "mux/*": ["../src/*"], "@/*": ["../src/*"] } }, From e53b5a58868d8ab3a89e81a29301e09819c0b9e0 Mon Sep 17 00:00:00 2001 From: Ammar Date: Fri, 14 Nov 2025 19:55:31 +0000 Subject: [PATCH 2/9] =?UTF-8?q?=F0=9F=A4=96=20fix:=20normalize=20legacy=20?= =?UTF-8?q?mux=20metadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _Generated with `mux`_ --- src/common/constants/events.ts | 4 --- src/node/services/historyService.test.ts | 19 +++++++++++ src/node/services/historyService.ts | 3 +- src/node/services/partialService.test.ts | 42 ++++++++++++++++++++++-- src/node/services/partialService.ts | 4 ++- src/node/utils/messages/legacy.ts | 39 ++++++++++++++++++++++ 6 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 src/node/utils/messages/legacy.ts diff --git a/src/common/constants/events.ts b/src/common/constants/events.ts index 6e04f1c219..c2f4097f05 100644 --- a/src/common/constants/events.ts +++ b/src/common/constants/events.ts @@ -49,16 +49,12 @@ export const CUSTOM_EVENTS = { * Event to execute a command from the command palette * Detail: { commandId: string } */ -<<<<<<< HEAD EXECUTE_COMMAND: "mux:executeCommand", /** * Event to enter the chat-based workspace creation experience. * Detail: { projectPath: string, startMessage?: string, model?: string, trunkBranch?: string, runtime?: string } */ START_WORKSPACE_CREATION: "mux:startWorkspaceCreation", -======= - EXECUTE_COMMAND: "mux:executeCommand", ->>>>>>> a3cb9358 (🤖 chore: rename cmux refs to mux) } as const; /** diff --git a/src/node/services/historyService.test.ts b/src/node/services/historyService.test.ts index f160d47bba..6d3229676e 100644 --- a/src/node/services/historyService.test.ts +++ b/src/node/services/historyService.test.ts @@ -99,6 +99,25 @@ describe("HistoryService", () => { } }); + it("hydrates legacy cmuxMetadata entries", async () => { + const workspaceId = "workspace-legacy"; + const workspaceDir = config.getSessionDir(workspaceId); + await fs.mkdir(workspaceDir, { recursive: true }); + + const legacyMessage = createMuxMessage("msg-legacy", "user", "legacy", { + historySequence: 0, + }); + (legacyMessage.metadata as Record).cmuxMetadata = { type: "normal" }; + + const chatPath = path.join(workspaceDir, "chat.jsonl"); + await fs.writeFile(chatPath, JSON.stringify({ ...legacyMessage, workspaceId }) + "\n"); + + const result = await service.getHistory(workspaceId); + expect(result.success).toBe(true); + if (result.success) { + expect(result.data[0].metadata?.muxMetadata?.type).toBe("normal"); + } + }); it("should handle empty lines in history file", async () => { const workspaceId = "workspace1"; const workspaceDir = config.getSessionDir(workspaceId); diff --git a/src/node/services/historyService.ts b/src/node/services/historyService.ts index 1f3b517223..312c89b2c3 100644 --- a/src/node/services/historyService.ts +++ b/src/node/services/historyService.ts @@ -8,6 +8,7 @@ import { workspaceFileLocks } from "@/node/utils/concurrency/workspaceFileLocks" import { log } from "./log"; import { getTokenizerForModel } from "@/node/utils/main/tokenizer"; import { KNOWN_MODELS } from "@/common/constants/knownModels"; +import { normalizeLegacyMuxMetadata } from "@/node/utils/messages/legacy"; /** * HistoryService - Manages chat history persistence and sequence numbering @@ -49,7 +50,7 @@ export class HistoryService { for (let i = 0; i < lines.length; i++) { try { const message = JSON.parse(lines[i]) as MuxMessage; - messages.push(message); + messages.push(normalizeLegacyMuxMetadata(message)); } catch (parseError) { // Skip malformed lines but log error for debugging console.error( diff --git a/src/node/services/partialService.test.ts b/src/node/services/partialService.test.ts index d1c5b84d25..65b9e22f22 100644 --- a/src/node/services/partialService.test.ts +++ b/src/node/services/partialService.test.ts @@ -1,10 +1,13 @@ /* eslint-disable @typescript-eslint/unbound-method */ -import { describe, test, expect, beforeEach, mock } from "bun:test"; +import { describe, test, expect, beforeEach, afterEach, mock } from "bun:test"; import { PartialService } from "./partialService"; import type { HistoryService } from "./historyService"; -import type { Config } from "@/node/config"; -import type { MuxMessage } from "@/common/types/message"; +import { Config } from "@/node/config"; +import { createMuxMessage, type MuxMessage } from "@/common/types/message"; import { Ok } from "@/common/types/result"; +import * as fs from "fs/promises"; +import * as path from "path"; +import * as os from "os"; // Mock Config const createMockConfig = (): Config => { @@ -194,3 +197,36 @@ describe("PartialService - Error Recovery", () => { expect(deletePartial).toHaveBeenCalledWith(workspaceId); }); }); + +describe("PartialService - Legacy compatibility", () => { + let tempDir: string; + let config: Config; + let partialService: PartialService; + + beforeEach(async () => { + tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "mux-partial-legacy-")); + config = new Config(tempDir); + partialService = new PartialService(config, createMockHistoryService()); + }); + + afterEach(async () => { + await fs.rm(tempDir, { recursive: true, force: true }); + }); + + test("readPartial upgrades legacy cmuxMetadata", async () => { + const workspaceId = "legacy-ws"; + const workspaceDir = config.getSessionDir(workspaceId); + await fs.mkdir(workspaceDir, { recursive: true }); + + const partialMessage = createMuxMessage("partial-1", "assistant", "legacy", { + historySequence: 0, + }); + (partialMessage.metadata as Record).cmuxMetadata = { type: "normal" }; + + const partialPath = path.join(workspaceDir, "partial.json"); + await fs.writeFile(partialPath, JSON.stringify(partialMessage)); + + const result = await partialService.readPartial(workspaceId); + expect(result?.metadata?.muxMetadata?.type).toBe("normal"); + }); +}); diff --git a/src/node/services/partialService.ts b/src/node/services/partialService.ts index 6962641e95..bfb258149a 100644 --- a/src/node/services/partialService.ts +++ b/src/node/services/partialService.ts @@ -6,6 +6,7 @@ import type { MuxMessage } from "@/common/types/message"; import type { Config } from "@/node/config"; import type { HistoryService } from "./historyService"; import { workspaceFileLocks } from "@/node/utils/concurrency/workspaceFileLocks"; +import { normalizeLegacyMuxMetadata } from "@/node/utils/messages/legacy"; /** * PartialService - Manages partial message persistence for interrupted streams @@ -48,7 +49,8 @@ export class PartialService { try { const partialPath = this.getPartialPath(workspaceId); const data = await fs.readFile(partialPath, "utf-8"); - return JSON.parse(data) as MuxMessage; + const message = JSON.parse(data) as MuxMessage; + return normalizeLegacyMuxMetadata(message); } catch (error) { if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") { return null; // No partial exists diff --git a/src/node/utils/messages/legacy.ts b/src/node/utils/messages/legacy.ts new file mode 100644 index 0000000000..cfe03bcb09 --- /dev/null +++ b/src/node/utils/messages/legacy.ts @@ -0,0 +1,39 @@ +import type { MuxFrontendMetadata, MuxMessage, MuxMetadata } from "@/common/types/message"; + +interface LegacyMuxMetadata extends MuxMetadata { + cmuxMetadata?: MuxFrontendMetadata; +} + +/** + * Normalize persisted messages that were stored before the mux rename. + * + * Older builds recorded frontend metadata under `metadata.cmuxMetadata`. + * After the rename, the field lives under `metadata.muxMetadata`. + * + * This helper upgrades the legacy field on read so UI code keeps working. + */ +export function normalizeLegacyMuxMetadata(message: MuxMessage): MuxMessage { + const metadata = message.metadata as LegacyMuxMetadata | undefined; + if (metadata?.cmuxMetadata === undefined) { + return message; + } + + const { cmuxMetadata, ...rest } = metadata; + const normalizedMetadata: MuxMetadata = rest; + + if (metadata.muxMetadata) { + // Message already has the new field; just drop the legacy copy. + return { + ...message, + metadata: normalizedMetadata, + }; + } + + return { + ...message, + metadata: { + ...normalizedMetadata, + muxMetadata: cmuxMetadata, + }, + }; +} From 0817e646b6c679abf82e32207fb1e0123a0d4de0 Mon Sep 17 00:00:00 2001 From: Ammar Date: Fri, 14 Nov 2025 20:16:25 +0000 Subject: [PATCH 3/9] =?UTF-8?q?=F0=9F=A4=96=20fix:=20allow=20jest=20to=20c?= =?UTF-8?q?ompile=20esnext=20modules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _Generated with `mux`_ --- jest.config.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jest.config.js b/jest.config.js index e58a37e860..6851fc4b17 100644 --- a/jest.config.js +++ b/jest.config.js @@ -20,6 +20,8 @@ module.exports = { { tsconfig: { target: "ES2020", + module: "ESNext", + moduleResolution: "node", lib: ["ES2020", "DOM", "ES2022.Intl"], esModuleInterop: true, allowSyntheticDefaultImports: true, From 320a225e34d94fd43da308dbbec16be21c341d48 Mon Sep 17 00:00:00 2001 From: Ammar Date: Fri, 14 Nov 2025 21:12:37 +0000 Subject: [PATCH 4/9] =?UTF-8?q?=F0=9F=A4=96=20fix:=20align=20ssh=20default?= =?UTF-8?q?s=20with=20mux=20paths?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _Generated with _ --- .../components/ChatInput/CreationControls.tsx | 2 +- src/browser/components/Modal.stories.tsx | 2 +- src/browser/utils/chatCommands.test.ts | 12 ++++++------ src/browser/utils/chatCommands.ts | 2 +- src/node/runtime/Runtime.ts | 4 ++-- src/node/runtime/SSHRuntime.test.ts | 2 +- src/node/services/tools/fileCommon.ts | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/browser/components/ChatInput/CreationControls.tsx b/src/browser/components/ChatInput/CreationControls.tsx index dd231843b2..7c568fcb4b 100644 --- a/src/browser/components/ChatInput/CreationControls.tsx +++ b/src/browser/components/ChatInput/CreationControls.tsx @@ -70,7 +70,7 @@ export function CreationControls(props: CreationControlsProps) { Runtime:
• Local: git worktree in ~/.mux/src -
• SSH: remote clone in ~/mux on SSH host +
• SSH: remote clone in ~/.mux/src on SSH host
diff --git a/src/browser/components/Modal.stories.tsx b/src/browser/components/Modal.stories.tsx index acaf82af21..f1ed219ba3 100644 --- a/src/browser/components/Modal.stories.tsx +++ b/src/browser/components/Modal.stories.tsx @@ -106,7 +106,7 @@ export const WithInfoBox: Story = { <>

- This operation will create a new workspace at ~/mux/project/branch + This operation will create a new workspace at ~/.mux/src/project/branch

Existing files will not be affected.

diff --git a/src/browser/utils/chatCommands.test.ts b/src/browser/utils/chatCommands.test.ts index 57385f0af8..14fb1977a0 100644 --- a/src/browser/utils/chatCommands.test.ts +++ b/src/browser/utils/chatCommands.test.ts @@ -18,7 +18,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "user@host", - srcBaseDir: "~/mux", + srcBaseDir: "~/.mux/src", }); }); @@ -27,7 +27,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "User@Host.Example.Com", - srcBaseDir: "~/mux", + srcBaseDir: "~/.mux/src", }); }); @@ -36,7 +36,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "user@host", - srcBaseDir: "~/mux", + srcBaseDir: "~/.mux/src", }); }); @@ -51,7 +51,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "hostname", - srcBaseDir: "~/mux", + srcBaseDir: "~/.mux/src", }); }); @@ -61,7 +61,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "dev.example.com", - srcBaseDir: "~/mux", + srcBaseDir: "~/.mux/src", }); }); @@ -71,7 +71,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "root@hostname", - srcBaseDir: "~/mux", + srcBaseDir: "~/.mux/src", }); }); diff --git a/src/browser/utils/chatCommands.ts b/src/browser/utils/chatCommands.ts index 39f63800b2..f782c86c02 100644 --- a/src/browser/utils/chatCommands.ts +++ b/src/browser/utils/chatCommands.ts @@ -57,7 +57,7 @@ export function parseRuntimeString( return { type: RUNTIME_MODE.SSH, host: hostPart, - srcBaseDir: "~/mux", // Default remote base directory (tilde will be resolved by backend) + srcBaseDir: "~/.mux/src", // Default remote base directory (tilde will be resolved by backend) }; } diff --git a/src/node/runtime/Runtime.ts b/src/node/runtime/Runtime.ts index 4e01a0ceb9..dc452c2fa1 100644 --- a/src/node/runtime/Runtime.ts +++ b/src/node/runtime/Runtime.ts @@ -248,11 +248,11 @@ export interface Runtime { * * @example * // LocalRuntime - * await runtime.resolvePath("~/mux") // => "/home/user/mux" + * await runtime.resolvePath("~/.mux/src") // => "/home/user/mux" * await runtime.resolvePath("./relative") // => "/current/dir/relative" * * // SSHRuntime - * await runtime.resolvePath("~/mux") // => "/home/user/mux" (via SSH shell expansion) + * await runtime.resolvePath("~/.mux/src") // => "/home/user/mux" (via SSH shell expansion) */ resolvePath(path: string): Promise; diff --git a/src/node/runtime/SSHRuntime.test.ts b/src/node/runtime/SSHRuntime.test.ts index 1ffdb2810e..956b51cdfc 100644 --- a/src/node/runtime/SSHRuntime.test.ts +++ b/src/node/runtime/SSHRuntime.test.ts @@ -7,7 +7,7 @@ describe("SSHRuntime constructor", () => { expect(() => { new SSHRuntime({ host: "example.com", - srcBaseDir: "~/mux", + srcBaseDir: "~/.mux/src", }); }).not.toThrow(); }); diff --git a/src/node/services/tools/fileCommon.ts b/src/node/services/tools/fileCommon.ts index 10179b1be9..6875f4dd82 100644 --- a/src/node/services/tools/fileCommon.ts +++ b/src/node/services/tools/fileCommon.ts @@ -111,7 +111,7 @@ export function validatePathInCwd( ): { error: string } | null { // TODO: Make path validation runtime-aware instead of skipping for SSH. // For now, skip local path validation for SSH runtimes since: - // 1. Node's path module doesn't understand remote paths (~/mux/branch) + // 1. Node's path module doesn't understand remote paths (~/.mux/src/branch) // 2. The runtime's own file operations will fail on invalid paths anyway if (runtime instanceof SSHRuntime) { return null; From ee7ad315746bd92d4a6e0389205cc9fd90c96f30 Mon Sep 17 00:00:00 2001 From: Ammar Date: Fri, 14 Nov 2025 21:20:40 +0000 Subject: [PATCH 5/9] =?UTF-8?q?Revert=20"=F0=9F=A4=96=20fix:=20align=20ssh?= =?UTF-8?q?=20defaults=20with=20mux=20paths"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 00318605d9caa360e3d23abd45286c741b5a7e52. --- src/browser/components/AIView.tsx | 1 - .../components/ChatInput/CreationControls.tsx | 2 +- src/browser/components/Modal.stories.tsx | 2 +- src/browser/utils/chatCommands.test.ts | 12 ++++++------ src/browser/utils/chatCommands.ts | 2 +- src/common/types/message.ts | 1 - src/node/runtime/Runtime.ts | 4 ++-- src/node/runtime/SSHRuntime.test.ts | 2 +- src/node/services/tools/fileCommon.ts | 2 +- 9 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/browser/components/AIView.tsx b/src/browser/components/AIView.tsx index 2dfa3a3efc..556d6260cc 100644 --- a/src/browser/components/AIView.tsx +++ b/src/browser/components/AIView.tsx @@ -399,7 +399,6 @@ const AIViewInner: React.FC = ({ msg.type !== "workspace-init" && msg.historyId === editCutoffHistoryId; - return (
Runtime:
• Local: git worktree in ~/.mux/src -
• SSH: remote clone in ~/.mux/src on SSH host +
• SSH: remote clone in ~/mux on SSH host
diff --git a/src/browser/components/Modal.stories.tsx b/src/browser/components/Modal.stories.tsx index f1ed219ba3..acaf82af21 100644 --- a/src/browser/components/Modal.stories.tsx +++ b/src/browser/components/Modal.stories.tsx @@ -106,7 +106,7 @@ export const WithInfoBox: Story = { <>

- This operation will create a new workspace at ~/.mux/src/project/branch + This operation will create a new workspace at ~/mux/project/branch

Existing files will not be affected.

diff --git a/src/browser/utils/chatCommands.test.ts b/src/browser/utils/chatCommands.test.ts index 14fb1977a0..57385f0af8 100644 --- a/src/browser/utils/chatCommands.test.ts +++ b/src/browser/utils/chatCommands.test.ts @@ -18,7 +18,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "user@host", - srcBaseDir: "~/.mux/src", + srcBaseDir: "~/mux", }); }); @@ -27,7 +27,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "User@Host.Example.Com", - srcBaseDir: "~/.mux/src", + srcBaseDir: "~/mux", }); }); @@ -36,7 +36,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "user@host", - srcBaseDir: "~/.mux/src", + srcBaseDir: "~/mux", }); }); @@ -51,7 +51,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "hostname", - srcBaseDir: "~/.mux/src", + srcBaseDir: "~/mux", }); }); @@ -61,7 +61,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "dev.example.com", - srcBaseDir: "~/.mux/src", + srcBaseDir: "~/mux", }); }); @@ -71,7 +71,7 @@ describe("parseRuntimeString", () => { expect(result).toEqual({ type: "ssh", host: "root@hostname", - srcBaseDir: "~/.mux/src", + srcBaseDir: "~/mux", }); }); diff --git a/src/browser/utils/chatCommands.ts b/src/browser/utils/chatCommands.ts index f782c86c02..39f63800b2 100644 --- a/src/browser/utils/chatCommands.ts +++ b/src/browser/utils/chatCommands.ts @@ -57,7 +57,7 @@ export function parseRuntimeString( return { type: RUNTIME_MODE.SSH, host: hostPart, - srcBaseDir: "~/.mux/src", // Default remote base directory (tilde will be resolved by backend) + srcBaseDir: "~/mux", // Default remote base directory (tilde will be resolved by backend) }; } diff --git a/src/common/types/message.ts b/src/common/types/message.ts index 2c381419a9..294a231a93 100644 --- a/src/common/types/message.ts +++ b/src/common/types/message.ts @@ -47,7 +47,6 @@ export interface MuxMetadata { cmuxMetadata?: MuxFrontendMetadata; // Frontend-defined metadata, backend treats as black-box muxMetadata?: MuxFrontendMetadata; // Frontend-defined metadata, backend treats as black-box historicalUsage?: ChatUsageDisplay; // Cumulative usage from all messages before this compaction (only present on compaction summaries) - } // Extended tool part type that supports interrupted tool calls (input-available state) diff --git a/src/node/runtime/Runtime.ts b/src/node/runtime/Runtime.ts index dc452c2fa1..4e01a0ceb9 100644 --- a/src/node/runtime/Runtime.ts +++ b/src/node/runtime/Runtime.ts @@ -248,11 +248,11 @@ export interface Runtime { * * @example * // LocalRuntime - * await runtime.resolvePath("~/.mux/src") // => "/home/user/mux" + * await runtime.resolvePath("~/mux") // => "/home/user/mux" * await runtime.resolvePath("./relative") // => "/current/dir/relative" * * // SSHRuntime - * await runtime.resolvePath("~/.mux/src") // => "/home/user/mux" (via SSH shell expansion) + * await runtime.resolvePath("~/mux") // => "/home/user/mux" (via SSH shell expansion) */ resolvePath(path: string): Promise; diff --git a/src/node/runtime/SSHRuntime.test.ts b/src/node/runtime/SSHRuntime.test.ts index 956b51cdfc..1ffdb2810e 100644 --- a/src/node/runtime/SSHRuntime.test.ts +++ b/src/node/runtime/SSHRuntime.test.ts @@ -7,7 +7,7 @@ describe("SSHRuntime constructor", () => { expect(() => { new SSHRuntime({ host: "example.com", - srcBaseDir: "~/.mux/src", + srcBaseDir: "~/mux", }); }).not.toThrow(); }); diff --git a/src/node/services/tools/fileCommon.ts b/src/node/services/tools/fileCommon.ts index 6875f4dd82..10179b1be9 100644 --- a/src/node/services/tools/fileCommon.ts +++ b/src/node/services/tools/fileCommon.ts @@ -111,7 +111,7 @@ export function validatePathInCwd( ): { error: string } | null { // TODO: Make path validation runtime-aware instead of skipping for SSH. // For now, skip local path validation for SSH runtimes since: - // 1. Node's path module doesn't understand remote paths (~/.mux/src/branch) + // 1. Node's path module doesn't understand remote paths (~/mux/branch) // 2. The runtime's own file operations will fail on invalid paths anyway if (runtime instanceof SSHRuntime) { return null; From 3d410ac0f6a6698bcba5f1a3b1ffc5b2831aab09 Mon Sep 17 00:00:00 2001 From: Ammar Date: Sun, 16 Nov 2025 00:20:05 +0000 Subject: [PATCH 6/9] =?UTF-8?q?=F0=9F=A4=96=20fix:=20clean=20vscode=20icon?= =?UTF-8?q?=20script=20merge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vscode/scripts/create-icon.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/vscode/scripts/create-icon.sh b/vscode/scripts/create-icon.sh index 29b6ae8984..862d456e86 100755 --- a/vscode/scripts/create-icon.sh +++ b/vscode/scripts/create-icon.sh @@ -1,10 +1,5 @@ #!/usr/bin/env bash # Create icon.png from the mux logo for the VS Code extension -# Create icon.png from the cmux logo for the VS Code extension -======= -#!/bin/bash -# Create icon.png from the mux logo for the VS Code extension ->>>>>>> 8dda7f224 (🤖 chore: rename cmux refs to mux) set -e From 4d8b69418c67698a1f9461db30db843ce37bb725 Mon Sep 17 00:00:00 2001 From: Ammar Date: Sun, 16 Nov 2025 17:36:05 +0000 Subject: [PATCH 7/9] =?UTF-8?q?=F0=9F=A4=96=20fix:=20resolve=20leftover=20?= =?UTF-8?q?merge=20marker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/desktop/main.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/desktop/main.ts b/src/desktop/main.ts index 7915ebdd84..63d6dfa038 100644 --- a/src/desktop/main.ts +++ b/src/desktop/main.ts @@ -14,7 +14,6 @@ import { } from "electron"; import * as fs from "fs"; import * as path from "path"; -<<<<<<< HEAD:src/desktop/main.ts import type { Config } from "@/node/config"; import type { IpcMain } from "@/node/services/ipcMain"; import { VERSION } from "@/version"; From f37179be1768194bc57c5963098ab1081ef94cbc Mon Sep 17 00:00:00 2001 From: Ammar Date: Sun, 16 Nov 2025 17:44:41 +0000 Subject: [PATCH 8/9] =?UTF-8?q?=F0=9F=A4=96=20fix:=20point=20vscode=20exte?= =?UTF-8?q?nsion=20at=20new=20mux=20paths?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vscode/src/extension.ts | 2 +- vscode/src/muxConfig.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/vscode/src/extension.ts b/vscode/src/extension.ts index ca6d4af965..9fbb0e31e6 100644 --- a/vscode/src/extension.ts +++ b/vscode/src/extension.ts @@ -1,7 +1,7 @@ import * as vscode from "vscode"; import { getAllWorkspaces, WorkspaceWithContext } from "./muxConfig"; import { openWorkspace } from "./workspaceOpener"; -import { formatRelativeTime } from "mux/utils/ui/dateTime"; +import { formatRelativeTime } from "mux/browser/utils/ui/dateTime"; /** * Format workspace for display in QuickPick diff --git a/vscode/src/muxConfig.ts b/vscode/src/muxConfig.ts index 1985f66d36..7fed9a5ad1 100644 --- a/vscode/src/muxConfig.ts +++ b/vscode/src/muxConfig.ts @@ -1,10 +1,10 @@ import * as path from "path"; import * as os from "os"; -import { Config } from "mux/config"; -import type { WorkspaceMetadata } from "mux/types/workspace"; -import { type ExtensionMetadata, readExtensionMetadata } from "mux/utils/extensionMetadata"; -import { getProjectName } from "mux/utils/runtime/helpers"; -import { createRuntime } from "mux/runtime/runtimeFactory"; +import { Config } from "mux/node/config"; +import type { WorkspaceMetadata } from "mux/common/types/workspace"; +import { type ExtensionMetadata, readExtensionMetadata } from "mux/node/utils/extensionMetadata"; +import { getProjectName } from "mux/node/utils/runtime/helpers"; +import { createRuntime } from "mux/node/runtime/runtimeFactory"; /** * Workspace with extension metadata for display in VS Code extension. From 2275793a7955fd7219ea10c17c2d3f435223b6e4 Mon Sep 17 00:00:00 2001 From: Ammar Date: Sun, 16 Nov 2025 17:59:11 +0000 Subject: [PATCH 9/9] =?UTF-8?q?=F0=9F=A4=96=20fix:=20drop=20unused=20image?= =?UTF-8?q?magick=20flag=20from=20release=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c1234e146b..3d47478193 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,8 +94,6 @@ jobs: fetch-depth: 0 # Required for git describe to find tags - uses: ./.github/actions/setup-mux - with: - install-imagemagick: true - name: Install GNU Make (for build) run: choco install -y make