Adds OpenClaude as a distinct CLI agent across detection, launch, settings, status, hooks, orchestration, telemetry identifiers, notifications, and README badges. Installs OpenClaude hooks under its own ~/.openclaude config root, handles StopFailure API/model-error events so statuses clear correctly, and keeps OpenClaude tab/status icons distinct from Claude.
Adds an RPM Linux package target and renames the Linux CLI command to orca-ide to avoid shadowing GNOME Orca, while preserving macOS and Windows CLI command behavior.\n\nFollow-up hardening keeps the Linux launcher executable, removes only old Orca-managed Linux/WSL orca launchers during migration, preserves AppImage/deb artifact names, and updates package/release tests for the RPM asset.
* 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>
* feat(settings): add Ghostty config import
Add safe one-shot Ghostty import with preview and success summary,
and probe documented Ghostty config paths before applying changes.
Refs #958
* chore(git): ignore atl artifacts
* feat(settings): map font-weight, cursor-blink and focus-follows-mouse from Ghostty
Adds three safe direct-mapping Ghostty keys that have clear equivalents
in GlobalSettings: font-weight, cursor-style-blink, and focus-follows-mouse.
Refs #958
* feat(settings): expand Ghostty import to support colors, opacity and option-as-alt
- Add TerminalColorOverrides type grouping 21 optional xterm ITheme fields
- Add terminalBackgroundOpacity, terminalPanePaddingColor, terminalPaddingBalance
to GlobalSettings
- Extend parser to collect repeated keys as string[] (needed for palette lines)
- Map background-opacity, background, foreground, cursor-color,
selection-background/foreground, palette (0-15), window-padding-color,
window-padding-balance, macos-option-as-alt in mapper
- Merge terminalColorOverrides into xterm ITheme at theme resolution; apply
opacity as rgba() with allowTransparency enabled
- Accept hex colors with or without leading # (Ghostty omits it)
- Fix preview diff to use deep equality for object values so already-applied
color overrides no longer reappear on next import
* feat(settings): support background-blur-radius and window-padding-color extend in Ghostty import
- Map background-blur-radius > 0 to windowBackgroundBlur: true; apply
vibrancy on macOS and backgroundMaterial acrylic on Windows at window
creation (blur requires restart — no hot-reload IPC exists)
- Accept window-padding-color = extend/background as valid Ghostty values;
both map to default Orca padding behavior (undefined field) instead of
landing in unsupportedKeys
- Split mapper.test.ts into domain-scoped describes to stay under 300-line limit
* feat(settings): add Window section to Terminal settings panel
Expose terminalBackgroundOpacity, windowBackgroundBlur, terminalPaddingBalance,
terminalPanePaddingColor, and terminalColorOverrides in the settings UI so
imported Ghostty values can be viewed and changed manually.
- New TerminalWindowSection component (extracted from TerminalPane to stay
under the 400-line limit)
- Collapsible color overrides sub-section with ColorField for all 21 xterm
ITheme fields grouped as base, ANSI normal, and ANSI bright
- Reset button clears all color overrides at once
- Window blur toggle shows restart-required note (blur applies at window
creation, no hot-reload IPC exists)
- Search entries added for all new controls
* feat(settings): expand Ghostty import with scrollback, padding, divider, cursor and word-chars keys
Map 9 additional Ghostty keys to Orca settings:
- split-divider-color → terminalDividerColorDark + terminalDividerColorLight
(single value applies to both; Ghostty has no dark/light distinction)
- unfocused-split-opacity → terminalInactivePaneOpacity (direct float 0-1)
- scrollback-limit → terminalScrollbackLimit; applied to xterm scrollback option
- window-padding-x / window-padding-y → terminalPaddingX/Y; applied as CSS
vars --pane-padding-x / --pane-padding-y in terminal.css
- cursor-text → terminalColorOverrides.cursorAccent (xterm ITheme field)
- bold-color → terminalColorOverrides.bold (persisted; xterm ITheme has no
bold field yet — stored for future xterm upgrade)
- cursor-opacity → terminalCursorOpacity; blended into cursor rgba at theme
resolution time
- selection-word-chars → terminalWordSeparator; applied to xterm wordSeparator
- mouse-hide-while-typing → terminalMouseHideWhileTyping field added; renderer
application deferred (needs per-pane disposable + global mousemove listener)
* feat(settings): expose new Ghostty-imported settings in Terminal Settings UI
- Window section: scrollback limit, horizontal/vertical padding, hide mouse
while typing toggle, cursor text and bold color in Color Overrides
- Cursor section: cursor opacity NumberField
- Advanced section: word separators text input
- Search entries added for all new controls
- terminalDividerColorDark/Light and terminalInactivePaneOpacity skipped —
already present in Theme and Pane Styling sections respectively
* feat(terminal): implement mouse-hide-while-typing per pane
Register terminal.onData → cursor:none and mousemove → restore, scoped to
the pane container element. Uses the existing IDisposable per-pane pattern
(same as selectionDisposablesRef). Cleans up on pane close and effect teardown.
* refactor(settings): address ghostty import code review findings
- Centralize GhosttyImportPreview type in shared/types (remove duplicate from mapper)
- Fix parser to strip inline comments without breaking hex color values (#1a1a1a)
- Extract HEX_COLOR_RE to shared/color-validation to avoid duplication
- Remove redundant Number.isNaN checks after Number.isFinite (4 sites)
- Replace unsafe catch-all assignment with explicit font-family branch
- Migrate 280-line if-chain in mapGhosttyToOrca to FIELD_PARSERS registry
- Add human-readable setting labels in GhosttyImportModal via setting-labels map
- Add clarifying comment in index.ts re JSON.stringify undefined behavior
* fix(settings): harden ghostty import from judgment-day review
- Surface readFile errors in GhosttyImportPreview.error instead of
showing misleading 'No config found' on permission denied
- Guard handleApply against double-apply when already applied
- Strip surrounding quotes from parsed config values (font-family)
- Return null from palette handler when all entries fail validation
- Inform user when background-blur-radius radius is not preserved
- Add valuesEqual key-order stability via stableStringify
- Normalize hex colors to #-prefixed format across all color mappers
- Reject blank values before numeric parsing (Number('') === 0 trap)
- Remove selection-word-chars mapping (inverted xterm semantics)
- Guard window-padding-x/y against negative integers
- Reactive mouse-hide-while-typing on existing panes when setting toggles
- Merge terminalColorOverrides on import instead of replacing
* fix(ghostty): drop broken imports, tighten parsing, prompt restart for blur
Review found three high-impact issues in the Ghostty import: scrollback-limit
semantics are inverted/rescaled (Ghostty is bytes with 0=unlimited, xterm is
rows with 0=disabled), and window-padding-color + window-padding-balance set
CSS custom properties (--pane-padding-color, --pane-padding-balance) that
have no consuming rule anywhere in the tree — so users confirming "changes"
to those keys would see nothing happen.
Because none of the three keys have a safe mapping today, drop them from the
import and remove the dead UI controls + GlobalSettings fields + CSS var
plumbing. The mapper now lists them as unsupportedKeys alongside the
existing window-decoration / keybind / custom-shader entries.
Other fixes in the same review:
- allowTransparency now clears when background-opacity returns to 1 (prior
code only ever set it to true, leaving a stale flag with measurable render
cost).
- background-blur-radius = 0 no longer emits a misleading "radius value not
preserved" note (0 cleanly maps to blur=false with no radius to lose).
- Add a 1 MB size cap on the config read so a pathological or symlinked file
cannot OOM the main process.
- Make handleApply async and surface IPC errors inline in the modal instead
of flipping straight to "Import complete" on failure.
- Type settings.previewGhosttyImport as Promise<GhosttyImportPreview> in
preload so shape drift is caught at compile time.
- Make stableStringify recursive so future nested settings round-trip
cleanly through valuesEqual.
- Restrict window-padding-x/y and background-blur-radius to decimal ints;
prior code accepted exponent notation (1e10 sails through Number.isInteger)
and would have landed absurd values in the store.
- Window blur now shows a "Restart required" banner with a Restart now
button when the setting differs from the mount-time snapshot, mirroring
the ExperimentalPane daemon pattern. Blur only applies at BrowserWindow
creation on macOS/Windows.
Co-authored-by: Orca <help@stably.ai>
* feat(settings): move Ghostty import trigger to Terminal section header
Per review feedback: the "Import from Ghostty" row was taking its own slot
in the Terminal settings list alongside real configuration sections. Move
the trigger into the Terminal section's header (upper-right corner) as a
headerAction, next to the Terminal heading — it's a one-shot action, not a
setting.
- SettingsSection gains an optional `headerAction` slot rendered to the
right of the section title/description.
- The useGhosttyImport hook is lifted from TerminalPane into Settings.tsx
so the section header button (owned by Settings.tsx) and the modal
(still rendered inside TerminalPane) share one state instance.
- TerminalPane drops its own "Import" section + the TERMINAL_GHOSTTY_IMPORT
search entry group is no longer referenced there.
- Button carries the official Ghostty mark as a 16x16 icon so it reads
clearly as a cross-app import even before users parse the label.
useGhosttyImport now accepts `GlobalSettings | null` so the parent can call
it above the pre-load spinner guard without violating hook ordering; the
apply path no-ops until settings arrive. Related test file updated to
pass the new `ghostty` prop and to assert the trigger is *not* rendered
inside TerminalPane anymore.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
Move build resources to resources/build/, icon source files to
resources/icon-source/, scripts to config/scripts/, and patches
to config/patches/ for a cleaner top-level directory layout.