stablyai / stablyai/orca

[Feature]: Let users set a custom icon for "Open in" apps they add

Open
#13,635 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
71.3k
Forks
4.7k
Avg merge
17h 8m
Merged PRs (30d)
475

Description

### Problem or use case

When you add your own entry under **Settings → General → "Open in" menu**, it always renders with the generic `AppWindow` placeholder icon. Only three commands get a real icon.

The catalog in `src/renderer/src/lib/open-in-app-catalog.tsx` hardcodes three presets — VS Code (`code`), Cursor (`cursor`), Zed (`zed`) — each with a `faviconDomain`. `OpenInApplicationIcon` matches the entry's `command` string against that list; anything that doesn't match falls through to ``.

So a user who adds IntelliJ IDEA, Sublime Text, Xcode, Fleet, Neovim, Windsurf, a JetBrains IDE, or a shell wrapper script gets a row of identical grey window glyphs in the "Open in" menu (sidebar worktree card, source-control context menu, file explorer). With the 8-entry cap (`OPEN_IN_APPLICATIONS_MAX`), a full list is effectively unscannable — you have to read every label because the icons carry no information.

Matching on `command` also means a preset icon silently disappears the moment someone points the entry at an absolute path or a wrapper (`/usr/local/bin/code-insiders`, `my-code`), even though it *is* VS Code.

### Proposed solution

Let the user attach an icon when creating or editing an "Open in" entry.

1. Add an optional `icon` field to `OpenInApplication` (`src/shared/types.ts:2706`), currently `{ id, label, command }`.
2. Preserve it in `normalizeOpenInApplications` (`src/shared/open-in-applications.ts`), which today reconstructs each row as `{ id, label, command }` and would drop any extra field. Validate type/size and ignore anything malformed, consistent with how `label`/`command` are normalized.
3. Add an icon control to the row editor in `OpenInMenuSetting.tsx` — clicking the current icon opens a picker.
4. Resolution order in `OpenInApplicationIcon`: user-set icon → command-matched preset → `AppWindow` fallback. Existing entries keep today's behavior with no migration.

Open question on what the picker should accept — worth deciding before implementation:

- **Image file import** (PNG/SVG), copied into user data like the approach proposed in #13316 for the app icon. Most flexible, needs storage + size validation, and has to survive sync to remote/mobile clients.
- **A bundled icon set** (lucide names, or an expanded preset list keyed by name rather than command). No storage concerns, no arbitrary user assets on the wire, but limited choice.
- **A favicon domain**, reusing the existing preset mechanism (user types `jetbrains.com`). Cheapest to build since it's exactly what presets already do, but requires network and leaks the domain to Google's favicon service.

Two smaller fixes that would help even without a picker:

- Decouple preset matching from the exact command string, so an absolute path or a wrapper still resolves to the right preset (basename match, or an explicit preset reference stored on the entry).
- Grow the built-in preset list beyond three — JetBrains IDEs, Sublime Text, Windsurf, and Xcode would cover most of the common additions.

Note for whoever picks this up: the "Open in" list is global settings that reach paired clients, so per [`docs/reference/remote-wire-compatibility.md`](../blob/main/docs/reference/remote-wire-compatibility.md) a new optional field is safe, but an older client will just ignore the icon and show the placeholder. If the icon is an imported asset rather than a name/domain, how it reaches a remote client needs a deliberate answer.

### Alternatives or additional context

Current workaround: none — icons aren't configurable, so the only lever is naming entries so labels disambiguate them.

Related but distinct:

- #13316 — importing a custom **Orca application** icon (Dock/taskbar). Same "let users bring their own icon" shape, different surface; if it lands first, its user-data storage and validation path is directly reusable here.
- #11719 — custom icon **sets** (FontAwesome, SimpleIcons) for project icons, proposed as a plugin extension point. If that ships, "Open in" entries could draw from the same registry instead of getting a bespoke picker.
- #5983 (closed) — "Open in" with absolute paths containing spaces. Related in that absolute-path commands are a normal configuration, and they're exactly the ones that lose their preset icon today.

Contributor guide

Open the contributing guide

Research direction

Start with src/shared/types.ts, src/shared/open-in-applications.ts, src/renderer/src/lib/open-in-app-catalog.tsx, and OpenInMenuSetting.tsx to trace the entry lifecycle and current icon resolution. Decide the supported icon representation and remote-client behavior before implementation, then verify malformed values are ignored, existing presets still work, and older clients retain the fallback behavior described in docs/reference/remote-wire-compatibility.md.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
desktop, developer-experience
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.