feat: drag-to-split, queue reorder, Cmd+Shift+T, PR auto-refresh#26
Merged
feat: drag-to-split, queue reorder, Cmd+Shift+T, PR auto-refresh#26
Conversation
Adds drag-and-drop to create/extend the split view by dragging sub-chats from the sidebar, drag reordering for queued messages, a Cmd+Shift+T shortcut (and tooltip) that opens a new sub-chat directly in split view, and PR status auto-refresh on git commit/push. Also adds a per-pane close button inline with the title, hides the Background/sandbox option, and lifts the sidebar's DndContext to a shared parent so drag can cross from sidebar to main content without overflow clipping (DragOverlay portals the preview at document root). Fix: `removeFromSplit` now shifts `activeSubChatId` when the removed pane was active so the correct pane stays visible after close. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aletc1
added a commit
that referenced
this pull request
Apr 18, 2026
Adds the user-visible features shipped since the README was last touched (commits #18 through #26) and groups the fork additions into four sections for readability: Workflow & UI, Git/PRs/Worktrees, Models, and Stability & Polish. Highlights surfaced: split view with drag-to-split, Cmd+Shift+T, sortable sidebar, draggable tabs, queue reorder, copy popover, PR widget + branch switcher, two-column commit diff, Pull & Push recovery dialog, worktree deletion safety, Sonnet 4.6 1M context + recovery action, GPT-5.4, rich tool rendering, stream wedge timeout, and crash auto-recovery. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8 tasks
aletc1
added a commit
that referenced
this pull request
Apr 18, 2026
…esh (#27) * fix(security,perf): audit-driven hardening of main process Addresses critical findings from a security/correctness/performance audit. Security (P0): - voice.ts, claude/env.ts: replace `execSync(${shell} -ilc '...')` with `execFileSync(shell, ['-ilc', ...])` and add a safe-shell allowlist to block `$SHELL=` command-injection via template interpolation. - claude-token.ts: remove `shell: true` from the `claude setup-token` spawn and resolve the CLI to an absolute path via `which`/`where` before invoking, so metacharacters in PATH can't be interpreted. - auth-manager.ts + index.ts: the `/auth` deep-link handler now requires an in-flight OAuth flow initiated by `startAuthFlow()`. A per-flow `state` nonce is generated, attached to the auth URL, and verified with constant-time compare on callback. Unsolicited deep links (drive- by CSRF via `twentyfirst-agents://auth?code=...`) are rejected. Performance (P1): - db/index.ts: add `PRAGMA synchronous = NORMAL` under WAL to reduce fsync load during high-frequency message persistence. - db/schema/index.ts + drizzle/0009_*: add indexes on `chats.project_id`, `sub_chats.chat_id`, and `sub_chats.stream_id` (previously full-table scans on hot FK lookups). - claude.ts: coalesce `text-delta` chunks in a 24ms buffer keyed by text id. Non-delta chunks flush the buffer first to preserve ordering. Cuts tRPC/IPC chatter during long streaming responses. Robustness (P2): - db/index.ts: migration failures now quarantine the DB file to `agents.db.broken-<timestamp>` and start fresh instead of crashing the app on every launch. - index.ts: bound `cleanupGitWatchers()` in `before-quit` to 1.5s so a hung chokidar instance can't block app quit indefinitely. Dismissed during verification: - `sandbox: false` in webPreferences is intentional for electron-trpc; contextIsolation remains enabled. - `activeSessions` map cleanup is already wired on unsubscribe and in the stream's finally block. - The stream's async IIFE is wrapped in try/catch/finally; no unhandled rejection. - Project deletion is atomic under FK cascade with `foreign_keys=ON`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: refresh fork additions section with recent features Adds the user-visible features shipped since the README was last touched (commits #18 through #26) and groups the fork additions into four sections for readability: Workflow & UI, Git/PRs/Worktrees, Models, and Stability & Polish. Highlights surfaced: split view with drag-to-split, Cmd+Shift+T, sortable sidebar, draggable tabs, queue reorder, copy popover, PR widget + branch switcher, two-column commit diff, Pull & Push recovery dialog, worktree deletion safety, Sonnet 4.6 1M context + recovery action, GPT-5.4, rich tool rendering, stream wedge timeout, and crash auto-recovery. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
DndContextlifted from the sidebar to a shared parent so the drag can cross components;DragOverlayrenders a portal-mounted preview so the sidebar's scroll-container overflow can't clip the dragged row. Drop zones disable themselves when the drop would no-op (dragging the active chat in solo mode, already a split pane, or split at max) so no misleading hover highlight appears.status === "processing"are undraggable so the processor and the user don't fight over ordering.Cmd+Shift+T(orOpt+Cmd+Shift+Ton web) — creates a new sub-chat and opens it in split view alongside the previously active chat. The+button tooltip now shows bothCmd+T("New chat") andCmd+Shift+T("New in split").extractGitActivityscans message parts for a commit/push/PR; if found,chats.getPrStatusandchanges.getGitHubStatusare invalidated so the PR badge updates immediately instead of waiting for the 30s poll.messageskept out of the effect deps (read via ref) so the effect only fires on the stream-end transition.ChatTitleEditor). Persistent so it doesn't vanish mid-hover; tooltip switches between "Remove from split" and "Close split view" (last pair).removeFromSplitnow shiftsactiveSubChatIdto an adjacent remaining pane when the removed pane was active — previously the UI kept pointing at the just-closed chat, making it look like the wrong pane closed.Background (Soon)work-mode option until it's wired up; commented out in place for easy rollback.Test plan
Cmd+Tcreates a normal new sub-chat (no split).Cmd+Shift+Tcreates one in split view.+button tooltip shows both shortcuts.git commitorgit push— PR badge state refreshes right after the stream ends (not 30s later). No spurious refresh after non-git tool calls.LocalandWorktree.Open in Split,Remove from Split,Close Split View) still work; divider resize still smooth with 350px min pane width.🤖 Generated with Claude Code