- Enhance discardChanges to handle untracked files by deleting them instead of git checkout
- Add path traversal protection to prevent discarding files outside the worktree
- Extract source control action logic into getSourceControlActions helper
- Show revert button for untracked files with confirmation dialog
- Add tests for both backend and frontend logic
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: auto-fetch PR data on worktree change and add refresh to empty state
Add useEffect to fetch PR data when the active worktree/branch changes,
and add a refresh button with loading spinner to the "no PR found" empty
state. Extract check helpers to separate file to stay within line limit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: replace custom PullRequestIcon SVG with lucide GitPullRequest
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Use gh api --cache for issues, issue lists, and PR checks endpoints so 304 Not Modified responses don't count against the rate limit
- Pass branch to getPRChecks to enable the check-runs REST endpoint with caching
- Extract mapping functions into separate mappers.ts to keep client.ts within 300-line limit
- Extract mapIssueInfo() helper to deduplicate issue mapping logic
- Remove dead re-exports from client.ts
- Fix reference instability in ChecksPanel poll dependency array
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Merge the separate download action button and dismiss button into one
unified button element. The dismiss icon now appears on hover only,
eliminating the visual split.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Fix ChecksPanel memory leak: add cancelled flag to prevent schedulePoll after unmount
- Include status in check signature for proper backoff reset on state transitions
- ChecksPanel lint: use ternary instead of if/else
- Don't cache empty string on gh CLI failure so login detection retries
- Clear checksCache on refreshAllGitHub to ensure fresh data
- Remove dead fetchIssueList code and supporting infrastructure
The PR state (merged/open/closed/draft) is already accessible via tooltip,
so the inline text label in the header is unnecessary visual noise.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Two issues caused "Restart to Update" to not apply the update on macOS:
1. Premature window destruction: quitAndInstall() destroyed all windows
before calling autoUpdater.quitAndInstall(). On macOS, MacUpdater
delegates to Squirrel.Mac which may not be ready yet — it registers
a listener and returns. With zero windows, the dock "activate" handler
would re-open the old version, making it appear the update failed.
Fix: remove close listeners (so windows don't block quit) but don't
destroy them. Let Squirrel.Mac handle the actual quit.
2. Premature "ready to install" status: electron-updater fires its
'update-downloaded' event after downloading the ZIP from GitHub, but
BEFORE Squirrel.Mac finishes downloading from the localhost proxy.
The UI showed "ready to install" when the update wasn't actually
installable yet. Fix: on macOS, defer the 'downloaded' status until
Electron's native autoUpdater confirms Squirrel has the update.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add console.error logging to startup update check catch block
- Add state guard to downloadUpdate() to prevent calls outside 'available' state
- Track and dismiss 'available' toast when download starts or completes
- Include version number in downloading status text
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Soften border opacity across UI components, move label default to text-xs,
simplify worktree group tones, and color PR icons by state.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
PR #103 added a blanket isEditableTarget() guard that inadvertently
matched xterm.js's internal <textarea class="xterm-helper-textarea">,
blocking Cmd+D (split pane), Shift+Enter (newline), and all other
terminal shortcuts whenever the terminal was focused.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Switch the app-wide font from SF Mono/monospace to Geist Sans for a
more polished, modern UI. Bundle the variable woff2 font in assets for
cross-platform support. Remove font-mono from sidebar and settings
components while keeping monospace in terminal/editor contexts.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add comprehensive tests for worktree parsing, GitHub check status derivation,
hooks YAML parsing, persistence store, layout serialization, store cascades,
and terminal helpers. Extract pure functions from worktrees.ts into
worktree-logic.ts for better testability.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: extract path-security helpers and refactor IPC modules
- Extracted path-security helpers from filesystem.ts into filesystem-auth.ts to fix max-lines lint error (402 -> 293 lines)
- Extracted duplicated ENOENT detection into isENOENT() helper to eliminate code duplication
- Fixed missing curly braces on single-line if-return in isDescendantOrEqual (lint violation)
- Replaced any with unknown in test files to satisfy lint rules
- All tests passing (29/29)
- Lint clean (0 errors, 0 warnings)
* fix: bundle preload deps for sandbox mode and fix editor test types
The sandbox: true change in createMainWindow broke the app because
electron-vite was externalizing @electron-toolkit/preload, producing
a require() call that fails in sandboxed preload scripts. Exclude it
from externalization so it gets bundled inline.
Also fix type errors in editor.test.ts from the partial store setup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Replace fragile tagName checks with a robust isEditableTarget() helper that
covers input, textarea, select, and contenteditable elements. Also add
Cmd/Ctrl+Enter support and stopPropagation to the WorktreeMetaDialog comment
textarea so Enter doesn't trigger terminal handlers.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Add PR checks panel to right sidebar
- Stream checks from GitHub API
- Update PR title real-time with loading state
- Add error logging and dependency fixes
- Fix linting issues (curly braces, exhaustive deps)
* feat: make keyboard shortcuts work with Ctrl on Linux/Windows
All Cmd+X shortcuts now also respond to Ctrl+X on non-Mac platforms.
Tooltip hints show platform-appropriate modifier symbols.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add cross-platform guidelines to AGENTS.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Adds clearWorkingIndicators to strip spinner/prefix/keyword markers from
terminal titles after 3s of data flow without a title update, preventing
the UI from showing a stuck "working" status after an agent exits.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Extract main process into focused modules (startup, window, menu, IPC
registration) and decompose the monolithic Terminal component into
TerminalShell, useTerminalTabs, useTerminalShortcuts, and
useTerminalSaveDialog hooks.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The cursor style sequence (e.g. \e[5 q) was being sent to the shell via
sendInput(), causing literal "[5 q" text to appear in the terminal. The
shell doesn't interpret DECSCUSR sequences. Cursor style is already
correctly applied via xterm.js terminal options.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Revert low-contrast text styles from PR #85 (worktree name, branch, repo
badge, group headers) back to full contrast. Force repo names to lowercase.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Redesign worktree cards with cleaner layout, inline PR state/CI badges,
and refined group headers. Hide redundant repo badge when grouped by repo.
Add uncaughtException handler to prevent crash on IPC pipe errors during quit.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
When a worktree is activated, update its sortOrder timestamp so that
the "recent" sort reflects the actual last-accessed time.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add copy path/relative path to line in editor tab context menu
Tracks cursor line position from Monaco editor and adds context menu
options to copy file path with line number anchor (e.g. path#L59).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add copy path to line in Monaco editor context menu
Adds "Copy Path to Line" and "Copy Relative Path to Line" as Monaco
editor context menu actions so they appear on right-click anywhere in
the editor. Also handles right-click on line number gutter to show
the context menu there too.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use Radix context menu for line number gutter right-click
Replaces Monaco's built-in context menu with a Radix DropdownMenu for
the line number gutter, matching the VSCode approach of intercepting
the gutter right-click and showing a custom menu. Shows the clicked
line number in the menu items.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: simplify gutter context menu to just path-to-line options
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
When macOS re-activates the app after all windows are closed, `createWindow()` is called
again but IPC handlers from the previous window were still registered, causing duplicate
handler errors and crashes. This fix removes stale handlers before re-registering them
in pty, repos, and worktrees modules, and ensures repo/worktree handlers + auto-updater
are also set up on activate. Includes minor lint/style cleanups across the codebase.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>