Skip to content

[Bug]: Running a project action shows the right-panel terminal in the bottom drawer too #14266

Closed

Description

@TonybynMp4

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/web

Steps to reproduce

  1. Open a thread with the bottom terminal drawer closed and empty.
  2. Open a terminal in the right panel. Leave it idle.
  3. Run a project action.

Expected behavior

The action runs in one terminal, and that terminal shows in one place.

Actual behavior

The action runs in the right-panel terminal, and the bottom drawer opens showing that same terminal. You now have one PTY rendered in two places. The drawer's close button kills the shared shell, so there's no way to get rid of the duplicate view without losing the terminal.

Cause

runProjectScript in apps/web/src/components/ChatView.tsx picks its base terminal from terminalUiState.activeTerminalId || activeKnownTerminalIds[0] || DEFAULT_THREAD_TERMINAL_ID. activeKnownTerminalIds comes from every server session for the thread, right-panel terminals included, so an empty drawer lets it pick the panel's terminal. It then calls setTerminalOpen(true). With no drawer terminals, setThreadTerminalOpen in terminalUiStateStore.ts adds "default" to the drawer, which is often the panel terminal's id.

toggleTerminalVisibility already avoids this by allocating a fresh id from allocatableActiveTerminalIds, which excludes panel terminals. The action path skips that step.

Possible fixes

I'd like a maintainer or triage to pick one:

  1. Keep running in the right-panel terminal and don't open the drawer. Focus the panel tab instead. If that terminal is busy, open a new terminal in the panel. The terminal the user placed stays where they put it, and no second shell gets created.
  2. Never reuse a right-panel terminal for actions. Reuse a drawer terminal if one exists, or create a new drawer terminal with an id that doesn't collide with panel terminals. This keeps "actions run in the drawer" as the one rule.

Either way the drawer should stop adopting a terminal id that the right panel owns.

Impact

Minor bug or occasional failure

Version or commit

main @ cdb26fe

Environment

Linux, desktop app

Activity

  1. juliusmarminge commented on Sep 29, 2026

    @juliusmarminge
    Member

    Triage

    Confirmed on current main (d2c9281b, which includes the reported cdb26fe635). Repro holds: empty closed drawer, one idle right-panel terminal, then a project action. The same path runs chat code-block shell commands (runShellCommand calls runProjectScript).

    Two things line up to attach one PTY to both surfaces:

    1. With the drawer empty, activeTerminalId is "", so runProjectScript falls through to activeKnownTerminalIds[0]. That list is every server session for the thread, and the drawer does not filter panel terminals out of it (unlike PersistentThreadTerminalDrawer, which does). The first panel terminal is allocated term-1 by nextTerminalId, so an idle panel session is reused. A busy one is not reused, but that does not avoid the collision below.
    2. setTerminalOpen(true) runs before the target id is applied. An empty drawer makes setThreadTerminalOpen insert DEFAULT_THREAD_TERMINAL_ID, which is "term-1", not "default". The drawer reconcile then refuses to drop it: panel sessions are removed from the drawer’s server list, so [] is treated as a strict subset of ["term-1"] and the id stays. The drawer close button closes that session, so dismissing the duplicate kills the panel shell too.

    toggleTerminalVisibility already avoids this. On an empty drawer it allocates with nextTerminalId(allocatableActiveTerminalIds) (panel ids included, so they are skipped) and calls ensureTerminal instead of setTerminalOpen.

    Prefer the second fix: actions stay in the drawer. Reuse a drawer terminal when one exists; otherwise allocate an id the right panel does not own, and do not let setTerminalOpen claim term-1 while the panel holds it. Keeping the action in the panel and only focusing that tab would also stop the double view, but it would change the existing “actions run in the drawer” behavior for the common case.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Sep 29, 2026
  3. added 2 commits that reference this issue on Sep 29, 2026
    ca923c6
    6aa034a
  4. added 3 commits that reference this issue on Oct 13, 2026
    ea36b5a
    628408e
    81ce800
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions