Skip to content

Fix script discovery and output handling on Windows (WSL + Git Bash)#43

Open
mike-thompson-day8 wants to merge 2 commits into
marimo-team:mainfrom
mike-thompson-day8:fix-windows-discovery-and-sse-crlf
Open

Fix script discovery and output handling on Windows (WSL + Git Bash)#43
mike-thompson-day8 wants to merge 2 commits into
marimo-team:mainfrom
mike-thompson-day8:fix-windows-discovery-and-sse-crlf

Conversation

@mike-thompson-day8
Copy link
Copy Markdown

Fixes #42.

Two related bugs hit users on Windows-hosted bash environments where marimo runs natively on Windows but the agent scripts run under a non-MSYS bash. Both are scoped to scripts/discover-servers.sh and scripts/execute-code.sh.

Bug 1 — discovery picks the wrong registry path under WSL

Both scripts only treat OSTYPE=msys*/cygwin* as Windows. Under WSL pointed at a Windows-native marimo install, OSTYPE=linux-gnu and the scripts read ~/.local/state/marimo/servers, missing the real registry at $USERPROFILE\.marimo\servers.

Fix: probe a candidate list — XDG path, ~/.marimo/servers, and (if $USERPROFILE is set) a wslpath/cygpath translation of it — and pick the first directory that has registry files. The is_windows flag (used to decide between kill -0 and an HTTP /health probe for liveness) is now inferred from whether the chosen path matches */.marimo/servers, since that's what determines whether the registered PIDs are Windows-native.

Bug 2 — SSE parser silently drops every event on Windows

execute-code.sh reads the event stream with IFS= read -r line and matches event: / data: literally. marimo's HTTP server emits CRLF terminators per the SSE spec; read -r strips only the LF, so the trailing \r keeps every literal-prefix pattern from matching on Git Bash and WSL. Result: stdout / stderr / done events are all dropped — the user sees no output even though the code ran.

Fix: one-line line="${line%$'\r'}" right after the read. Cheap to do unconditionally; works the same on POSIX systems (no CR to strip).

Testing

  • bash -n on both scripts (clean).
  • On Windows 11 / Git Bash with a live --no-token marimo session: discover-servers.sh finds the running server, and execute-code.sh -c "print(1+1)" returns its output correctly.
  • I haven't tested the WSL path translation on a real WSL system — would appreciate a check there. The logic is: if $USERPROFILE is set and wslpath -u (or cygpath -u) is on PATH, append the translated <USERPROFILE>/.marimo/servers as a candidate.

Notes

No behaviour change on Linux/macOS native: the XDG path is checked first and remains the only candidate that has files there. The Windows-native ~/.marimo/servers path is checked second and is only selected when it actually contains a registry file. Falling through to "no registry found" early-returns [] from discover-servers.sh exactly as before.

Two related bugs hit users on Windows-hosted bash environments where
marimo runs natively on Windows but the agent scripts run under a
non-MSYS bash:

1. discover-servers.sh and execute-code.sh only treat OSTYPE=msys*/cygwin*
   as Windows. Under WSL pointed at a Windows-native marimo install,
   OSTYPE=linux-gnu and the scripts read ~/.local/state/marimo/servers,
   missing the real registry at $USERPROFILE\.marimo\servers. Fix: probe
   a candidate list (XDG path, ~/.marimo/servers, and a wslpath/cygpath
   translation of $USERPROFILE if available), pick the first that holds
   registry files, and infer is_windows from the chosen path rather than
   from OSTYPE.

2. The SSE parser in execute-code.sh reads with `IFS= read -r line` and
   matches "event:" / "data:" literally. marimo's server emits CRLF
   terminators per the SSE spec; `read -r` strips only the LF, so the
   trailing \r makes none of the case branches match on Git Bash *or*
   WSL. Result: stdout/stderr/done events are silently dropped — the
   user sees no output even though the code ran. Fix: strip the trailing
   \r from each line before the case match.

Tested on Windows 11 / Git Bash with a live marimo session: discovery
finds the running server, and `execute-code.sh -c "print(1+1)"` returns
its output correctly.
Copilot AI review requested due to automatic review settings May 1, 2026 13:07
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Windows-hosted bash environment issues when marimo runs natively on Windows but the helper scripts run under Git Bash/WSL, improving both server discovery and SSE output parsing.

Changes:

  • Update registry discovery to probe multiple candidate server-registry directories (XDG, ~/.marimo/servers, and translated $USERPROFILE/.marimo/servers) and infer “Windows PID registry” behavior from the selected path.
  • Fix SSE parsing on Windows by trimming trailing \r so event:/data: prefix matching works with CRLF-terminated streams.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
scripts/execute-code.sh Adds multi-path registry discovery and CRLF-safe SSE parsing so stdout/stderr/done events are not dropped on Windows shells.
scripts/discover-servers.sh Adds multi-path registry discovery and updated Windows/native liveness probing behavior to find the correct registry under WSL/Git Bash.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/execute-code.sh Outdated
Comment on lines +85 to +89
servers_dir=""
for d in "${candidates[@]}"; do
if [[ -d "$d" ]] && compgen -G "$d/*.json" >/dev/null 2>&1; then
servers_dir="$d"
break
Comment thread scripts/discover-servers.sh Outdated
Comment on lines +30 to +34
servers_dir=""
for d in "${candidates[@]}"; do
if [[ -d "$d" ]] && compgen -G "$d/*.json" >/dev/null 2>&1; then
servers_dir="$d"
break
Address Copilot's review on the previous commit: picking the first
candidate directory that contains *.json files can lock onto a stale
registry (e.g. leftover XDG entries from a previous WSL-side marimo
run) and never check the candidate that holds the live server.

Walk every candidate, apply per-candidate liveness rules
(`kill -0` for POSIX/XDG, HTTP `/health` probe for Windows-native
`~/.marimo/servers`), and aggregate the live entries. A stale POSIX
registry can no longer shadow a live Windows-native one, and a user
with two live marimos in different registries (rare but possible)
sees both.

Also dedupe candidates by string before iterating: on Git Bash,
$HOME and $(cygpath -u "$USERPROFILE") typically resolve to the
same path (e.g. /c/Users/foo), and without dedupe the same registry
file is walked twice and the same server is listed twice. The
dedupe is a tiny O(n^2) loop — the candidate list never exceeds a
handful — and stays bash 3-compatible.

Verified: on Git Bash with one live marimo, discover-servers.sh
returns a single entry (was returning duplicates pre-dedupe). The
"multiple instances found" path in execute-code.sh now also walks
all candidates so its output matches the count it reports.
@mike-thompson-day8
Copy link
Copy Markdown
Author

Thanks @copilot-pull-request-reviewer — both comments are pointing at the same real bug and I've fixed it in b98d015.

What changed: picking the first candidate directory that contains registry files locks the script onto whichever registry happens to have stale entries first. A user with leftover entries under the XDG path but a live registry at ~/.marimo/servers (or vice versa) would see [] even though a server is running.

The new logic walks every candidate directory, applies per-candidate liveness rules (kill -0 for the POSIX/XDG path; HTTP /health probe for Windows-native ~/.marimo/servers since those PIDs aren't reachable via kill -0 from any Cygwin/MSYS/WSL shell), and aggregates the live entries. A stale POSIX registry can't shadow a live Windows-native one, and a user with two live marimos in different registries gets both listed.

While testing, I also noticed $HOME and $(cygpath -u "$USERPROFILE") typically resolve to the same string on Git Bash (e.g. /c/Users/foo), which would otherwise count the same live server twice. Added a tiny string-dedupe before the main loop to handle that. Verified on Git Bash with one live marimo: discover-servers.sh now returns a single entry, and the "multiple instances found" branch in execute-code.sh walks the same aggregate set so its listing matches the count it reports.

I have not been able to verify on a real WSL system — same caveat as before. The wslpath -u "$USERPROFILE" translation logic is unchanged; only the iteration shape moved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scripts fail on Windows under WSL; SSE parser drops output on Git Bash & WSL

2 participants