Skip to content

fix: show the runtime icon on a profile-launched tab - #672

Merged
onevcat merged 2 commits into
onevcat:mainfrom
verbaux:fix/agent-profile-tab-icon
Aug 3, 2026
Merged

fix: show the runtime icon on a profile-launched tab#672
onevcat merged 2 commits into
onevcat:mainfrom
verbaux:fix/agent-profile-tab-icon

Conversation

@verbaux

@verbaux verbaux commented Aug 2, 2026

Copy link
Copy Markdown

Launching an agent from the Agents menu leaves the tab wearing the generic terminal glyph, while typing claude by hand in the same worktree shows the Claude Code brand icon.

launchAgentProfile creates the tab with a hardcoded icon: "terminal" and leaves the rest to CommandIconMap, which resolves an icon from the first whitespace token of the command in the OSC 2 title. Since 053/006 the launch command is env CLAUDE_CONFIG_DIR='…' claude, so that token is env. It matches nothing, and per CommandIconMap's contract an unmatched token deliberately leaves the existing icon untouched — so the placeholder stays for the life of the tab.

The launch path already knows its runtime, so it resolves the brand icon directly instead of round-tripping through the shell title. iconLock stays .auto, so a later command in the same tab still claims the slot, exactly as it does for a hand-typed agent.

A profile's custom SF Symbol is deliberately out of scope: it isn't part of AgentProfileLaunchPlan, and docs/components/agent-profiles.md already states that live panes show the icon of the process Prowl actually detects.

Test plan

  • make build-app — 0 errors, 0 warnings
  • WorktreeTerminalStateAgentProfileTests — 5/5; reverting the one-line change fails launchCreatesTheTabWithTheRuntimeIcon()
  • make check — clean
  • Manually: launch a profile from the Agents menu → the tab shows the runtime icon; run another recognised command in that tab → the icon follows it

Notes

  • Conflicts with Add profile-aware handoff #651, which restructures the same createTab call (and keeps the hardcoded glyph). Happy to rebase whenever it lands.
  • Possible follow-up, deliberately left out to keep this at one line: CommandIconMap could skip a leading env VAR=… prefix, so a hand-typed env FOO=1 claude resolves too.

A profile launch creates its tab with a hardcoded terminal glyph and leaves the
rest to CommandIconMap, which resolves an icon from the first token of the
command in the shell title. The launch command is `env CLAUDE_CONFIG_DIR=…
claude`, so that token is `env`; nothing matches, and by contract an unmatched
token leaves the existing icon untouched. The placeholder therefore stays for
the life of the tab: typing `claude` by hand shows the brand icon, launching the
same agent from the Agents menu does not.

The launch path already knows its runtime, so resolve the icon there instead of
round-tripping through the shell title. The lock stays `.auto`, so a later
command in the same tab still claims the slot, exactly as for a hand-typed
agent.

@onevclaw onevclaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new-tab path correctly applies the Agent Profile runtime icon while preserving the .auto lock, but the successful split path is currently missed.

launchAgentProfile returns immediately after creating a split in WorktreeTerminalState.swift, before reaching the runtime-icon update used by the new-tab path. Because the split becomes the focused surface and its env … OSC 2 title is not recognized by CommandIconMap, the containing tab can retain its previous icon. I reproduced this by starting with @asset:Git and launching a Codex Profile into a split: the icon remained @asset:Git instead of changing to the profile runtime icon.

Please apply the resolved icon to the split's containing tab before returning, while continuing to respect user/script locks, and add coverage for both .auto and locked split cases.

The terminal documentation should also be narrowed slightly: Profile commands only start with env when launch-scoped environment tokens exist, and only a later recognized command overrides the automatic icon.

onevclaw - an assistant to @onevcat

The split placement path returned right after creating the surface, before the
runtime-icon update the new-tab path does. The split becomes the focused
surface, and its `env …` title is not recognised by CommandIconMap, so the
containing tab kept whatever icon it had — reproducibly `@asset:Git` when a
Codex profile was launched into a split from a Git-branded tab.

Apply the resolved icon through applyResolvedIcon before returning: it already
guards focus and the icon lock, so `.user` and `.script` claims are untouched
and the slot stays `.auto` for a later recognised command.

launchTabIcon now returns TabIconSource? instead of folding an unmatched
runtime into "terminal": on the split path that fallback would have overwritten
the tab's existing icon. The new-tab call site keeps the glyph as its default.

Docs narrowed accordingly: the `env` prefix appears only when the profile sets
launch-scoped environment variables, and only a later *recognised* command
takes the slot back.
@verbaux

verbaux commented Aug 3, 2026

Copy link
Copy Markdown
Author

@onevclaw Good catch on the split path — fixed in d1728a6.

One adjacent change. launchTabIcon now returns TabIconSource? instead of collapsing an unmatched runtime into "terminal". On the new-tab path that fallback was harmless, but on the split path it would have overwritten the tab's existing icon with the generic glyph. The new-tab call site keeps ?? "terminal" as its default.

@verbaux
verbaux requested a review from onevclaw August 3, 2026 07:10
@onevcat

onevcat commented Aug 3, 2026

Copy link
Copy Markdown
Owner

@onevclaw Can you please verify the fix again?

I can indeed reproduce this issue so obviously it is true. Please check and see the new fixes addressed your previous concerns.

@onevclaw

onevclaw commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Rechecked on d1728a6. The split path now applies the resolved runtime icon to the newly focused split's containing tab before returning. Going through applyResolvedIcon means it still respects user and script icon locks, while the .auto case is rebranded as intended.

The optional icon result also avoids replacing an existing split-tab icon with the generic terminal glyph if a future runtime has no mapping; the new-tab path retains its deliberate fallback. The added tests cover the automatic split rebrand plus both locked cases.

I ran make test on the PR head: all 2,253 tests passed. The CI build is green as well. This addresses my previous concerns; no further issues found.

🧵 mh_1785761892065_fb1b6df0 · 🐾 main → main
🪝 gh:onevcat:prowl:pr:672:main:m202608
🆔 cfcc4744-01c0-43bf-9028-d31dfb26e185

@onevcat
onevcat merged commit 2c002bd into onevcat:main Aug 3, 2026
1 check passed
@onevcat

onevcat commented Aug 3, 2026

Copy link
Copy Markdown
Owner

@verbaux Nice catch! Thank you for the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants