Prerequisites
Install Method
Docker (docker compose up)
Operating System
Linux
Steps to Reproduce
- Add a remote Linux server to Cookbook whose user's login shell is fish (e.g. a stock CachyOS/Arch desktop where the user chose fish) — Settings → Servers, key installed, Check green.
- Try Cookbook → Dependencies → install a system package (e.g. tmux) on that server; or start any model download/serve targeting it; or just open Dependencies and look at the system rows.
Expected Behaviour
Remote Cookbook operations work regardless of the target user's login shell — the shell snippets Cookbook sends should run under a POSIX shell explicitly.
Actual Behaviour
Every remote operation that sends a POSIX shell snippet fails, because sshd hands the remote command line to the target user's login shell and fish cannot parse POSIX constructs (VAR=value assignments, export, if …; then; set -e is even a valid fish command that erases a variable instead of enabling errexit). Concretely:
- System dependency install (
/api/cookbook/install-system-deps) fails with fish: Unsupported use of '='. In fish, please use 'set BREW "$(command -v brew …)"' — the script never runs.
- Binary probes (
_remote_binary_available, the system-prereq probe behind /api/cookbook/packages) use a PATH="…"; prefix, so they error and report tmux/every prereq as missing regardless of reality — installing the package doesn't help, the row stays red.
- tmux launch/status/kill chains (
_remote_tmux_command, _remote_tmux_launch_command, the frontend _tmuxCmd/kill/alive builders and the capture-pane status poll) all use PATH=/ODYSSEUS_TMUX=$(…) prefixes → downloads/serves to such a host fail to launch, and running tasks show no output/status because the poll command itself errors.
- The GPU probe's shell-fallback chain (
if command -v sh …; then sh -lc …; elif bash …) is itself POSIX-only syntax, so it dies on fish before reaching any of its fallbacks.
- Package probes with venv activation (
. …/bin/activate && python3 -c …) and the llama-server PATH probe (export PATH=…) fail the same way.
Affected files: routes/shell_routes.py, routes/cookbook_routes.py, routes/cookbook_helpers.py, routes/codex_routes.py, src/tools/cookbook.py, static/js/cookbook.js, static/js/cookbookRunning.js, static/js/cookbookDownload.js.
Logs / Screenshots
UI toast when installing tmux via Dependencies on a fish-shell server:
System dependency install failed: fish: Unsupported use of '='. In fish, please use 'set BREW "$(command -v brew 2>/dev/null || true)"' set -e; BREW="$(command -v brew 2>/dev/null || true)"; if [ -z "$BREW" ] && [ -x /opt/homebrew/bin/brew ]; then BREW=/opt/homebrew/bin/brew; fi; if [ -z "$BREW" ] && [ -x /usr/local/bin/brew ]; the
Minimal reproduction of the class of failure (fish standing in for the remote login shell, exactly what sshd invokes):
$ fish -c 'PATH="/x:$PATH"; command -v tmux'
fish: Unsupported use of '='. In fish, please use 'set PATH "/x:$PATH"'
$ fish -c 'sh -c '\''PATH="/x:$PATH"; command -v tmux'\'''
/usr/bin/tmux
Model / Backend (if relevant)
No response
Are you willing to submit a fix?
Yes — I can open a PR
Additional Information
Fix ready as a PR: wrap every remote POSIX snippet as sh -c '<snippet>' — a simple command that bash/zsh/fish/csh all parse identically — via a shared posix_remote_shell_cmd() helper (backend) and an _shWrap/_sshCmd equivalent (frontend, with the two quoting layers the local-shell → ssh → remote-shell path needs). Verified end-to-end against a real fish-shell CachyOS server: deps install, prereq probes, venv-based pip install, and tmux launch/status all work; the regression test includes a live fish round-trip reproducing the unwrapped failure.
Prerequisites
devbranch (the default branch you get on clone, where fixes land first) and the bug still reproduces there. Pleasegit pullthe latestdevbefore filing.Install Method
Docker (docker compose up)
Operating System
Linux
Steps to Reproduce
Expected Behaviour
Remote Cookbook operations work regardless of the target user's login shell — the shell snippets Cookbook sends should run under a POSIX shell explicitly.
Actual Behaviour
Every remote operation that sends a POSIX shell snippet fails, because sshd hands the remote command line to the target user's login shell and fish cannot parse POSIX constructs (
VAR=valueassignments,export,if …; then;set -eis even a valid fish command that erases a variable instead of enabling errexit). Concretely:/api/cookbook/install-system-deps) fails withfish: Unsupported use of '='. In fish, please use 'set BREW "$(command -v brew …)"'— the script never runs._remote_binary_available, the system-prereq probe behind/api/cookbook/packages) use aPATH="…";prefix, so they error and report tmux/every prereq as missing regardless of reality — installing the package doesn't help, the row stays red._remote_tmux_command,_remote_tmux_launch_command, the frontend_tmuxCmd/kill/alive builders and the capture-pane status poll) all usePATH=/ODYSSEUS_TMUX=$(…)prefixes → downloads/serves to such a host fail to launch, and running tasks show no output/status because the poll command itself errors.if command -v sh …; then sh -lc …; elif bash …) is itself POSIX-only syntax, so it dies on fish before reaching any of its fallbacks.. …/bin/activate && python3 -c …) and the llama-server PATH probe (export PATH=…) fail the same way.Affected files:
routes/shell_routes.py,routes/cookbook_routes.py,routes/cookbook_helpers.py,routes/codex_routes.py,src/tools/cookbook.py,static/js/cookbook.js,static/js/cookbookRunning.js,static/js/cookbookDownload.js.Logs / Screenshots
Model / Backend (if relevant)
No response
Are you willing to submit a fix?
Yes — I can open a PR
Additional Information
Fix ready as a PR: wrap every remote POSIX snippet as
sh -c '<snippet>'— a simple command that bash/zsh/fish/csh all parse identically — via a sharedposix_remote_shell_cmd()helper (backend) and an_shWrap/_sshCmdequivalent (frontend, with the two quoting layers the local-shell → ssh → remote-shell path needs). Verified end-to-end against a real fish-shell CachyOS server: deps install, prereq probes, venv-based pip install, and tmux launch/status all work; the regression test includes a live fish round-trip reproducing the unwrapped failure.