Skip to content

TUI renders blank responses when launched from a symlinked directory #16528

Closed

Description

@cristianmiranda

Description

When opencode is launched from a symlinked directory that contains a git repo (e.g. ~/dotfiles -> /real/path/dotfiles), the TUI shows blank responses. The model processes messages correctly (verified via opencode run and opencode export), but the TUI chat area remains empty.

The bug only occurs when the symlinked directory is a git repository. Symlinks to non-git directories work fine, since there's no git toplevel resolution to create a path mismatch.

Root cause: the TUI main thread resolves the directory from process.env.PWD (preserves the symlink path), while the worker uses process.cwd() (returns the physical/canonical path). Since Instance and Bus are keyed by directory string, this creates two separate instances. Events published by the main thread's instance never reach the worker's SSE subscription, so the TUI store never receives message updates.

  • thread.ts:114 — uses process.env.PWD → /home/user/dotfiles
  • worker.ts:98 — uses process.cwd() → /home/user/Documents/.../dotfiles

When both resolve to the same path (launching from the real path), everything works.

opencode_bug.mp4

Plugins

@mohak34/opencode-notifier, cursor-opencode-auth

OpenCode version

1.2.21

Steps to reproduce

  1. Create a symlinked directory pointing to a git repo: ln -s /real/path/myrepo ~/myrepo
  2. cd ~/myrepo
  3. Run opencode (TUI mode)
  4. Send any message (e.g. "hi")
  5. Observe blank response area — no text rendered
  6. Verify the model did respond: opencode export <session-id> shows the assistant message

Running from the real path (cd /real/path/myrepo && opencode) works correctly.

Note: Symlinks to directories without a git repo work fine — the bug requires a git repository to be present in the target directory.

Operating System

Arch Linux (x86_64)

Terminal

Alacritty

Activity

  1. github-actions commented on Mar 7, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Please review those issues and consider closing this one if they cover your case, or add any additional context that differs.

  2. added a commit that references this issue on Mar 7, 2026
    d1fd8d4
  3. mindcrime commented on Mar 8, 2026

    @mindcrime

    FWIW, I'm experiencing what appears to be the same issue, BUT... in my case, the presence of absence of a Git repo makes no difference in the OpenCode behavior. I simply see the case where:

    1. If I launch OpenCode from a symlinked directory, responses are not rendered in the session (but if you exit out and then resume the session, it appears that those responses are in the session history)
    2. If I launch OpenCode in the same directory, but using the real path, it works fine.

    This is all on PopOS 22.04 LTS and using OpenCode 1.2.21.

  4. cristianmiranda commented on Mar 8, 2026

    @cristianmiranda
    Author

    FWIW, I'm experiencing what appears to be the same issue, BUT... in my case, the presence of absence of a Git repo makes no difference in the OpenCode behavior. I simply see the case where:

    1. If I launch OpenCode from a symlinked directory, responses are not rendered in the session (but if you exit out and then resume the session, it appears that those responses are in the session history)
    2. If I launch OpenCode in the same directory, but using the real path, it works fine.

    This is all on PopOS 22.04 LTS and using OpenCode 1.2.21.

    Looks like this fix would cover that exact scenario 🙌🏽

  5. prolific commented on Mar 8, 2026

    @prolific

    Yes, I am also facing exactly the same issue where not seeing any responses in TUI when opened inside symlinked directory.

  6. jyapayne commented on Mar 8, 2026

    @jyapayne

    I am also facing the same issue. In this case, I am on Aurora Linux, which symlinks the entire home directory, so opencode doesn't work anywhere.

    Here is some more info:

    Bug Description

    On Fedora Atomic desktops (Silverblue, Aurora, Bazzite, etc.), /home is a symlink to /var/home. Starting in v1.2.21, the TUI renders blank assistant responses — the agent header appears but no response text is shown. The backend works correctly (LLM responses are received and stored in the database).

    Root Cause

    The v1.2.21 changes to thread.ts and server.ts introduced Filesystem.resolve() for directory path handling. On Linux, Filesystem.resolve() calls path.resolve(), which does not follow symlinks. This creates a path mismatch:

    • process.env.PWD = /home/joey (the symlink path, set by the shell)
    • process.cwd() = /var/home/joey (the real path, because the kernel resolves symlinks on chdir)

    In thread.ts (line 114):

    const root = Filesystem.resolve(process.env.PWD ?? process.cwd())
    // → path.resolve("/home/joey") → "/home/joey"

    This /home/joey path is passed as directory to the SDK client, which sends it as the x-opencode-directory header. But elsewhere in the server pipeline, process.cwd() returns /var/home/joey, causing a mismatch between the TUI's directory context and the server's instance directory. Events are published under one path but the TUI is listening under the other.

    Reproduction

    1. Use any Linux distro where /home is a symlink (e.g., Fedora Atomic: /home → var/home)
    2. Run opencode v1.2.21
    3. Send any message
    4. The agent header appears but the response text is blank
    5. The response IS stored in the sqlite database — only the TUI rendering fails

    Workarounds

    • Set PWD to the real path: PWD=/var/home/joey opencode works
    • Add export PWD=$(realpath "$PWD") to shell rc
    • Downgrade to v1.2.20

    Suggested Fix

    Filesystem.resolve() on Linux should follow symlinks (e.g., use fs.realpathSync) rather than just path.resolve(), which only normalizes path segments without resolving symlinks. Alternatively, thread.ts could use process.cwd() instead of process.env.PWD since process.cwd() always returns the canonical path.

    Version Info

    • Works: v1.2.20
    • Broken: v1.2.21
    • Platform: Fedora Aurora 43 (Fedora Atomic), Linux 6.18.7
    • Terminals tested: Ghostty 1.2.3, Ptyxis (both affected)

    Bisection

    The regression was introduced in the v1.2.20→v1.2.21 release. The relevant commits that changed path handling:

    • server.ts: Added Filesystem.resolve() wrapper around directory in middleware
    • thread.ts: Changed process.env.PWD ?? process.cwd() to Filesystem.resolve(process.env.PWD ?? process.cwd())
    • instance.ts: Added Filesystem.resolve(input.directory) in Instance.provide()
  7. cristianmiranda commented on Mar 8, 2026

    @cristianmiranda
    Author

    I am also facing the same issue. In this case, I am on Aurora Linux, which symlinks the entire home directory, so opencode doesn't work anywhere.

    Here is some more info:

    Bug Description

    On Fedora Atomic desktops (Silverblue, Aurora, Bazzite, etc.), /home is a symlink to /var/home. Starting in v1.2.21, the TUI renders blank assistant responses — the agent header appears but no response text is shown. The backend works correctly (LLM responses are received and stored in the database).

    Root Cause

    The v1.2.21 changes to thread.ts and server.ts introduced Filesystem.resolve() for directory path handling. On Linux, Filesystem.resolve() calls path.resolve(), which does not follow symlinks. This creates a path mismatch:

    • process.env.PWD = /home/joey (the symlink path, set by the shell)
    • process.cwd() = /var/home/joey (the real path, because the kernel resolves symlinks on chdir)

    In thread.ts (line 114):

    const root = Filesystem.resolve(process.env.PWD ?? process.cwd())
    // → path.resolve("/home/joey") → "/home/joey"

    This /home/joey path is passed as directory to the SDK client, which sends it as the x-opencode-directory header. But elsewhere in the server pipeline, process.cwd() returns /var/home/joey, causing a mismatch between the TUI's directory context and the server's instance directory. Events are published under one path but the TUI is listening under the other.

    Reproduction

    1. Use any Linux distro where /home is a symlink (e.g., Fedora Atomic: /home → var/home)
    2. Run opencode v1.2.21
    3. Send any message
    4. The agent header appears but the response text is blank
    5. The response IS stored in the sqlite database — only the TUI rendering fails

    Workarounds

    • Set PWD to the real path: PWD=/var/home/joey opencode works
    • Add export PWD=$(realpath "$PWD") to shell rc
    • Downgrade to v1.2.20

    Suggested Fix

    Filesystem.resolve() on Linux should follow symlinks (e.g., use fs.realpathSync) rather than just path.resolve(), which only normalizes path segments without resolving symlinks. Alternatively, thread.ts could use process.cwd() instead of process.env.PWD since process.cwd() always returns the canonical path.

    Version Info

    • Works: v1.2.20
    • Broken: v1.2.21
    • Platform: Fedora Aurora 43 (Fedora Atomic), Linux 6.18.7
    • Terminals tested: Ghostty 1.2.3, Ptyxis (both affected)

    Bisection

    The regression was introduced in the v1.2.20→v1.2.21 release. The relevant commits that changed path handling:

    • server.ts: Added Filesystem.resolve() wrapper around directory in middleware
    • thread.ts: Changed process.env.PWD ?? process.cwd() to Filesystem.resolve(process.env.PWD ?? process.cwd())
    • instance.ts: Added Filesystem.resolve(input.directory) in Instance.provide()

    You can try out the fix in my PR and see how that goes.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions