Skip to content

Add account component to show active Claude Code login profile - #2

Merged
Mirage20 merged 2 commits into
Mirage20:mainfrom
ThusharaSampath:feat/account-component
May 18, 2026
Merged

Add account component to show active Claude Code login profile#2
Mirage20 merged 2 commits into
Mirage20:mainfrom
ThusharaSampath:feat/account-component

Conversation

@ThusharaSampath

Copy link
Copy Markdown
Contributor

Summary

Adds a new `account` provider + component that detects which Claude Code account is currently logged in (macOS only) and renders a colored label on the status line.

Motivation

When using Claude Code with multiple accounts (e.g. personal Pro + work Team) and switching between them by swapping the OAuth token in the macOS Keychain, it's easy to lose track of which account a given session belongs to. This component makes that visible at a glance.

How it works

  • Provider: shells out to `security find-generic-password` to read the live credentials slot (default: `Claude Code-credentials`) and each configured profile slot (defaults: `Claude Code-personal`, `Claude Code-work`). When the live token matches a saved profile slot, the provider returns that profile name. When it matches no slot, it returns `"unknown"`. Non-macOS platforms get an empty profile (component renders nothing).
  • Component: maps the profile name to a color (defaults: `personal=cyan`, `work=magenta`) and renders via the standard template system. By default it hides itself when no profile is detected; configurable via `hide_unknown`.
  • Caching: default TTL is 60s — Keychain shellouts are cheap but not free, and account switches are deliberate user actions.

Defaults

  • Added to the default `active` list between `duration` and `version`. Users who don't want it can remove it from their `active` list (it's a no-op on non-macOS anyway).
  • Profile-name and slot-name conventions match a companion setup tool (claude-switch) that manages the Keychain slots, but the component is independent — any setup that maintains the named Keychain slots will work.

Config example

```yaml
providers:
account:
cache:
ttl: 60s
active_slot: "Claude Code-credentials"
profiles:
personal: "Claude Code-personal"
work: "Claude Code-work"

components:
account:
template: "{{.Icon}}{{.Profile}}"
colors:
personal: cyan
work: magenta
default_color: gray
hide_unknown: true
```

Test plan

  • `go test ./...` passes (new component has unit tests covering: hidden states, per-profile coloring, default-color fallback, custom templates/icons, empty template)
  • `make lint` passes with 0 issues
  • Manual smoke test with both `personal` (Pro) and `work` (Team) tokens in Keychain — component correctly renders cyan `personal` / magenta `work` based on which token is in the active slot
  • Manual smoke test with no matching profile — component hides itself by default

Notes

  • The provider isn't unit-tested directly because it shells out to `security`. If you'd prefer it be testable, I can refactor to inject a `keychainReader` interface — happy to do so in a follow-up.
  • The component is macOS-only by design (Keychain). On Linux/Windows the provider returns an empty profile and the component renders nothing.

Introduces an 'account' provider + component that detects which Claude
Code account is currently logged in by comparing the live OAuth token
in the macOS Keychain against saved per-profile snapshots.

The provider is a no-op on non-macOS platforms; on macOS it shells out
to `security find-generic-password` to read the active credentials
(default slot: "Claude Code-credentials") and each configured profile
slot (defaults: "Claude Code-personal", "Claude Code-work"). When the
active token matches a saved profile, the component renders a colored
label (defaults: cyan "personal", magenta "work"); when it matches no
saved slot the provider reports "unknown" and the component hides
itself by default (configurable).

This is useful when running Claude Code with multiple accounts (e.g.
personal Pro + work Team) and switching between them by swapping
Keychain entries — the status line then reflects which account the
current session belongs to.

Default cache TTL is 60s to keep the cost of Keychain shellouts low
while still picking up account switches quickly.

The component is added to the default `active` list between
`duration` and `version`. Users can omit it from `active` if they
don't want it shown.

Includes unit tests for the component covering: hidden states
(missing/empty/unknown), per-profile coloring, default-color fallback
for unknown profiles, custom templates/icons, and empty template
handling. Provider is not unit-tested as it shells out to `security`;
behavior is covered manually.
Comment thread config.yaml Outdated
- ratelimit.sevenday
- changes
- duration
- account

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Shall we keep this disabled by default, as this is not a common use case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good call — agreed. Pushed in a086efb: dropped account from the default active list (both in config.yaml and the hardcoded fallback in main.go), kept the component and provider registered, and added a commented example near the bottom of config.yaml showing how to enable it.

It's only useful for users juggling multiple Claude Code logins, so
keep it registered but leave it out of the default active list. Added
a commented example near the bottom of config.yaml showing how to
enable it.
@Mirage20
Mirage20 merged commit 28d4b14 into Mirage20:main May 18, 2026
5 checks passed
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