fix(windows): path handling fixes for Windows
Summary
This fix solves a whole series of bugs, resulting from filepath issues with backslashes occuring on Windows.
→ Solution: normalize all internal paths to forward slashes using centralized Filesystem wrappers
Why this works: all win32 shells work with forward slash paths, this is de-facto industry standard (git, vscode, cmake, ... all use this pattern)
Observed issues
❌ git rev-parse --show-toplevel returns E:/x/y forward slash format → worktree/directory mismatch
❌ path.resolve(), path.relative(), realpathSync.native(), realpath (bash) break with git bash paths (various issues)
❌ /d/x within C drive (/c/) results in things like C:\d\x
❌ relative paths not working like expected using cross-drive
❌ contains logic not working → issues with permission system and external_directory
❌ /tmp inside git bash is something else outside of it
❌ tools break using backslash paths (some backslashes get "eaten")
❌ escaping hell for agents → requires double/quadruple escaping
❌ observed in all win32 native shells (git bash, cmd, powershell/pwsh)
❌ few issues in app/desktop (wrong filepath splits/usage)
Tested with fix
✅ local test suite succeeds now with 100% (bun test in packages/opencode)
✅ all possible path variants (C:\a\b, C:/a/b, /c/a/b, /cygdrive/c/a/b) are normalized into C:/a/b format
✅ full functionality of all tools (ENOENT errors gone, permissions, relative paths, external directory, LSP)
✅ worktree/sandbox handling correct
✅ tested TUI and desktop
How to reproduce/test
- test suite
- running prompts with various problematic/mixed filepaths (see attached md example)
Notes
A few more places would require normalization - but they're unused/dead code (should be removed):
-
packages/ui/src/context/sync.tsxline 16absolute() -
packages/ui/src/context/local.tsxline 392, 420, 455, 546 - file tree operations (no file tree used)
Hey! Your PR title (feat) support MSYS forward slashes with experimental flag doesn't follow conventional commit format.
Please update it to start with one of:
-
feat:orfeat(scope):new feature -
fix:orfix(scope):bug fix -
docs:ordocs(scope):documentation changes -
chore:orchore(scope):maintenance tasks -
refactor:orrefactor(scope):code refactoring -
test:ortest(scope):adding or updating tests
Where scope is the package name (e.g., app, desktop, opencode).
See CONTRIBUTING.md for details.
Thanks for your contribution!
This PR doesn't have a linked issue. All PRs must reference an existing issue.
Please:
- Open an issue describing the bug/feature (if one doesn't exist)
- Add
Fixes #<number>orCloses #<number>to this PR description
See CONTRIBUTING.md for details.
This sounds perfect @pschiel
If you can get it ready and finish the cleanup you said I can test and approve.
Btw don't put it behind an experimental flag. We'll ship once it's working.