Repository navigation
Description
Summary
/cd ~ in the TUI expands ~ against the client's home directory before
sending it to the server. When a macOS client attaches to a Linux server, the
tilde becomes /Users/<user>, which does not exist server-side, so the
directory change fails with Location not found: /Users/<user>.
Same class as #47665 (client-side path resolution while attached to a remote
server), but hit through the /cd slash command's tilde expansion rather than
the positional directory argument.
Environment
- opencode version: 2.0.26 (branch
v2) - OS: macOS client → Linux server
- Attach:
opencode --server https://<server>(TUI attached to remoteopencode serve) - Active plugins: none
Reproduction
- Start the server on Linux:
opencode serve(reachable from the client). - Attach from the macOS client:
opencode --server https://<server>. - On the TUI home screen (no session yet), run:
/cd ~ - Observe failure: "Failed to change directory — Location not found:
/Users/". The tilde was expanded to the client's home.
Expected Behavior
~ expands according to the server's home (e.g. /home/<user>), since the
server owns the filesystem the location refers to.
Actual Behavior
- No active session: the client pre-expands
~→/Users/<user>and sends
that absolute path inlocation.get. The server uses the query parameter
verbatim (no server-side tilde expansion on this endpoint), so Linux tries to
boot a location at/Users/<user>and fails. - With an active session:
session.movesends the raw~and the server
expands it correctly with its own home — the move works. But the client still
records its locally-expanded/Users/...path into directory recents. - Autocomplete is also affected: typing
/cd ~/lists the client's home
(viafile.liston the wrong absolute path), producing empty/failed results.
Additional Context
Root cause — packages/tui/src/component/prompt/index.tsx (~line 279), the
session.cd command handler:
const expanded =
value === "~" ? paths.home : value.startsWith("~/") ? path.join(paths.home, value.slice(2)) : valuepaths.home resolves through TuiPathsProvider (packages/tui/src/app.tsx,
home: global.home) to os.homedir() of the client process
(packages/util/src/global.ts). The expanded path is then sent to
location.get, whose server-side middleware (requestRef in
packages/server/src/location.ts) performs no tilde expansion of its own.
The session flow shows the intended split: SessionMove.resolveDestination
(packages/core/src/session/move.ts) expands ~ server-side using the
server's Global.home. location.get lacks the equivalent, and the TUI
expands too early regardless.
Secondary affected sites (same client-home source):
- directory autocomplete: packages/tui/src/component/prompt/autocomplete.tsx
passes paths.home into directoryAutocomplete, whose
directoryAutocompleteSearch (packages/tui/src/prompt/directory-completion.ts)
maps//x to the client home before calling file.list - recents: the session branch of the /cd handler records the
client-computed path via directoryRecents.touch
A structural blocker for a clean client-side fix: the server never reports its
home directory. Location.Info (packages/schema/src/location.ts) carries only
directory/project, so clients have no authoritative home to expand against.
Possible directions:
- Expand ~ server-side in the location middleware (mirroring
SessionMove.resolveDestination), letting the TUI send raw input on the
no-session path — consistent with how session.move already behaves. - Expose the server's home (e.g. a home field on location.get) so TUI
autocomplete and display can use the correct root client-side.
Related: cli(v2): positional directory resolved locally even with --server, fails on remote-only paths #47665 (same class, CLI positional directory), Desktop: project picker sends host paths to a remote server, and the resulting failure is silent #44150 (Desktop project
picker sends host paths), TUI referencing local directory when using attach --dir to connect to a remote server. #5380 / TUI sends absolute local paths causing ENOENT on server side #4686 / attach: @ file mentions use client-local path instead of remote directory #13732 (closed V1 cousins of the
family).
Activity
opencode-agent commentedon Oct 13, 2026
Thanks for the detailed report! I reproduced this on 2.0.26, and it still happens on the latest
dev(23e3493).To get a client with a different home directory than the server, I started the attached TUI (
--server <url>) with a separate home. On the home screen with no session:/cd ~/makes the directory autocomplete show "Could not search directories. Keep typing to try again."/cd ~fails withFailed to change directory — Location not found: <client home>.The recording and screenshots below show this, and the script below reproduces it. On
dev, the/cdhandler still replaces~with the client's home before callinglocation.get, and the server doesn't expand~on that endpoint. I only tested the case without a session; I didn't check the recents behaviour you describe for/cdinside an active session.Related issues:
--serverrecording.mp4
Reproduction script (drive.ts)
Run it with opencode-drive:
opencode-drive run ./drive.ts. It drivesopencodefrom yourPATH; setOC_DEVto the path of an OpenCode checkout to run that from source instead.