Renames the experimental pet overlay to "sidekick" with themed character
names (Claude the Mage, OpenCode the Rogue, Gremlin the Trickster).
Covers IPC channels, preload API, persisted UI state, settings flag,
on-disk userData path, components, and types.
Deletes the standalone pet-overlay design mock.
Co-authored-by: Orca <help@stably.ai>
* feat: add experimental pet overlay
Adds an opt-in 3D pet overlay pinned to the bottom-right. Gated behind
an experimental flag so three.js + GLB models stay out of the renderer
bundle for users who never enable the feature. Ships with four bundled
models plus user-uploaded custom GLBs via a pet:import IPC; a status-bar
segment provides model picker + hide toggle.
See docs/design/pet-overlay.md for the full design.
Co-authored-by: Orca <help@stably.ai>
* refactor(pet): replace 3D GLB models with 2D webp images
Co-authored-by: Orca <help@stably.ai>
* chore(pet): compress pet webp images and remove unused assets
Reduce resources/claude.webp, gremlin.webp, opencode.webp sizes; drop
the obsolete pet-overlay design doc and compress-pet-glb script now
that the GLB pipeline has been replaced by 2D webp images.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* fix(tabs): align tab row bottom with sidebar header
The center column's top band was 6px drag strip + 34px tab row = 40px,
while the sibling `titlebar-left` above the sidebar is 42px. The tab row
sat 2px high, making the seam between the two columns visibly off.
Bump the drag strip from 6px to 8px so the top band totals 42px and the
tab row's bottom border lines up with the sidebar header.
Co-authored-by: Orca <help@stably.ai>
* fix(tabs): shrink tab row to 32px, pad drag strip to 10px
Keep the total top-band at 42px (matching the sidebar's titlebar-left)
while making the tabs themselves 2px shorter, so the tab chrome feels a
touch more compact without breaking alignment with the sidebar header.
Co-authored-by: Orca <help@stably.ai>
* fix(tabs): drop doubled border on leftmost split pane
The TabGroupSplitLayout wrapper paints a full-height `border-l` at the
sidebar seam, and every split pane paints its own `border-l`. On the
leftmost pane those stacked at the same x, reading as a ~2px bar just
below the drag strip where the wrapper's 1px line continues alone above.
Mirror the right-edge handling: skip the pane's `border-l` when it
touches the left edge, leaving the single wrapper border to draw the
seam — same visual weight as the right edge.
Co-authored-by: Orca <help@stably.ai>
* docs(tabs): refresh stale wrapper border-l comment
Why: `border-l` on the wrapper comment still described the pre-fix
overlap behavior. After `touchesLeftEdge`, the leftmost pane drops
its own `border-l`, so the seam is exactly 1px — the old comment
contradicted the code.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
- BrowserTab: Globe icon uses text-blue-500 on both active and inactive tabs
for a distinct, recognizable anchor in the tab strip.
- shell-icons: GenericTerminalIcon now renders a pitch-black tile with a
thick stroked >_ (chevron at 3.2px, underscore at 2.6px, taller chevron)
so mac/linux/default terminal tabs match the colored-badge treatment of
the PowerShell/CMD/WSL icons instead of a flat lucide chevron.
- SortableTab: all terminal tabs use ShellIcon. On Windows, tabs without a
per-tab shellOverride fall back to the user's configured default
Windows shell so the tab-strip icon reflects what's actually running.
Co-authored-by: Orca <help@stably.ai>
getConnectionId returns undefined during store hydration, which was
misclassified as remote by `!== null` check. Changed to `typeof === 'string'`
so unhydrated state falls through to client-OS quoting, consistent with
terminal-drop-handler.ts behavior.
Co-authored-by: Orca <help@stably.ai>
Switch the reveal scroll from align:'center' to align:'auto' so clicking
a worktree only scrolls the sidebar when its card is not already visible.
Centering on every click made the list feel jumpy during normal navigation.
Co-authored-by: Orca <help@stably.ai>
Electron <webview> elements run in a separate process, so clicks inside
them don't dispatch pointerdown on the renderer document. Radix
DropdownMenu relies on document pointerdown for outside-click detection
and therefore misses webview clicks, leaving the menu stuck open.
Listening for window blur catches the moment focus leaves the renderer
(including into a webview) and closes the menu.
Co-authored-by: Orca <help@stably.ai>
On close/quit (especially auto-updater relaunch via quitAndInstall),
Electron/OS emit resize/move/unmaximize while the window is torn down.
The debounced persistence was capturing those near-minimum bounds, so
the next launch came up at minWidth x minHeight.
- Freeze bounds persistence on window 'close' and app 'before-quit'
(updater strips the window 'close' listener before quitting, so
the app-level latch is needed as a second line of defense).
- Release the freeze on will-prevent-unload so aborted Cmd+Q keeps
saving bounds.
- On restore, discard saved bounds at/below the min dimensions to
recover users who already persisted corrupt bounds.
Co-authored-by: Orca <help@stably.ai>
Before removing a <webview> that currently owns focus, blur the active
element and refocus the window. Without this, macOS hands activation to
the previously-active app (e.g. Slack) because the focused webContents
is gone with no replacement, pulling the user out of Orca on worktree
delete.
Co-authored-by: Orca <help@stably.ai>
Audited and rebased PR 1138. Squashed to remove the original untrusted commit stack; hook execution now requires explicit UI trust or CLI --run-hooks opt-in.