Skip to content

cli(feat): share each profile's colour and symbol through the CLI - #100

Merged
Ducksss merged 13 commits into
mainfrom
claude/profile-identity-cli
Oct 28, 2026
Merged

Ducksss merged 13 commits into
mainfrom
claude/profile-identity-cli

Conversation

@Ducksss

@Ducksss Ducksss commented Oct 28, 2026

Copy link
Copy Markdown
Owner

Summary

One colour and symbol per profile, shown everywhere: the menu-bar app, the shell prompt, Raycast and new launchers. Stacked on #96, which added colours to the menu-bar app; GitHub retargets this to main once #96 merges.

  • New codex-profile appearance command.
    codex-profile appearance                                   # every profile
    codex-profile appearance work --color teal --symbol briefcase
    codex-profile appearance work --reset
    codex-profile appearance --json
    • Without a choice, default is graphite and other profiles take a stable colour from an FNV-1a hash of their name, computed the same way as the app.
    • The palette leaves out red, orange and yellow, which mean low quota.
    • Choices live in a private appearance.tsv next to the workspace registry, written atomically under the state lock with symlinks refused. Damaged lines fall back to automatic, and remove forgets the profile's entry.
    • usage(), per-command help, USAGE.md, llms.txt and the bash, zsh and fish completions all cover the new command.
  • Menu-bar app. It reads appearances on each refresh and saves choices through the CLI instead of its own preferences.
    • A choice shows at once, and writes run in order, so quick clicks can't land out of order.
    • A refresh never overwrites a write that's still in flight.
    • A refused write shows the CLI's reason and reloads what the CLI holds.
  • Shell prompt. env exports CODEX_PROFILE_COLOR, and shell-init --prompt puts a ● in the profile's colour before [codex:<profile>] in bash, zsh and fish. The dot uses fixed escapes, so earlier dots are removed exactly and never stack, including through venv-style prompt restores. NO_COLOR leaves it out, and the prompt never runs the CLI.
  • Raycast. Open Profile tints each profile's icon with its colour. An older codex-profile without appearance keeps plain icons.
  • Launchers. launcher create uses the profile's colour unless --color is given. Launcher colours gain indigo and brown, and red and orange are still accepted.

Not in this PR: symbols in Raycast, since its built-in icons don't map cleanly to the twelve symbols. Colour-coded Terminal tabs are also left out; CODEX_PROFILE_TERMINAL_TITLE already labels titles.

Testing

  • make check passes, including ShellCheck.
  • New test/cli/appearance-test.sh covers:
    • automatic colours, and that reading never creates the registry;
    • set, partial update and reset, with private file modes;
    • refused colours, symbols, profiles and flag combinations;
    • damaged lines and a symlinked registry;
    • env in POSIX and fish;
    • remove.
  • launcher-test.sh covers the default colour following the profile, and an explicit --color still winning.
  • prompt-test.sh runs the existing transcripts with NO_COLOR and adds dot checks in bash, zsh and fish: colour, no stacking, switching profile.
  • completions-test.sh covers the new flags and values in all three shells.
  • The native real-CLI test checks that Bash and Swift pick the same automatic colour, and round-trips a choice, a reset and a refused write.
  • Raycast npm test passes (58 tests). It includes checks that Raycast's colours match the CLI's names and the app's exact values.
  • Not run: Raycast's npm run typecheck, npx eslint and npx prettier --check, which need npm ci in raycast/. The new code reuses the existing { source, tintColor } image shape and Object.hasOwn (ES2022).

Scope and compatibility

  • Affected scope: the CLI's new appearance command, env output, the opt-in prompt and launcher defaults, plus the menu-bar app and Raycast. cli/login behaviour, app default and named Desktop launches are unchanged.
  • Compatibility impact:
    • env now prints a third line, CODEX_PROFILE_COLOR.
    • launcher create without --color now uses the profile colour instead of always blue.
    • The prompt shows a coloured dot unless NO_COLOR is set.
    • The state schema version is unchanged; appearance.tsv is an optional, additive file.
    • Choices saved by an unreleased frontend(feat): give profiles colours and show quota in the menu bar #96 build in UserDefaults aren't migrated.

Checklist

  • I ran make check; if the environment lacks ShellCheck, I ran
    make test and documented the missing lint result instead.
  • I did not add code that reads, copies, prints, parses, uploads, compares,
    or migrates auth tokens or ChatGPT cookies.
  • Desktop changes preserve the stock app default session and use the
    original signed app bundle.
  • I did not claim that CLI and Desktop account equality can be inspected or verified.
  • I updated documentation for user-facing behavior changes.

🤖 Generated with Claude Code

Ducksss and others added 8 commits October 27, 2026 19:33
Rebuild the menu-bar popover around profiles, following the canvas
redesign.

- Each profile leads a group and its workspaces sit beneath it, pinned
  first and then by last launch; this replaces the profile filter.
  Workspaces whose profile is missing follow the groups and name it.
- The header is search and the gear. Typing selects the first match so
  Return's target is visible, and the footer names what Return and
  Command-Return open.
- Clicking a row opens it. Command-Return and Command-click open the
  other destination; the gear menu's "Return opens in" replaces the
  ChatGPT/Terminal control and keeps the saved preference.
- Rows drop their Open buttons. The actions button shows with the hover
  or selection plate and stays visible on rows that need repair, which
  also offer Locate…. Right-click shows the same actions.
- Each profile shows its tightest Codex window as a figure and a ring.
  Low and critical use darker orange and red in light mode so the
  figure keeps 4.5:1 contrast; the profile's actions list every window
  with its reset time.
- The popover is 360 points wide; previews render at 2x on any display.

Tests cover nesting and alignment, search selection, Command-Return,
the Return destination, right-click actions, the usage lines and quota
colours in both appearances. DESIGN.md, the READMEs, the site copy,
llms.txt and the previews are updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The footer decided whether to show the Return and Command-Return hints
by comparing the status message with two literals that the store also
set. Rewording either side would have left the footer stuck on a stale
message without any error.

The store now keeps its resting prompts in one place and exposes
hasStatusNews, which the footer uses. A store test covers the resting
prompt and a reported outcome.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Build the rest of the canvas redesign on top of the grouped menu.

- Each profile has a colour and symbol. New profiles get a stable
  colour from an FNV-1a hash of their name, with default in graphite,
  and show their initial. The palette leaves out red, orange and
  yellow, which mean low quota; white symbols keep 4.5:1 contrast.
- Appearance… in a profile's actions replaces the list with an editor:
  a preview with the profile's CODEX_HOME path, eight colour swatches
  and twelve symbols. Choices apply at once and persist in
  UserDefaults; Reset restores the automatic look, and Done, Return or
  Escape returns. The chosen swatch gains a ring and every choice
  reports its state to accessibility clients.
- A search result listed without its profile row shows a square of the
  profile's colour beside its name.
- Quota in menu bar, an opt-in gear-menu toggle, shows the lowest
  remaining share across profiles beside the template icon. The
  tooltip and VoiceOver label name that window. While it is on, usage
  is read every five minutes through the same path as alerts, with no
  notification permission; background reads stop only when both are
  off.

Tests cover automatic and chosen appearance, the editor and its
persistence, the tag colour, the lowest figure and its tooltip, and
background reads that follow the figure. The previews, a new editor
preview, DESIGN.md, the READMEs, the site alt text and llms.txt are
updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ions

The profile's actions listed each window with its reset time, except a
window whose reset had already passed, which said only "awaiting a
fresh reading". It now reads "5h: reset at 14:20 · awaiting a fresh
reading", worded in the past like the tooltip. An interaction test
covers it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Darken green and graphite slightly so white symbols keep the 4.5:1
  contrast the code and docs claim (green was 4.40:1, graphite 4.52:1;
  now 4.67:1 and 4.72:1). A unit test computes the contrast of every
  colour so the claim stays true.
- A symbol choice whose SF Symbol is missing on this Mac shows the
  profile's initial instead of a blank button.
- Background passes list profiles each time, so profiles created or
  removed outside the app join or leave the figure and alerts while the
  menu stays closed. They refresh quietly and leave the footer's status
  message alone; a foreground refresh that joins one still reports. The
  usage fixture answers profile listings from files without counting
  them as usage reads, and a test covers a profile joining.

Previews are re-rendered with the adjusted colours.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main is #95's final tree squashed (ff32520), which this branch already
contains as 6db4cd9, so the merge keeps this branch's tree unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Give a profile one identity that every tool shows.

- `codex-profile appearance [profile] [--color] [--symbol] [--reset]
  [--json]` shows or sets a profile's colour and symbol. Without a
  choice, default is graphite and other profiles take a stable colour
  from an FNV-1a hash of their name, computed the same way as the
  menu-bar app. Colours leave out red, orange and yellow, which mean low
  quota. Choices live in a private appearance.tsv beside the workspace
  registry, written atomically under the state lock with symlinks
  refused; damaged lines fall back to automatic, and `remove` forgets
  the profile's entry. Help, usage, completions and USAGE.md cover it.
- The menu-bar app reads appearances with each refresh and writes
  choices through the CLI instead of UserDefaults. A choice shows at
  once, writes run in order, a refresh never overwrites a write in
  flight, and a refused write shows the CLI's reason and reloads.
- `env` exports CODEX_PROFILE_COLOR, and `shell-init --prompt` puts a
  dot in the profile's colour before `[codex:<profile>]` in bash, zsh
  and fish. The dot uses fixed escapes, so earlier dots are removed
  exactly and never stack; NO_COLOR leaves it out.
- Raycast's Open Profile tints each profile's icon with its colour.
- `launcher create` defaults to the profile's colour; launcher colours
  gain indigo and brown.

Tests cover the command, its storage and refusals, env, remove, the
launcher default, completions, the prompt dot in three shells, the app
reading and writing through the real CLI with matching automatic
colours, and Raycast's colours matching the CLI and the app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 28, 2026 08:24
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Caution

Review failed

The pull request is closed.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

Ducksss and others added 4 commits October 28, 2026 16:32
Bring in the site redesign (#97). Its menu bar section replaced the one
this branch had edited, so the new section stays as #97 wrote it, with
its screenshot refreshed to this branch's dark preview (same layout, so
the numbered pins still line up) and its description noting each
profile's colour.

Also clarify in DESIGN.md and the macOS guide that background passes
list profiles quietly only after the first profile load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from claude/menu-profile-identity to main October 28, 2026 11:12
@Ducksss
Ducksss merged commit d2c4175 into main Oct 28, 2026
3 of 4 checks passed
@Ducksss
Ducksss deleted the claude/profile-identity-cli branch October 28, 2026 11:19
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.

2 participants