From 32d34c22fdd2907a63b89de30941b93e1057c050 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Sun, 25 Jan 2026 23:36:42 -0500 Subject: [PATCH 1/6] feat: add pnpm serve command for code-server development This adds a new `pnpm serve` command that: - Builds the extension as a vsix to a temp directory - Installs it into code-server - Configures user settings (disable welcome tab, workspace trust, etc.) - Launches code-server at http://127.0.0.1:8080 Prerequisites: brew install code-server Usage: pnpm serve --- package.json | 1 + scripts/serve.js | 176 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 scripts/serve.js diff --git a/package.json b/package.json index b93691d2693..20e3e9593be 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "clean": "turbo clean --log-order grouped --output-logs new-only && rimraf dist out bin .vite-port .turbo", "install:vsix": "pnpm install --frozen-lockfile && pnpm clean && pnpm vsix && node scripts/install-vsix.js", "install:vsix:nightly": "pnpm install --frozen-lockfile && pnpm clean && pnpm vsix:nightly && node scripts/install-vsix.js --nightly", + "serve": "node scripts/serve.js", "changeset:version": "cp CHANGELOG.md src/CHANGELOG.md && changeset version && cp -vf src/CHANGELOG.md .", "knip": "knip --include files", "evals": "dotenvx run -f packages/evals/.env.development packages/evals/.env.local -- docker compose -f packages/evals/docker-compose.yml --profile server --profile runner up --build --scale runner=0", diff --git a/scripts/serve.js b/scripts/serve.js new file mode 100644 index 00000000000..d79d0321757 --- /dev/null +++ b/scripts/serve.js @@ -0,0 +1,176 @@ +/** + * Serve script for Roo Code extension development + * + * This script builds the extension as a vsix, installs it into code-server, + * and launches code-server for web-based VS Code testing. + * + * Prerequisites: + * brew install code-server + * + * Usage: + * pnpm serve + * + * The script will: + * 1. Check if code-server is installed + * 2. Build the vsix (pnpm vsix) + * 3. Install the vsix into code-server + * 4. Configure user settings (disable welcome tab) + * 5. Start code-server on http://127.0.0.1:8080 + * + * Your password is stored in ~/.config/code-server/config.yaml + */ + +const { execSync, spawn } = require("child_process") +const fs = require("fs") +const path = require("path") +const os = require("os") + +const RESET = "\x1b[0m" +const BOLD = "\x1b[1m" +const GREEN = "\x1b[32m" +const YELLOW = "\x1b[33m" +const CYAN = "\x1b[36m" +const RED = "\x1b[31m" + +// Build vsix to a fixed path in temp directory +const VSIX_PATH = path.join(os.tmpdir(), "roo-code-serve.vsix") + +function log(message) { + console.log(`${CYAN}[serve]${RESET} ${message}`) +} + +function logSuccess(message) { + console.log(`${GREEN}✓${RESET} ${message}`) +} + +function logWarning(message) { + console.log(`${YELLOW}⚠${RESET} ${message}`) +} + +function logError(message) { + console.error(`${RED}✗${RESET} ${message}`) +} + +function isCodeServerInstalled() { + try { + execSync("which code-server", { stdio: "pipe" }) + return true + } catch { + return false + } +} + +function ensureUserSettings() { + // code-server stores user data in ~/.local/share/code-server + const userDataDir = path.join(process.env.HOME || process.env.USERPROFILE, ".local", "share", "code-server", "User") + const settingsFile = path.join(userDataDir, "settings.json") + + // Create directory if it doesn't exist + if (!fs.existsSync(userDataDir)) { + fs.mkdirSync(userDataDir, { recursive: true }) + } + + // Read existing settings or start fresh + let settings = {} + if (fs.existsSync(settingsFile)) { + try { + settings = JSON.parse(fs.readFileSync(settingsFile, "utf8")) + } catch { + // If parsing fails, start fresh + } + } + + // Set the startup editor to none (disables welcome tab) + settings["workbench.startupEditor"] = "none" + + // Hide the secondary sidebar (auxiliary bar) + settings["workbench.auxiliaryBar.visible"] = false + + // Disable extension recommendations prompts + settings["extensions.ignoreRecommendations"] = true + + fs.writeFileSync(settingsFile, JSON.stringify(settings, null, "\t")) +} + +async function main() { + console.log(`\n${BOLD}🚀 Roo Code - code-server Development Server${RESET}\n`) + + // Step 1: Check if code-server is installed + log("Checking for code-server...") + if (!isCodeServerInstalled()) { + logError("code-server is not installed") + console.log("\nTo install code-server on macOS:") + console.log(` ${CYAN}brew install code-server${RESET}`) + console.log("\nFor other platforms, see: https://coder.com/docs/code-server/install") + process.exit(1) + } + logSuccess("code-server found") + + // Step 2: Build vsix to temp directory + log(`Building vsix to ${VSIX_PATH}...`) + try { + execSync(`pnpm vsix -- --out "${VSIX_PATH}"`, { stdio: "inherit" }) + logSuccess("Build complete") + } catch (error) { + logError("Build failed") + process.exit(1) + } + + // Step 3: Install extension into code-server + log("Installing extension into code-server...") + try { + execSync(`code-server --install-extension "${VSIX_PATH}"`, { stdio: "inherit" }) + logSuccess("Extension installed") + } catch (error) { + logWarning("Extension installation had warnings (this is usually fine)") + } + + // Step 4: Configure user settings to disable welcome tab + log("Configuring user settings...") + ensureUserSettings() + logSuccess("User settings configured (welcome tab disabled)") + + // Step 5: Start code-server + const cwd = process.cwd() + console.log(`\n${BOLD}Starting code-server...${RESET}`) + console.log(` Working directory: ${cwd}`) + console.log(` URL: ${CYAN}http://127.0.0.1:8080${RESET}`) + console.log(` Password: ${YELLOW}~/.config/code-server/config.yaml${RESET}`) + console.log(`\n Press ${BOLD}Ctrl+C${RESET} to stop\n`) + + // Spawn code-server with: + // --disable-workspace-trust: Skip workspace trust prompts + // --disable-getting-started-override: Disable welcome/getting started page + // -e: Ignore last opened directory (start fresh) + const codeServer = spawn( + "code-server", + ["--disable-workspace-trust", "--disable-getting-started-override", "-e", cwd], + { + stdio: "inherit", + cwd: cwd, + }, + ) + + codeServer.on("error", (err) => { + logError(`Failed to start code-server: ${err.message}`) + process.exit(1) + }) + + codeServer.on("close", (code) => { + if (code !== 0 && code !== null) { + logError(`code-server exited with code ${code}`) + } + }) + + // Handle Ctrl+C gracefully + process.on("SIGINT", () => { + console.log("\n") + log("Shutting down code-server...") + codeServer.kill("SIGTERM") + }) +} + +main().catch((error) => { + logError(error.message) + process.exit(1) +}) From 203a6ebc3b0c93ba877e36fd919bbd72845cca69 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Sun, 25 Jan 2026 23:41:52 -0500 Subject: [PATCH 2/6] feat: add serve:rebuild command for quick extension updates Adds a --rebuild-only flag to the serve script that: - Rebuilds and reinstalls the extension - Skips starting code-server - Provides instructions to reload the window Usage: pnpm serve:rebuild --- package.json | 1 + scripts/serve.js | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 20e3e9593be..1260a502cc0 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "install:vsix": "pnpm install --frozen-lockfile && pnpm clean && pnpm vsix && node scripts/install-vsix.js", "install:vsix:nightly": "pnpm install --frozen-lockfile && pnpm clean && pnpm vsix:nightly && node scripts/install-vsix.js --nightly", "serve": "node scripts/serve.js", + "serve:rebuild": "node scripts/serve.js --rebuild-only", "changeset:version": "cp CHANGELOG.md src/CHANGELOG.md && changeset version && cp -vf src/CHANGELOG.md .", "knip": "knip --include files", "evals": "dotenvx run -f packages/evals/.env.development packages/evals/.env.local -- docker compose -f packages/evals/docker-compose.yml --profile server --profile runner up --build --scale runner=0", diff --git a/scripts/serve.js b/scripts/serve.js index d79d0321757..b18d6e0c2cd 100644 --- a/scripts/serve.js +++ b/scripts/serve.js @@ -8,14 +8,15 @@ * brew install code-server * * Usage: - * pnpm serve + * pnpm serve # Build, install, and start code-server + * pnpm serve:rebuild # Only rebuild and reinstall the extension * * The script will: * 1. Check if code-server is installed * 2. Build the vsix (pnpm vsix) * 3. Install the vsix into code-server * 4. Configure user settings (disable welcome tab) - * 5. Start code-server on http://127.0.0.1:8080 + * 5. Start code-server on http://127.0.0.1:8080 (unless --rebuild-only) * * Your password is stored in ~/.config/code-server/config.yaml */ @@ -35,6 +36,9 @@ const RED = "\x1b[31m" // Build vsix to a fixed path in temp directory const VSIX_PATH = path.join(os.tmpdir(), "roo-code-serve.vsix") +// Parse command line flags +const rebuildOnly = process.argv.includes("--rebuild-only") + function log(message) { console.log(`${CYAN}[serve]${RESET} ${message}`) } @@ -93,7 +97,8 @@ function ensureUserSettings() { } async function main() { - console.log(`\n${BOLD}🚀 Roo Code - code-server Development Server${RESET}\n`) + const title = rebuildOnly ? "Roo Code - Rebuild Extension" : "Roo Code - code-server Development Server" + console.log(`\n${BOLD}🚀 ${title}${RESET}\n`) // Step 1: Check if code-server is installed log("Checking for code-server...") @@ -130,6 +135,14 @@ async function main() { ensureUserSettings() logSuccess("User settings configured (welcome tab disabled)") + // If rebuild-only mode, exit here + if (rebuildOnly) { + console.log(`\n${GREEN}✓ Extension rebuilt and installed.${RESET}`) + console.log(` Reload the code-server window to pick up changes.`) + console.log(` (Cmd+Shift+P → "Developer: Reload Window")\n`) + return + } + // Step 5: Start code-server const cwd = process.cwd() console.log(`\n${BOLD}Starting code-server...${RESET}`) From ad0c516ffe83307555b1276cab3dc8fed8bc53e6 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Sun, 25 Jan 2026 23:52:19 -0500 Subject: [PATCH 3/6] feat: add --port argument for configurable port (default 9080) --- scripts/serve.js | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/scripts/serve.js b/scripts/serve.js index b18d6e0c2cd..9c97f28e017 100644 --- a/scripts/serve.js +++ b/scripts/serve.js @@ -8,15 +8,16 @@ * brew install code-server * * Usage: - * pnpm serve # Build, install, and start code-server - * pnpm serve:rebuild # Only rebuild and reinstall the extension + * pnpm serve # Build, install, and start code-server on port 9080 + * pnpm serve -- --port 8080 # Use a custom port + * pnpm serve:rebuild # Only rebuild and reinstall the extension * * The script will: * 1. Check if code-server is installed * 2. Build the vsix (pnpm vsix) * 3. Install the vsix into code-server * 4. Configure user settings (disable welcome tab) - * 5. Start code-server on http://127.0.0.1:8080 (unless --rebuild-only) + * 5. Start code-server on http://127.0.0.1:9080 (unless --rebuild-only) * * Your password is stored in ~/.config/code-server/config.yaml */ @@ -39,6 +40,20 @@ const VSIX_PATH = path.join(os.tmpdir(), "roo-code-serve.vsix") // Parse command line flags const rebuildOnly = process.argv.includes("--rebuild-only") +// Parse --port argument (default: 9080) +const DEFAULT_PORT = 9080 +function getPort() { + const portIndex = process.argv.indexOf("--port") + if (portIndex !== -1 && process.argv[portIndex + 1]) { + const port = parseInt(process.argv[portIndex + 1], 10) + if (!isNaN(port) && port > 0 && port < 65536) { + return port + } + } + return DEFAULT_PORT +} +const port = getPort() + function log(message) { console.log(`${CYAN}[serve]${RESET} ${message}`) } @@ -147,7 +162,7 @@ async function main() { const cwd = process.cwd() console.log(`\n${BOLD}Starting code-server...${RESET}`) console.log(` Working directory: ${cwd}`) - console.log(` URL: ${CYAN}http://127.0.0.1:8080${RESET}`) + console.log(` URL: ${CYAN}http://127.0.0.1:${port}${RESET}`) console.log(` Password: ${YELLOW}~/.config/code-server/config.yaml${RESET}`) console.log(`\n Press ${BOLD}Ctrl+C${RESET} to stop\n`) @@ -157,7 +172,14 @@ async function main() { // -e: Ignore last opened directory (start fresh) const codeServer = spawn( "code-server", - ["--disable-workspace-trust", "--disable-getting-started-override", "-e", cwd], + [ + "--bind-addr", + `127.0.0.1:${port}`, + "--disable-workspace-trust", + "--disable-getting-started-override", + "-e", + cwd, + ], { stdio: "inherit", cwd: cwd, From 1b6b894e672f52d7c35e8ac3be5a5d9eb869221a Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Mon, 26 Jan 2026 00:19:36 -0500 Subject: [PATCH 4/6] feat: add --host argument for Docker/remote access (default 127.0.0.1) --- scripts/serve.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/serve.js b/scripts/serve.js index 9c97f28e017..0638fad9e51 100644 --- a/scripts/serve.js +++ b/scripts/serve.js @@ -10,6 +10,7 @@ * Usage: * pnpm serve # Build, install, and start code-server on port 9080 * pnpm serve -- --port 8080 # Use a custom port + * pnpm serve -- --host 0.0.0.0 # Bind to all interfaces (for Docker/remote access) * pnpm serve:rebuild # Only rebuild and reinstall the extension * * The script will: @@ -54,6 +55,17 @@ function getPort() { } const port = getPort() +// Parse --host argument (default: 127.0.0.1, use 0.0.0.0 for Docker/remote access) +const DEFAULT_HOST = "127.0.0.1" +function getHost() { + const hostIndex = process.argv.indexOf("--host") + if (hostIndex !== -1 && process.argv[hostIndex + 1]) { + return process.argv[hostIndex + 1] + } + return DEFAULT_HOST +} +const host = getHost() + function log(message) { console.log(`${CYAN}[serve]${RESET} ${message}`) } @@ -162,7 +174,7 @@ async function main() { const cwd = process.cwd() console.log(`\n${BOLD}Starting code-server...${RESET}`) console.log(` Working directory: ${cwd}`) - console.log(` URL: ${CYAN}http://127.0.0.1:${port}${RESET}`) + console.log(` URL: ${CYAN}http://${host}:${port}${RESET}`) console.log(` Password: ${YELLOW}~/.config/code-server/config.yaml${RESET}`) console.log(`\n Press ${BOLD}Ctrl+C${RESET} to stop\n`) @@ -174,7 +186,7 @@ async function main() { "code-server", [ "--bind-addr", - `127.0.0.1:${port}`, + `${host}:${port}`, "--disable-workspace-trust", "--disable-getting-started-override", "-e", From 466defc4c67b5dca32e413183e30daad32946fa1 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Mon, 26 Jan 2026 00:31:42 -0500 Subject: [PATCH 5/6] feat: add --auth argument for code-server authentication (password|none) --- scripts/serve.js | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/scripts/serve.js b/scripts/serve.js index 0638fad9e51..33c68f30af6 100644 --- a/scripts/serve.js +++ b/scripts/serve.js @@ -11,6 +11,7 @@ * pnpm serve # Build, install, and start code-server on port 9080 * pnpm serve -- --port 8080 # Use a custom port * pnpm serve -- --host 0.0.0.0 # Bind to all interfaces (for Docker/remote access) + * pnpm serve -- --auth none # Disable authentication (password|none) * pnpm serve:rebuild # Only rebuild and reinstall the extension * * The script will: @@ -66,6 +67,16 @@ function getHost() { } const host = getHost() +// Parse --auth argument (optional, passed to code-server: "password" or "none") +function getAuth() { + const authIndex = process.argv.indexOf("--auth") + if (authIndex !== -1 && process.argv[authIndex + 1]) { + return process.argv[authIndex + 1] + } + return null +} +const auth = getAuth() + function log(message) { console.log(`${CYAN}[serve]${RESET} ${message}`) } @@ -175,28 +186,29 @@ async function main() { console.log(`\n${BOLD}Starting code-server...${RESET}`) console.log(` Working directory: ${cwd}`) console.log(` URL: ${CYAN}http://${host}:${port}${RESET}`) - console.log(` Password: ${YELLOW}~/.config/code-server/config.yaml${RESET}`) + if (auth === "none") { + console.log(` Auth: ${YELLOW}disabled${RESET}`) + } else { + console.log(` Password: ${YELLOW}~/.config/code-server/config.yaml${RESET}`) + } console.log(`\n Press ${BOLD}Ctrl+C${RESET} to stop\n`) // Spawn code-server with: + // --bind-addr: Address to bind to + // --auth: Authentication type (password or none) // --disable-workspace-trust: Skip workspace trust prompts // --disable-getting-started-override: Disable welcome/getting started page // -e: Ignore last opened directory (start fresh) - const codeServer = spawn( - "code-server", - [ - "--bind-addr", - `${host}:${port}`, - "--disable-workspace-trust", - "--disable-getting-started-override", - "-e", - cwd, - ], - { - stdio: "inherit", - cwd: cwd, - }, - ) + const args = ["--bind-addr", `${host}:${port}`] + if (auth) { + args.push("--auth", auth) + } + args.push("--disable-workspace-trust", "--disable-getting-started-override", "-e", cwd) + + const codeServer = spawn("code-server", args, { + stdio: "inherit", + cwd: cwd, + }) codeServer.on("error", (err) => { logError(`Failed to start code-server: ${err.message}`) From 49b7a0a573929ebc6c47a32bce067bd2a67cbd0a Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Mon, 26 Jan 2026 01:03:04 -0500 Subject: [PATCH 6/6] refactor: separate serve (start) and serve:install (build+install) --- package.json | 2 +- scripts/serve.js | 80 +++++++++++++++++++++++------------------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 1260a502cc0..b32b0bd9cc2 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "install:vsix": "pnpm install --frozen-lockfile && pnpm clean && pnpm vsix && node scripts/install-vsix.js", "install:vsix:nightly": "pnpm install --frozen-lockfile && pnpm clean && pnpm vsix:nightly && node scripts/install-vsix.js --nightly", "serve": "node scripts/serve.js", - "serve:rebuild": "node scripts/serve.js --rebuild-only", + "serve:install": "node scripts/serve.js --install-only", "changeset:version": "cp CHANGELOG.md src/CHANGELOG.md && changeset version && cp -vf src/CHANGELOG.md .", "knip": "knip --include files", "evals": "dotenvx run -f packages/evals/.env.development packages/evals/.env.local -- docker compose -f packages/evals/docker-compose.yml --profile server --profile runner up --build --scale runner=0", diff --git a/scripts/serve.js b/scripts/serve.js index 33c68f30af6..1f67c4275b1 100644 --- a/scripts/serve.js +++ b/scripts/serve.js @@ -1,25 +1,23 @@ /** * Serve script for Roo Code extension development * - * This script builds the extension as a vsix, installs it into code-server, - * and launches code-server for web-based VS Code testing. + * This script manages code-server for web-based VS Code testing. * * Prerequisites: * brew install code-server * * Usage: - * pnpm serve # Build, install, and start code-server on port 9080 + * pnpm serve # Start code-server on port 9080 * pnpm serve -- --port 8080 # Use a custom port * pnpm serve -- --host 0.0.0.0 # Bind to all interfaces (for Docker/remote access) * pnpm serve -- --auth none # Disable authentication (password|none) - * pnpm serve:rebuild # Only rebuild and reinstall the extension + * pnpm serve:install # Build and install the extension into code-server * - * The script will: - * 1. Check if code-server is installed - * 2. Build the vsix (pnpm vsix) - * 3. Install the vsix into code-server - * 4. Configure user settings (disable welcome tab) - * 5. Start code-server on http://127.0.0.1:9080 (unless --rebuild-only) + * Workflow: + * 1. Run `pnpm serve:install` to build and install the extension + * 2. Run `pnpm serve` to start code-server + * 3. After code changes, run `pnpm serve:install` again and reload the window + * (Cmd+Shift+P → "Developer: Reload Window") * * Your password is stored in ~/.config/code-server/config.yaml */ @@ -40,7 +38,7 @@ const RED = "\x1b[31m" const VSIX_PATH = path.join(os.tmpdir(), "roo-code-serve.vsix") // Parse command line flags -const rebuildOnly = process.argv.includes("--rebuild-only") +const installOnly = process.argv.includes("--install-only") // Parse --port argument (default: 9080) const DEFAULT_PORT = 9080 @@ -135,10 +133,7 @@ function ensureUserSettings() { } async function main() { - const title = rebuildOnly ? "Roo Code - Rebuild Extension" : "Roo Code - code-server Development Server" - console.log(`\n${BOLD}🚀 ${title}${RESET}\n`) - - // Step 1: Check if code-server is installed + // Check if code-server is installed log("Checking for code-server...") if (!isCodeServerInstalled()) { logError("code-server is not installed") @@ -149,39 +144,42 @@ async function main() { } logSuccess("code-server found") - // Step 2: Build vsix to temp directory - log(`Building vsix to ${VSIX_PATH}...`) - try { - execSync(`pnpm vsix -- --out "${VSIX_PATH}"`, { stdio: "inherit" }) - logSuccess("Build complete") - } catch (error) { - logError("Build failed") - process.exit(1) - } + // If install-only mode, build and install the extension + if (installOnly) { + console.log(`\n${BOLD}🔧 Roo Code - Install Extension${RESET}\n`) - // Step 3: Install extension into code-server - log("Installing extension into code-server...") - try { - execSync(`code-server --install-extension "${VSIX_PATH}"`, { stdio: "inherit" }) - logSuccess("Extension installed") - } catch (error) { - logWarning("Extension installation had warnings (this is usually fine)") - } + // Build vsix to temp directory + log(`Building vsix to ${VSIX_PATH}...`) + try { + execSync(`pnpm vsix -- --out "${VSIX_PATH}"`, { stdio: "inherit" }) + logSuccess("Build complete") + } catch (error) { + logError("Build failed") + process.exit(1) + } + + // Install extension into code-server + log("Installing extension into code-server...") + try { + execSync(`code-server --install-extension "${VSIX_PATH}"`, { stdio: "inherit" }) + logSuccess("Extension installed") + } catch (error) { + logWarning("Extension installation had warnings (this is usually fine)") + } - // Step 4: Configure user settings to disable welcome tab - log("Configuring user settings...") - ensureUserSettings() - logSuccess("User settings configured (welcome tab disabled)") + // Configure user settings to disable welcome tab + log("Configuring user settings...") + ensureUserSettings() + logSuccess("User settings configured (welcome tab disabled)") - // If rebuild-only mode, exit here - if (rebuildOnly) { - console.log(`\n${GREEN}✓ Extension rebuilt and installed.${RESET}`) - console.log(` Reload the code-server window to pick up changes.`) + console.log(`\n${GREEN}✓ Extension built and installed.${RESET}`) + console.log(` If code-server is running, reload the window to pick up changes.`) console.log(` (Cmd+Shift+P → "Developer: Reload Window")\n`) return } - // Step 5: Start code-server + // Default: Start code-server + console.log(`\n${BOLD}🚀 Roo Code - code-server Development Server${RESET}\n`) const cwd = process.cwd() console.log(`\n${BOLD}Starting code-server...${RESET}`) console.log(` Working directory: ${cwd}`)