feat(web): default panel layout for new project chats - #6100
pranav100000 wants to merge 7 commits into
Conversation
Adds two client settings under Settings -> General, both off by default: "Open files panel in new chats" and "Open terminal in new chats". When on, a new chat in a project opens with the files panel and/or the terminal drawer already visible instead of a bare chat column. The defaults are seeded at chat creation, keyed by the draft's pre-allocated thread ref, so the layout survives the draft -> thread promotion on first send. A chat that already has panel state keeps it, so a panel the user deliberately closed is never re-opened.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9e7395910b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| applyNewThreadPanelDefaults( | ||
| scopeThreadRef(projectRef.environmentId, threadId), | ||
| getClientSettings(), | ||
| ); |
There was a problem hiding this comment.
Apply defaults to every new-chat creation path
When preparing a pull request must allocate a fresh draft (ChatView.tsx:1906-1918) or Implement Plan directly creates and navigates to a new thread (ChatView.tsx:5654-5731), neither path invokes useNewThreadHandler, so enabled panel defaults remain closed despite the setting promising to affect every new project chat. Apply the defaults from a shared initializer used by these creation paths rather than only here.
AGENTS.md reference: AGENTS.md:L67-L69
Useful? React with 👍 / 👎.
| // "New chat" hands back an unused draft rather than minting one whenever it | ||
| // can, so the defaults must never re-force a layout: whatever that draft | ||
| // already has wins, including a panel the user deliberately closed. | ||
| if (hasPanelState(threadRef)) return; |
There was a problem hiding this comment.
Remember fully closed layouts before reapplying defaults
When an empty draft's files tab is the only surface and the user closes that tab or chooses Close All, rightPanelStore.updateThread removes the resulting all-closed entry; therefore hasPanelState returns false, and invoking New Chat again for the reusable draft reopens the panel the user deliberately closed. Preserve an explicit initialized/closed marker instead of treating absence as proof that defaults were never applied.
AGENTS.md reference: AGENTS.md:L73-L73
Useful? React with 👍 / 👎.
ApprovabilityVerdict: Needs human review This PR introduces new user-facing settings that change default panel behavior when creating new chats. Multiple unresolved review comments identify edge cases around hydration timing, persistence across reloads, and environment remapping where the implementation may not behave as expected. These gaps in a new feature warrant human review. You can customize Macroscope's approvability policy. Learn more. |
Both panel stores drop a thread's entry once its layout returns to the all-closed default, so store contents alone could not tell an untouched draft from one the user had emptied on purpose: pressing "new chat" again reused that draft and re-opened the panel the user just closed. Decide the defaults once per chat and remember that decision, and count a suppressed terminal id — the only trace left when the last terminal is closed — as a layout the user has already shaped.
Checking out a pull request into a chat, implementing a plan in a fresh thread, and reusing the draft already on screen each hand the user a new chat without going through the path that seeds the layout, so the setting appeared to do nothing there. Route all of them through the same defaults, which still leave a chat that has a layout alone.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9560bb82b5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // The chats this defaulting has already decided on. Both stores drop a thread's | ||
| // entry once its layout returns to the all-closed default, so store contents | ||
| // alone cannot tell an untouched chat from one the user emptied on purpose. | ||
| const decidedThreadKeys = new Set<string>(); |
There was a problem hiding this comment.
Persist the all-closed decision across reloads
When an enabled default is applied to a reusable empty draft, the user closes every panel, and then reloads the app, both panel stores persist the all-closed state as no entry while this module-level set is reset; pressing New Chat for that persisted draft therefore reopens a panel the user deliberately closed. The fresh evidence in this revision is that the attempted fix records the decision only in the in-memory decidedThreadKeys set, so it still needs a durable initialized/closed marker associated with the persisted draft.
AGENTS.md reference: AGENTS.md:L73-L73
Useful? React with 👍 / 👎.
| applyNewThreadPanelDefaults( | ||
| scopeThreadRef(projectRef.environmentId, emptyStoredDraftThread.threadId), | ||
| getClientSettings(), |
There was a problem hiding this comment.
Wait for client-settings hydration before defaulting
Immediately after startup, before asynchronous client-settings hydration completes, getClientSettings() still returns DEFAULT_CLIENT_SETTINGS, with both new options false. Because the new-chat UI is not gated on hydration, opening or reusing a draft during that window causes applyNewThreadPanelDefaults to return without applying the persisted opt-ins, and nothing retries after hydration, leaving that first chat with the wrong layout.
Useful? React with 👍 / 👎.
| <SettingsRow | ||
| {...searchableSetting("new-thread-open-files")} | ||
| description="Start every new chat in a project with the files panel already open." |
There was a problem hiding this comment.
Document the new chat-layout settings
This exposes two user-visible settings that change the initial layout of every project chat, but a repo-wide search finds no corresponding addition under docs/user/. Add shipped-product documentation describing these preferences and their defaults so the behavior is documented in the required audience-specific location.
AGENTS.md reference: AGENTS.md:L75-L75
Useful? React with 👍 / 👎.
Client settings hydrate asynchronously and read as the defaults — both new-chat panels off — until that lands. The index route opens its draft as soon as projects load, well inside that window, so the first chat of a session was decided against settings that had not been read yet and nothing revisited it. Give the defaulting its own hydrated read instead of a snapshot handed in by each caller, so no call site can take the decision too early. Also record why the once-per-chat decision is kept in memory rather than persisted: an emptied layout leaves nothing behind in either store to begin with, so a durable marker would have to be threaded through the persisted composer draft schema to buy anything.
Two settings now change how every new chat in a project opens, with nothing under docs/user describing them.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 00583cff49
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // window, so reading the snapshot directly would skip the first chat of the | ||
| // session and never come back to it. | ||
| const settings = await getHydratedClientSettings(); | ||
| if (!settings.newThreadOpenFilesPanel && !settings.newThreadOpenTerminal) return; |
There was a problem hiding this comment.
Record the layout decision when both defaults are disabled
When a draft is first opened while both preferences are off, this early return leaves its key out of decidedThreadKeys. If the user later enables a preference and New Chat reuses that same empty draft, the helper now opens the panel in an already-existing chat; this is also inconsistent with drafts first opened with either preference enabled, which are permanently marked as decided. Record the thread key before returning so every initial layout, including all-closed, is decided once per chat.
Useful? React with 👍 / 👎.
A draft first opened while both panel defaults were off returned before it was recorded in decidedThreadKeys, so enabling a default and reusing that same unused draft opened a panel in an already-on-screen chat — unlike a draft first opened with a default on, which is marked decided. Mark the decision before the all-closed early return so every initial layout is decided once per chat. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…anel-defaults-5676 # Conflicts: # docs/README.md
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1b0dbfa. Configure here.
| if (decidedThreadKeys.has(threadKey)) return; | ||
| decidedThreadKeys.add(threadKey); | ||
| if (!settings.newThreadOpenFilesPanel && !settings.newThreadOpenTerminal) return; | ||
| if (hasPanelState(threadKey)) return; |
There was a problem hiding this comment.
Remap reopens closed panels
Medium Severity
decidedThreadKeys and hasPanelState key off the full scoped thread ref, including environmentId. Reusing a draft while remapping it to another physical member of a logical project calls applyNewThreadPanelDefaults with the new environment, so prior close/decision evidence under the old key is invisible and defaults can reopen panels the user already closed.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 1b0dbfa. Configure here.
|
thanks for the contribution! closing this at the request of @StiensWout because it currently has merge conflicts. if you think closing this was a mistake, please feel free to reopen it. |


What Changed
New project chats open with a configurable default panel layout (files panel and/or terminal) instead of a bare chat column. The defaults are set in Settings, applied once per chat across the new-chat creation paths, and never re-force a panel the user has deliberately closed.
Why
Closes #5676. Every new chat starts blank; users who always want the files panel or a terminal had to open them by hand each time.
UI Changes
With the two toggles enabled in Settings, a new chat opens with the files panel and terminal already open:
Checklist
Note
Medium Risk
Touches core new-chat creation flows and panel/terminal UI stores with subtle once-per-chat draft-reuse logic. Defaults stay off and behavior is client-local, so blast radius is limited but edge cases around reused drafts matter.
Overview
Adds client settings so new project chats can open with the files panel and/or terminal already visible, instead of a bare chat column. Both toggles default off and live under Settings → General.
Introduces
applyNewThreadPanelDefaults, which waits for hydrated settings and applies the layout once per chat. It skips chats that already have panel state (including deliberately closed panels) and reused drafts, so enabling a preference later does not reshape chats already on screen.The helper is wired into the main new-thread path, PR checkout drafts, and plan-implementation chats. Includes settings search/reset support, user docs, and coverage for hydration and draft-reuse edge cases.
Reviewed by Cursor Bugbot for commit 1b0dbfa. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add default panel layout settings for new project chats
newThreadOpenFilesPanel,newThreadOpenTerminal) that control whether the files panel and/or terminal open automatically when a new chat is created.applyNewThreadPanelDefaults, which applies these defaults once per thread per session, skipping threads that already have panel state or were previously decided.ChatView.tsxanduseHandleNewThread.tsso all new-chat code paths are covered.Macroscope summarized 1b0dbfa.