fix(ui): use official Claude, Grok, and Pi agent icons - #475
Conversation
Greptile SummaryThe PR replaces placeholder or legacy agent icons with official Claude, Grok, and Pi marks across shared web and React Native renderers.
Confidence Score: 5/5The PR appears safe to merge with no concrete blocking or non-blocking defects identified. The changed icon mappings and SVG definitions remain consistent with the existing web and native rendering contracts, and no reachable rendering or build failure was established.
|
| Filename | Overview |
|---|---|
| packages/presentation/ui/src/agent-meta.ts | Updates fallback documentation to reflect that all current agents now have brand glyphs. |
| packages/presentation/ui/src/chat/agent-icon.tsx | Replaces the Claude Code glyph, adds Grok and Pi marks, and generalizes the glyph component typing without an established defect. |
| packages/presentation/ui/src/native/agent-icon.tsx | Updates the Claude path and adds normalized Grok and Pi paths to keep native rendering aligned with the web renderer. |
Reviews (1): Last reviewed commit: "fix(ui): use official agent icons" | Re-trigger Greptile
There was a problem hiding this comment.
ℹ️ No correctness issues — one comment nit inline, two things worth a decision below.
Reviewed changes — a presentation-only glyph swap across both platform halves of packages/presentation/ui; no wire, schema, or daemon surface is touched.
- Claude Code moves to the Claude star — web imports
~icons/lobe-icons/claudein place ofclaudecode; the native path string is swapped to match.claudecodenow has no remaining referrer anywhere in the repo. grok-buildandpigain glyphs —grok-buildpicks up~icons/lobe-icons/grok;pigets a hand-writtenPiGlyphcomponent on web plus a 24×24 path string on native, since lobe-icons ships nopimark.- Glyph-map value type widened —
typeof ClaudeCodeGlyphbecomes an explicitAgentGlyph = React.ComponentType<React.SVGProps<SVGSVGElement>>. Required, not incidental: a plain function component and an unplugin-icons component are not the same type. AGENT_INITIALScomment only inagent-meta.ts. All five kinds now have a glyph on both platforms, so the initials fallback is unreachable in practice; keeping it is correct —.claude/rules/frontend.mdrelies on theRecord<AgentKind>to force coverage of future kinds.
I verified the parts that are easy to get quietly wrong, and they all hold:
- The two native path strings are byte-exact copies of the upstream
claudeandgrokbodies innode_modules/@proj-airi/lobe-icons/dist/icons.json. - Neither icon carries a per-icon
width/height/left/topoverride, so the collection's 24×24 default applies and the native hard-codedviewBox="0 0 24 24"is right. - Every upstream body ships
fill-rule="evenodd", so the native<Path fillRule="evenodd">is load-bearing rather than decorative. - The
pihand-roll is justified: lobe-icons has nopiglyph across its 837 icons, and the only Pi-adjacent entries (inflection*) are Inflection AI's Pi chat assistant, a different product from theearendil-works/picoding agent. The path also matches the livehttps://pi.dev/logo.svgcharacter-for-character, and the 24×24 rescale is exact (×24/800:165.29→4.9587,517.36→15.5208,634.72→19.0416). - No new
~iconswiring is needed — icon names require no registration, andchat/agent-icon.tsxis already in thelinkcode/unplugin-icons-virtual-moduleseslint override ateslint.config.cjs:124.
I also measured optical sizing, since the PR body claims cross-platform visual consistency: pi covers 58.7% of its viewBox linearly on both platforms (an exact proportional rescale), against 55.6% for the pre-existing opencode and ~100% for claude/codex/grok. So pi lands in the same band as opencode and this PR introduces no new inconsistency. Not a finding — recording it so nobody re-litigates it later.
ℹ️ .claude/rules/frontend.md now states the opposite of what the code does
The rule at line 21 ends with "there is no pi glyph (it falls back to initials)" and lists claudecode among the lobe-icons names in use — this PR falsifies both. Line 23 also tells the next person adding an agent kind to add a glyph "if one exists", which gives no guidance for the case this PR just established. The PR checklist ticks "Docs and comments are updated where behavior changed", so this looks like an oversight rather than a decision.
Technical details
# Refresh the agent-glyph convention in `.claude/rules/frontend.md`
## Affected sites
- `.claude/rules/frontend.md:21` — asserts "there is no `pi` glyph (it falls back to initials)". A `pi` glyph now exists on both platforms.
- `.claude/rules/frontend.md:21` — cites `claudecode` as one of the lobe-icons names in use. After this PR nothing in the repo references it.
- `.claude/rules/frontend.md:23` — "add the brand glyph to the `Partial` glyph map if one exists (a missing glyph deliberately falls back to initials)" is now the incomplete branch: this PR hand-rolled a glyph precisely because lobe-icons had none.
## Required outcome
- A reader following the rule to add the next agent kind arrives at what this PR actually did, not at the initials fallback.
- The rule records that hand-rolling an agent glyph is acceptable when lobe-icons lacks one, and what that costs: on web a plain function component forces the `AgentGlyph` value type rather than `typeof SomeIconsGlyph`, and on native the path must be rescaled to 24×24 by hand and kept in sync.
- The stale `claudecode` reference is either dropped or re-worded as historical context for why lobe-icons was chosen over simple-icons.
## Open questions for the human
- Is `pi` expected to stay hand-rolled long-term, or is upstreaming the mark into `@proj-airi/lobe-icons` the intended path? That answer changes whether the rule documents a permanent escape hatch or a temporary one.ℹ️ Claude Code and the claude-sub account now render the same mark on the same screen
shell/service-icon.tsx:30 already maps claude-sub → ClaudeColorGlyph, so on the account-detail surface the header ServiceIcon (shell/providers/account-detail.tsx:120) and the AgentRow AgentIcon (line 346) now show the same Claude star — the claudecode robot used to disambiguate the harness from the account there. Worth a conscious call rather than a fix: variant="brand" already used the Claude star before this PR, so the collision is only newly visible in solid/ghost, and standardizing on the star is the PR's stated intent.
Technical details
# Decide whether the harness glyph should stay distinct from the provider glyph
## Affected sites
- `packages/presentation/ui/src/chat/agent-icon.tsx:17` — `'claude-code': ClaudeGlyph` (was `ClaudeCodeGlyph`).
- `packages/presentation/ui/src/shell/service-icon.tsx:30` — `'claude-sub': ClaudeColorGlyph`, the provider-side mapping this now duplicates.
- `packages/presentation/ui/src/shell/providers/account-detail.tsx:120` and `:346` — the one surface that renders a `ServiceIcon` and an `AgentIcon` in the same tree.
## Required outcome
- An explicit decision, not necessarily a code change. `AGENTS.md` calls out that "provider" (account/service) and "Harness" (agent) "used to collide in adjacent UI", and this is the one screen where the two glyph systems meet.
## Open questions for the human
- Is the harness/provider visual distinction something the design intends to preserve, or is one Anthropic mark across both surfaces the desired end state?
- If distinction matters, the cheapest lever is the `solid` variant's `bg-primary` chip on the agent row, not reverting the glyph.Claude Opus | 𝕏

Summary
Linear: CODE-611
Icon provenance
@proj-airi/lobe-iconspackage (MIT).earendil-works/pirepository (MIT), normalized to the existing 24×24 native icon view box.Screenshots
Agents settings:
Harness picker:
Verification
pnpm check:cipnpm test— 2,990 passed, 1 skippedChecklist
pnpm check:ciandpnpm testboth pass (pluscargo fmt/clippy/testfor Rust changes)WIRE_PROTOCOL_VERSIONis bumped (not applicable)