cmux-next: Feed kinds, inbox controls and GitHub actions draw registry icons
Summary
Seventh PR of the icon registry lane (after #17538, #17558, #17582, #17583, #17593 and #17597). The Feed showed each item's kind with SF Symbols at the font size of its text, plus SF labels on GitHub actions, prompt summaries and the inbox header. The Feed now draws them from the cmux icon registry, with one semantic name per meaning, at the row size of the text beside them. Because of #17597, they land on whole pixels.
Kind glyphs (FeedGlyph.icon(for:)):
| Item | Was (SF) | Now (registry) |
|---|---|---|
| Notice from an integration | arrow.triangle.pull | integration |
| Notice from a server or VM | server.rack | machine.remote |
| Notice from an automation | gearshape.2 | automation |
| System notice with a terminal | terminal | terminal |
| Other notices | bell | notification |
| Approve: command | terminal | terminal |
| Approve: edit | pencil.line | action.edit |
| Approve: network | network | network |
| Approve: install | shippingbox | package |
| Approve: tool or custom | wrench.and.screwdriver | tools |
| Question | text.bubble | agent.question |
| Choice | list.bullet | feed.choice |
| Confirm | checkmark.circle | action.confirm |
| Sign in | person.badge.key | account.signin |
| Passkey | person.badge.key.fill | account.passkey |
| Review | doc.text.magnifyingglass | action.review |
| Input | rectangle.and.pencil.and.ellipsis | feed.input |
| File | doc.badge.plus | file.new |
| Handoff | hand.raised | agent.handoff |
| Custom | square.grid.2x2 | feed.custom |
The glyph box is iconRowSize(textSize) (11 โ 13, 12 โ 14, 15 โ 18). The frame stays size + 6.
Other converted call sites:
| Surface | Was (SF) | Now (registry) |
|---|---|---|
PosterLine this-Mac mark | laptopcomputer | machine.local |
FeedInboxHeader connection tabs | arrow.triangle.pull, tray | brand.github, inbox |
FeedInboxHeader add connection | plus | action.add |
FeedInboxHeader search | magnifyingglass | search |
FeedInboxHeader filter menu | line.3.horizontal.decrease, .circle.fill when filtered | filter, Line or Solid when filtered |
FeedInboxHeader refresh | arrow.clockwise | action.reload |
FeedToast close | xmark 9 pt | action.close at iconFloor |
FeedEmptyState, inbox placeholder | tray | inbox.empty |
FeedMenubarView open Feed | arrow.up.forward.app | app.open.external |
FeedApproveControls scope menu | chevron.up.chevron.down 8 pt | control.popup at iconFloor |
FeedInboxView snooze menu | moon.zzz | action.snooze |
FeedGitHubActions branch, checks, error | arrow.triangle.branch, checkmark.circle/xmark.circle, exclamationmark.triangle | git.branch, status.success/status.error, status.warning |
FeedGitHubActions buttons | arrow.up.right, arrow.down.to.line, sparkles, checkmark, exclamationmark.bubble | link.external, git.branch, agent.chat.new, action.confirm, action.review |
FeedAnswerControls closed line | checkmark, minus.circle | status.success, action.remove |
FeedPromptSummary checklist, origin, attachment | circle, lock, doc.text | list.bullet.item, security.lock, file.text |
Menu labels (filter, scope, snooze) draw NSImage.icon template images rather than the canvas-backed Icon. AppKit renders menu labels and keeps images but drops custom views, so a canvas could leave the control blank.
Not converted: mark-all-read keeps checkmark.circle. action.confirm means approve, and the pack has no mark-read icon yet. FeedTunables.section keeps its symbol string because TunableSection takes one.
Testing
Red commit a1b1873daac adds FeedRegistryIconTests; the fix follows. The red run failed to compile on base (FeedGlyph has no member icon or side).
- Approve-command, integration, system and server items name
terminal,integration,notificationandmachine.remote. - A glyph's box is
iconRowSizeof its text size.
scripts/verify-local.py --affected: feature-flags passed; package-groups fails on base's cmux.xcworkspace grouping, as on earlier PRs in this lane.
Changelog
Changed: Feed items, inbox controls and GitHub actions use the cmux icon set at the size of their text
Demo Video
Fleet builds of base (96f7421369d) and the fix (ba711434f18), on a capture mini (1x display), with the Feed opened from the Window menu. The mini has no Feed items, so the captures show the header and the empty state. The two runs came up in different appearances (light before, dark after).
| Before | After |
|---|---|
![]() | ![]() |
Empty-state tray at 8x (before left, after right): 
The first after build drew the tray at a 20 pt box. A pack drawing inks about two thirds of its box, so the tray was 14 px wide against the SF tray's 23. The empty states now use 32 and 44 pt boxes, and the tray inks 24 px wide.
Checklist
- Behavior changes have added or updated tests, or Testing says why not
- UI change with no new or changed user-facing strings; localization not affected
๐ค Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.
Summary by cubic
The Feed now draws item kind glyphs, inbox controls, and GitHub actions icons from the cmux icon registry instead of SF Symbols, with one semantic name per meaning at the row size of the text beside them.
- Kind glyphs use registry names like
.integration,.machineRemote,.automation, and.terminal; the glyph box isiconRowSizeof the text size. - Converted inbox header controls (connection tabs, add, search, filter, refresh), toast close, empty states, menubar, approve scope, snooze, GitHub actions, answer controls, and prompt summary icons.
- Menu labels (filter, scope, snooze) draw template NSImages because AppKit keeps images but drops canvas-backed views.
- Empty-state trays are sized so the pack's ink matches the SF Symbols they replaced.
FeedIconLabelis a new reusable label;FeedRegistryIconTestscover the glyph-to-icon mapping and row sizing.

