Repository navigation
refactor(web): chat shortcuts live with the hooks that own their actions - #23097
Merged
juliusmarminge merged 1 commit intoOct 21, 2026
Conversation
juliusmarminge
added this pull request to stack #23098
October 21, 2026 21:07
Terminal, right panel, thread lifecycle and composer chords move next to the code they drive; useChatShortcuts reads its input through effect events instead of a layout-effect ref. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
juliusmarminge
force-pushed
the
refactor/split3-chatview-shortcuts
branch
from
October 21, 2026 21:26
8eef2f8 to
300d3ce
Compare
juliusmarminge
marked this pull request as ready for review
October 21, 2026 21:30
Contributor
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This PR reorganizes existing chat shortcut handlers into the hooks that own their actions, while preserving the prior permission checks, routing, and keyboard-event behavior. It introduces no new user-facing capability, schema change, product-default change, or static-analysis override. You can add or adjust custom eligibility rules. Learn more. |
Contributor
github-actions Bot
added a commit
to omarcresp/t3code-flake
that referenced
this pull request
Oct 22, 2026
## What's Changed * docs(agents): proof for a bug fix depends on the bug by @juliusmarminge in pingdotgg/t3code#23008 * fix(server): removing a worktree on Windows no longer deletes what its junctions point to by @SunkenInTime in pingdotgg/t3code#21099 * perf(web): a streaming thread re-renders only its own sidebar row by @juliusmarminge in pingdotgg/t3code#22730 * refactor(web): the add environment dialog owns its form state by @juliusmarminge in pingdotgg/t3code#22686 * fix(desktop): use Clerk's upstream fix for abandoned browser sign-ins by @wobsoriano in pingdotgg/t3code#23038 * feat: show automation messages as compact timeline rows by @juliusmarminge in pingdotgg/t3code#22638 * feat(server,web,mobile): approvals in full access say why Claude asked by @juliusmarminge in pingdotgg/t3code#22546 * feat(claude): idle compaction has a global default and per-instance overrides by @juliusmarminge in pingdotgg/t3code#23037 * perf(web): typing no longer re-renders the traits picker or attach button by @juliusmarminge in pingdotgg/t3code#23040 * refactor(web): the composer's layout and provider hooks live in their own files by @juliusmarminge in pingdotgg/t3code#23042 * refactor(web): the prompt stash lives in useComposerStash by @juliusmarminge in pingdotgg/t3code#23046 * refactor(web): composer context imports live in useComposerContextImport by @juliusmarminge in pingdotgg/t3code#23048 * refactor(web): composer file intake lives in useComposerAttachmentIntake by @juliusmarminge in pingdotgg/t3code#23049 * refactor(web): the composer's footer controls render in ComposerControlsBar by @juliusmarminge in pingdotgg/t3code#23058 * refactor(web): composer key handling lives in useComposerCommandKey by @juliusmarminge in pingdotgg/t3code#23060 * refactor(web): ChatView's send paths live in useComposerSend by @juliusmarminge in pingdotgg/t3code#23062 * refactor(web): ChatView's terminal actions live in useChatTerminalActions by @juliusmarminge in pingdotgg/t3code#23063 * refactor(web): ChatView's right panel actions live in useRightPanelActions by @juliusmarminge in pingdotgg/t3code#23064 * refactor(web): ChatView's snooze, settle, and checkout actions live in useThreadLifecycle by @juliusmarminge in pingdotgg/t3code#23065 * refactor(web): ChatView's revert, rollback, and fork live in useTimelineRewind by @juliusmarminge in pingdotgg/t3code#23066 * refactor(web): ChatView's attachment preview handoff lives in useAttachmentPreviewHandoff by @juliusmarminge in pingdotgg/t3code#23067 * refactor(web): ChatView's project clone banner lives in useProjectCloneBanner by @juliusmarminge in pingdotgg/t3code#23068 * refactor(web): ChatView's model, mode, and workspace choices live in useComposerSelection by @juliusmarminge in pingdotgg/t3code#23069 * refactor(web): ChatView's pull request checkout lives in usePullRequestDraftThread by @juliusmarminge in pingdotgg/t3code#23070 * refactor(web): ChatView's thread derivations are tested functions in ChatView.logic by @juliusmarminge in pingdotgg/t3code#23071 * refactor(web): ChatView's paste-to-focus, titlebar controls, and timeline overlays move out by @juliusmarminge in pingdotgg/t3code#23072 * fix(cursor): a closed-stream write in the Cursor SDK no longer stops the server by @t3dotgg in pingdotgg/t3code#22897 * fix(server): Codex no longer offers a one-click update for installs it can't detect by @koushikxd in pingdotgg/t3code#22504 * fix(pi): declare properties on MCP tool schemas that omit them by @tlconde in pingdotgg/t3code#21822 * fix(server): a desktop backend whose launcher died shuts down cleanly instead of crashing by @SunkenInTime in pingdotgg/t3code#22471 * fix(mobile): chat feed no longer re-derives on every render by @t3dotgg in pingdotgg/t3code#22913 * docs(user): the outside agents guide says which addresses agents can sign in over by @Gourav224 in pingdotgg/t3code#22377 * fix(server): HTML preview reports a browser start error instead of an internal error by @t3dotgg in pingdotgg/t3code#22895 * fix(tailscale): a timed-out tailscale probe no longer outlives its call by @t3dotgg in pingdotgg/t3code#22900 * docs(composer): queued messages follow the Follow-up behavior setting by @t3dotgg in pingdotgg/t3code#22857 * fix(server): failed provider updates say why by @koushikxd in pingdotgg/t3code#22506 * test(telemetry): keep fixture PIDs from colliding with the test worker by @only21mil in pingdotgg/t3code#21446 * fix(server): server tests resolve the macOS temp dir symlink by @nabettu in pingdotgg/t3code#21442 * fix(scripts): mobile lint fails instead of passing when ktlint or detekt is missing by @t3dotgg in pingdotgg/t3code#22896 * fix(server): t3_thread_read clamps oversized page sizes instead of failing by @t3dotgg in pingdotgg/t3code#22901 * fix(mobile): opening a pull request no longer crashes with "Maximum update depth exceeded" by @nabettu in pingdotgg/t3code#22600 * fix(web): PR Code tab keeps its files after a refresh with an unchanged diff by @t3dotgg in pingdotgg/t3code#22917 * fix(web): finished provider updates no longer leave a hidden spinner in the sidebar by @t3dotgg in pingdotgg/t3code#22912 * fix(composer): mentions of files like `posts.$postId.tsx` or `[id].tsx` stay chips by @t3dotgg in pingdotgg/t3code#22922 * refactor(web): resuming an interrupted run lives in its own hook by @juliusmarminge in pingdotgg/t3code#23087 * refactor(web): proposed-plan follow-ups and implement-in-new-thread live in their own hooks by @juliusmarminge in pingdotgg/t3code#23091 * refactor(web): multiple-model sends live in their own hook by @juliusmarminge in pingdotgg/t3code#23094 * refactor(web): the composer send reads its own settings and draft instead of taking them from ChatView by @juliusmarminge in pingdotgg/t3code#23095 * refactor(web): ComposerControlsBar renders without a memo() wrapper by @juliusmarminge in pingdotgg/t3code#23093 * refactor(web): chat shortcuts live with the hooks that own their actions by @juliusmarminge in pingdotgg/t3code#23097 * refactor(web): ChatView's timeline banners render in ChatBannerLane by @juliusmarminge in pingdotgg/t3code#23101 * fix(web): the branch toolbar and thread details panel stay cached while a reply streams by @juliusmarminge in pingdotgg/t3code#23103 * fix(server): scheduled tasks no longer jump to the top when toggled by @t3dotgg in pingdotgg/t3code#22899 * fix(server): Forgejo and GitCafe pull requests link to their threads again by @MarcoDotIO in pingdotgg/t3code#22937 * fix(server): pushes the remote refuses say why instead of a generic failure by @t3dotgg in pingdotgg/t3code#22904 * fix(composer): typing a price no longer opens the skill menu by @MarcoDotIO in pingdotgg/t3code#21519 * fix(web): thread details PR merge uses the last selected merge method by @tris203 in pingdotgg/t3code#22399 * fix(web): a Usage toggle shortcut now goes back instead of staying on Usage by @t3dotgg in pingdotgg/t3code#22905 * fix(web): quote comment box stays on screen for long code lines by @EtanHey in pingdotgg/t3code#22149 * fix(web): right panel launcher letters open their surface instead of typing into the composer by @t3dotgg in pingdotgg/t3code#22898 * fix(web): ../ file links outside the workspace open as host files by @t3dotgg in pingdotgg/t3code#22853 * fix(shared): recognize relative folder links with trailing slash by @macodev00 in pingdotgg/t3code#22188 * fix(client): usage limits skip disabled connections by @M4NU5 in pingdotgg/t3code#22936 * fix(web): imported VS Code themes keep destructive buttons red by @lgollut in pingdotgg/t3code#21924 * fix(shared): Azure DevOps repositories with a space in the name list their pull requests by @Tabonx in pingdotgg/t3code#22782 * fix(opencode): cancelled todos no longer keep the todo list running by @MarcoDotIO in pingdotgg/t3code#22938 * fix(web): copy to machine clones the fork, not its upstream by @AKolenda in pingdotgg/t3code#22492 * fix(server): JetBrains IDEs open file links at the right column by @levochkaa in pingdotgg/t3code#22826 * fix(server): sync pull request draft status changes by @Yash-Singh1 in pingdotgg/t3code#22832 * test(web): chat shortcut test types through the composer handle by @juliusmarminge in pingdotgg/t3code#23126 * fix(source-control): merge messages drop Claude Code's current claude.com footer by @MarcoDotIO in pingdotgg/t3code#23133 ## New Contributors * @Gourav224 made their first contribution in pingdotgg/t3code#22377 * @nabettu made their first contribution in pingdotgg/t3code#21442 * @MarcoDotIO made their first contribution in pingdotgg/t3code#22937 * @M4NU5 made their first contribution in pingdotgg/t3code#22936 * @lgollut made their first contribution in pingdotgg/t3code#21924 * @Tabonx made their first contribution in pingdotgg/t3code#22782 * @levochkaa made their first contribution in pingdotgg/t3code#22826 **Full Changelog**: pingdotgg/t3code@v0.1.2-nightly.20261021.3486...v0.1.2-nightly.20261021.3499 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.1.2-nightly.20261021.3499
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ChatView built the whole keyboard shortcut table inline: about 130 lines of handlers that reached into the terminal actions, the right panel actions, thread settlement and pinning, and the composer handle. ChatView had to pull every one of those pieces out of their hooks just to hand them to
useChatShortcuts. The hook itself kept its input in a ref assigned from a layout effect.Each owner now returns its own chords:
useChatTerminalActionsreturnsshortcutsforterminal.toggle/split/splitVertical/close/new. It checks terminal permissions when the key is pressed instead of ChatView reading two scopes on every render.useRightPanelActionsreturnsrightPanel.toggle/toggleMaximized/close,threadPanel.toggleanddiff.toggle.useThreadLifecycleownsthread.settleandthread.pin, together with the settled and pinned state they read. ChatView no longer callsuseThreadActionsor exports that state.composerShortcutCommandsinchat/composerShortcuts.ts.useChatShortcutstakescomposerRefandbranchToolbarRefand resolves those chords inside its key handler, which is the only place a ref read is allowed. It also uses the refs for type-to-focus, replacing thetypeIntoComposercallback.useChatShortcutsreads its input throughuseEffectEventinstead ofuseLayoutEffect(() => { latest.current = input }). The listeners still attach once.ChatView keeps the chords that combine state from several owners (copy reference, find, cycle host, the queue chords, stop, and the project-script fallback). The behavior is unchanged.
useStableCallbackcalls in ChatView: 33 to 30. No render boundaries change; the composer render counts match #23093.Tested:
🤖 Generated with Claude Code