Skip to content

fix(widget): claude-account-email respects CLAUDE_CONFIG_DIR - #339

Merged
sirmalloc merged 2 commits into
sirmalloc:mainfrom
CorticalCode:fix/317-account-email-config-dir
Apr 27, 2026
Merged

sirmalloc merged 2 commits into
sirmalloc:mainfrom
CorticalCode:fix/317-account-email-config-dir

Conversation

@CorticalCode

@CorticalCode CorticalCode commented Apr 26, 2026 •

Copy link
Copy Markdown
Contributor

Closes #317.

The widget reads the same .claude.json no matter what CLAUDE_CONFIG_DIR is set to, so every profile ends up showing the same account email.

The path was built like this:

path.join(getClaudeConfigDir(), '..', '.claude.json')

That works for the default ~/.claude config dir, since going up one level lands at $HOME where .claude.json actually lives. But when someone sets CLAUDE_CONFIG_DIR=~/.claude-work, the .. still lands at $HOME, so every profile keeps reading the same file.

The reason it's not a simple fix: .claude.json lives at $HOME by default, but Claude Code moves it inside CLAUDE_CONFIG_DIR when that env var is set. The path needs to branch on whether the env var is there:

function getClaudeJsonPath(): string {
    const envConfigDir = process.env.CLAUDE_CONFIG_DIR;
    if (envConfigDir) {
        return path.resolve(envConfigDir, '.claude.json');
    }
    return path.join(os.homedir(), '.claude.json');
}

A few small extra changes I made in the same render method:

  • Removed an existsSync check before readFileSync. The outer try/catch already handles missing files, and dropping the check also closes a small race window between the two calls.
  • Dropped a redundant path.resolve on a path that was already absolute.
  • Tightened the email check from if (!email) to typeof email === 'string' && email.length > 0. The old check would let a non-string emailAddress field through, so {"emailAddress": 12345} would have rendered as Account: 12345.

Tests

Three new tests:

  1. Widget reads from $CLAUDE_CONFIG_DIR/.claude.json when the env var is set. This is the regression test.
  2. Widget returns null when CLAUDE_CONFIG_DIR points at a directory with no .claude.json, even if $HOME/.claude.json exists. Guards against the old fallback coming back.
  3. Non-string emailAddress returns null.

All existing tests still pass. bun run lint, bun test, and bun run build are all clean.

@daren-porter — if you have a minute, could you check this against your work/personal alias setup? The new tests mirror what you described in the issue, but a real-world confirmation would help.

CorticalCode and others added 2 commits April 26, 2026 00:58
Closes sirmalloc#317.

The widget computed the .claude.json path as ${configDir}/../.claude.json,
which only happens to work when configDir is the default ~/.claude (going
up one level lands at $HOME). When CLAUDE_CONFIG_DIR points elsewhere
(e.g. ~/.claude-work), the same .. heuristic still lands at $HOME, so
all profiles read the same .claude.json and display the same account
email — the symptom reported in the issue.

Fix: branch the path resolution on whether CLAUDE_CONFIG_DIR is set.
Claude Code stores .claude.json inside CLAUDE_CONFIG_DIR when that env
var is set, otherwise it lives at ~/.claude.json.

Also tightened the surrounding code while in the area:
- Drop redundant existsSync check (readFileSync ENOENT is already caught)
- Drop redundant path.resolve on already-absolute paths
- Tighten email field check from truthy (!email) to typeof+length, so a
  non-string oauthAccount.emailAddress can't render as Account: 12345

New tests cover:
- $CLAUDE_CONFIG_DIR/.claude.json is read when env var is set (regression)
- $HOME/.claude.json is NOT silently read when CLAUDE_CONFIG_DIR points
  to a dir without one (no profile leak)
- Non-string emailAddress returns null (typeof guard)
@sirmalloc
sirmalloc merged commit 6f87563 into sirmalloc:main Apr 27, 2026
3 checks passed
@sirmalloc

Copy link
Copy Markdown
Owner

Thanks. I made one small tweak the centralize the logic to grab the json path in case we need to use it outside that widget in the future.

@CorticalCode
CorticalCode deleted the fix/317-account-email-config-dir branch April 27, 2026 16:01
tahodev pushed a commit to tahodev/ccstatusline that referenced this pull request Oct 20, 2026
…oc#339)

* fix(widget): claude-account-email respects CLAUDE_CONFIG_DIR

Closes sirmalloc#317.

The widget computed the .claude.json path as ${configDir}/../.claude.json,
which only happens to work when configDir is the default ~/.claude (going
up one level lands at $HOME). When CLAUDE_CONFIG_DIR points elsewhere
(e.g. ~/.claude-work), the same .. heuristic still lands at $HOME, so
all profiles read the same .claude.json and display the same account
email — the symptom reported in the issue.

Fix: branch the path resolution on whether CLAUDE_CONFIG_DIR is set.
Claude Code stores .claude.json inside CLAUDE_CONFIG_DIR when that env
var is set, otherwise it lives at ~/.claude.json.

Also tightened the surrounding code while in the area:
- Drop redundant existsSync check (readFileSync ENOENT is already caught)
- Drop redundant path.resolve on already-absolute paths
- Tighten email field check from truthy (!email) to typeof+length, so a
  non-string oauthAccount.emailAddress can't render as Account: 12345

New tests cover:
- $CLAUDE_CONFIG_DIR/.claude.json is read when env var is set (regression)
- $HOME/.claude.json is NOT silently read when CLAUDE_CONFIG_DIR points
  to a dir without one (no profile leak)
- Non-string emailAddress returns null (typeof guard)

* chore: Centralize implementation of getClaudeJsonPath similar to getClaudeSettingsPath and getClaudeConfigDir

---------

Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
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.

claude-account-email widget ignores CLAUDE_CONFIG_DIR when multiple profiles are active

2 participants