From e62bf9e81119a62d44e03da1bc283b6892d60188 Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Fri, 26 Dec 2025 01:44:33 +0200 Subject: [PATCH] feat(shell): add Nushell support --- .../desktop/src-tauri/src/opencode_manager.rs | 6 ++++++ packages/vscode/src/opencode.ts | 18 ++++++++++++++++-- packages/web/server/index.js | 10 +++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/desktop/src-tauri/src/opencode_manager.rs b/packages/desktop/src-tauri/src/opencode_manager.rs index c35aa7eb..9bb62f5e 100644 --- a/packages/desktop/src-tauri/src/opencode_manager.rs +++ b/packages/desktop/src-tauri/src/opencode_manager.rs @@ -628,6 +628,12 @@ fn build_shell_env_command(shell: &str) -> Vec { .unwrap_or("sh"); match shell_name { + "nu" | "nushell" => vec![ + "-l".to_string(), + "-i".to_string(), + "-c".to_string(), + "echo $\"__PATH__=($env.PATH | str join (char esep))\"; echo $\"__OPENCODE_BINARY__=($env.OPENCODE_BINARY? | default '')\"".to_string(), + ], "bash" => vec![ "-lic".to_string(), "source ~/.bashrc 2>/dev/null; echo \"__PATH__=$PATH\"; echo \"__OPENCODE_BINARY__=$OPENCODE_BINARY\"".to_string(), diff --git a/packages/vscode/src/opencode.ts b/packages/vscode/src/opencode.ts index 17942343..cac0cf3e 100644 --- a/packages/vscode/src/opencode.ts +++ b/packages/vscode/src/opencode.ts @@ -78,8 +78,16 @@ function getLoginShellPath(): string | null { } const shell = process.env.SHELL || '/bin/zsh'; + const shellName = path.basename(shell); + + // Nushell requires different flag syntax and PATH access + const isNushell = shellName === 'nu' || shellName === 'nushell'; + const args = isNushell + ? ['-l', '-i', '-c', '$env.PATH | str join (char esep)'] + : ['-lic', 'echo -n "$PATH"']; + try { - const result = spawnSync(shell, ['-lic', 'echo -n "$PATH"'], { + const result = spawnSync(shell, args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], }); @@ -144,7 +152,13 @@ function resolveCliPath(): string | null { for (const shellPath of shellCandidates) { if (!isExecutable(shellPath)) continue; try { - const result = spawnSync(shellPath, ['-lic', 'command -v opencode'], { + const shellName = path.basename(shellPath); + const isNushell = shellName === 'nu' || shellName === 'nushell'; + const args = isNushell + ? ['-l', '-i', '-c', 'which opencode'] + : ['-lic', 'command -v opencode']; + + const result = spawnSync(shellPath, args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], }); diff --git a/packages/web/server/index.js b/packages/web/server/index.js index 08484718..e9bed59a 100644 --- a/packages/web/server/index.js +++ b/packages/web/server/index.js @@ -552,8 +552,16 @@ function getLoginShellPath() { } const shell = process.env.SHELL || '/bin/zsh'; + const shellName = path.basename(shell); + + // Nushell requires different flag syntax and PATH access + const isNushell = shellName === 'nu' || shellName === 'nushell'; + const args = isNushell + ? ['-l', '-i', '-c', '$env.PATH | str join (char esep)'] + : ['-lic', 'echo -n "$PATH"']; + try { - const result = spawnSync(shell, ['-lic', 'echo -n "$PATH"'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }); + const result = spawnSync(shell, args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }); if (result.status === 0 && typeof result.stdout === 'string') { const value = result.stdout.trim(); if (value) {