* fix: display reset time in days when >= 24 hours
The 7-day usage window reset countdown shows raw hours (e.g., "151h 59m")
which is hard to read. Format as days + hours when >= 24h (e.g., "6d 7h").
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: cover day-based usage reset formatting
---------
Co-authored-by: KwCCCC <KwCCCC@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
* feat: show session name in statusline
Reads the session slug (auto-generated) and custom title (set via
/rename) from the transcript JSONL and displays it in dim text after
the project/git info on both expanded and compact layouts.
Custom title takes priority over auto-generated slug when both exist.
* test: add session name coverage and harden integration spawn
---------
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
* fix: prevent double-counting CLAUDE.md when cwd is home directory
When the working directory is the user's home directory, the project
scope check for {cwd}/.claude/CLAUDE.md resolves to the same path as
the user scope check (~/.claude/CLAUDE.md), causing the HUD to display
"2 CLAUDE.md" instead of "1 CLAUDE.md". Skip the project scope
.claude/ checks when cwd equals the home directory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: handle home cwd config counting edge cases
* fix: avoid home cwd double-counting for rules and settings
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
Add typeof guard to only run legacy string migration when layout is a
string. When layout is an object (written by third-party config editors),
extract nested lineLayout, showSeparators, and pathLevels to top level.
- Widen LegacyConfig type to accept Record<string, unknown>
- Export mergeConfig for direct testing of migration paths
- Add test cases for all migration scenarios
* feat: show API billing indicator in model badge
When ANTHROPIC_API_KEY is present in the environment, display
[Opus | API] in red instead of [Opus | Max]. This helps users
who manage both Max plan and API key access (e.g., work vs personal)
immediately see when they're running on API billing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Bump marketplace version to 0.0.7
---------
Co-authored-by: Fielding Johnston <fielding@justfielding.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
New default: model+project on line 1, context+usage bars combined on line 2.
All optional features (tools, agents, todos) hidden by default with
setup onboarding step to enable them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Bash tool on Windows uses Git Bash as its interpreter, so `uname -s`
returns MINGW even when the user launched Claude Code from PowerShell.
This caused setup to generate bash commands that fail in PowerShell.
Fix: Instruct Claude to use the Platform value from its environment
context (darwin/linux/win32) instead of running uname. This correctly
identifies the user's actual platform regardless of the Bash tool's
environment.
- darwin → bash commands (macOS)
- linux → bash commands (all distros: Ubuntu, NixOS, Arch, etc.)
- win32 → PowerShell commands (works on PowerShell, cmd.exe, Git Bash)
Fixes#90
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Add `--extra-cmd` CLI flag to execute a user-specified command
- Command must return JSON with a `label` field, e.g., `{"label": "$1.23/day"}`
- Includes security hardening:
- sanitize() to strip terminal escape sequences (CSI, OSC, control chars, bidi)
- maxBuffer: 10KB limit to prevent memory issues
- Label truncation to 50 chars max
- Display extraLabel in session line when present
Co-authored-by: Johnny Wang <johnnywang1991@msn.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add usageBarEnabled config option for quota display style
Add configurable display style for usage limits:
- usageBarEnabled: true → visual bar (██░░ 25%)
- usageBarEnabled: false → text format (5h: 25%)
Changes:
- config.ts: Add usageBarEnabled option (default: true)
- colors.ts: Add quotaBar() and getQuotaColor() with blue color scheme
- usage.ts, session-line.ts: Conditional rendering based on config
Closes#84
* fix: add clamp guard to coloredBar for consistency
Apply the same safeWidth/safePercent guards from quotaBar to coloredBar
to prevent RangeError on malformed input values.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: revert dist files to main
Remove build artifacts from PR diff. CI will rebuild dist/ after merge.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: add usageBarEnabled: false to baseContext
Ensures existing tests continue to check text format behavior.
The new bar format is opt-in via config.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Aster Kim <aster@spoonlabs.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix: resolve symlinks in path comparison for auto-execute
The HUD fails to output when ~/.claude is a symlink (common on macOS
with iCloud). This happens because process.argv[1] contains the symlink
path while fileURLToPath resolves to the real path.
Use realpathSync to normalize both paths before comparison.
Fixes#86
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: add try/catch fallback for realpathSync
Wrap realpathSync calls in try/catch to handle edge cases where the path
doesn't exist, has permission issues, or has a broken symlink chain.
Falls back to raw path comparison on errors.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
Document the showFileStats configuration option added in PR #71:
- Add option to Options table with description
- Add file stats display example with symbol legend
- Add showFileStats to example configuration
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat(layout): add expanded multi-line layout mode
Split the overloaded session line into semantic lines for better readability:
- Identity line: model, plan, context bar, duration
- Project line: path, git status
- Environment line: config counts (CLAUDE.md, rules, MCPs, hooks)
- Usage line: rate limits with reset times
New config options:
- `lineLayout`: 'compact' | 'expanded' (default: expanded for new users)
- `showSeparators`: boolean (orthogonal to layout)
- `usageThreshold`: show usage line only when >= N%
- `environmentThreshold`: show env line only when counts >= N
Backward compatible: old `layout` config is automatically migrated.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: address code review feedback
- Fix usage threshold to use max(5h, 7d) so high 7d usage isn't hidden
when 5h is null
- Update stale comment in session-line.ts (now compact layout only)
- Remove non-null assertions in identity.ts by hoisting planName
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: apply thresholds to compact layout for consistency
- Add environmentThreshold gating to config counts in compact mode
- Add usageThreshold with max(5h, 7d) logic to usage in compact mode
- Remove non-null assertion for planName (same fix as identity.ts)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: update tests for new lineLayout config schema
- Update config.test.js to validate lineLayout instead of layout
- Update render.test.js to use lineLayout and showSeparators
- Update index.test.js mock config with new schema
- Update integration test expected output for expanded default
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Failed or interrupted plugin installations can leave inconsistent state:
- Cache exists but not in registry (orphaned)
- Registry entry exists but no cache (stale)
- temp_local_* files left from interrupted installs
New Step 0 in setup.md:
- Detects cache/registry mismatch
- Finds leftover temp files
- Provides cleanup commands for macOS/Linux/Windows
- Includes EXDEV check for Linux (consolidated from Step 1)
Also consolidates EXDEV detection into Step 0 instead of buried in Step 1.
Fixes#59, #62, #60
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix: read OAuth credentials from macOS Keychain (Claude Code 2.x)
Claude Code 2.x stores OAuth credentials in the macOS Keychain under
"Claude Code-credentials" instead of ~/.claude/.credentials.json.
This caused the usage tracker to silently fail on macOS since the
credentials file doesn't exist.
Changes:
- Add readKeychainCredentials() to read from macOS Keychain via security CLI
- Add 1.5s timeout to prevent HUD hangs if Keychain is slow
- Fall back to file-based credentials if Keychain lacks subscriptionType
- Extract parseCredentialsData() to share validation logic
- Add readKeychain to UsageApiDeps for test isolation
- Add test for Keychain-to-file fallback behavior
The credential lookup order is now:
1. macOS Keychain (Claude Code 2.x on darwin)
2. File-based ~/.claude/.credentials.json (older versions, non-macOS)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: address review feedback for keychain credentials
- Increase keychain timeout from 1.5s to 5s to allow time for macOS
permission prompts (user needs to click "Allow")
- Fix fallback logic: always use keychain token (authoritative) when
present, supplement subscriptionType from file if needed
- Add happy-path test for complete keychain credentials
- Add test verifying keychain token is used even when subscriptionType
comes from file
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* security: harden keychain credential reading
- Use execFileSync with absolute path (/usr/bin/security) instead of
execSync with shell - prevents PATH hijacking and shell injection
- Sanitize debug logging to only log error.message, not full error
object which may contain stdout/stderr with credential data
- Add 60s backoff on keychain failures to prevent re-prompting user
on every render cycle after a timeout/denial
Addresses security review feedback from Codex.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
* fix: add autocompact buffer to context percentage calculation
Adds AUTOCOMPACT_BUFFER (45k tokens) to match /context output.
This accounts for the reserved space Claude Code uses for autocompact.
Changes:
- Add src/constants.ts with AUTOCOMPACT_BUFFER export
- Update getContextPercent to include buffer in calculation
- Add edge case guard for invalid context window sizes
- Update tests to use realistic 200k context sizes
Closes#4🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add native context percentage support for Claude Code v2.1.6+
Use `used_percentage` field from stdin when available, providing accurate
context percentage that matches `/context` output. Falls back automatically
to manual calculation for older Claude Code versions.
- Add `used_percentage` and `remaining_percentage` to StdinData type
- Add `getNativePercent()` helper with edge case handling (NaN, <0, >100)
- Update both `getContextPercent()` and `getBufferedPercent()` to prefer native
- Add 8 comprehensive tests for native percentage behavior
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: melon-hub <melon-hub@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Remove ~160 lines of DEFAULT_CONFIG assertion tests that only verify
constants equal themselves (no bug-catching value)
- Add 2 tests for layout: 'separators' path (was 40% branch coverage)
Net: 102 tests (was 123), same meaningful coverage, less maintenance.
Based on distinguished-reviewer analysis of test suite quality.
The flag was incorrectly placed as a subcommand option for `git status`,
which causes "unknown option" error on all git versions since
--no-optional-locks is a global git option.
Fixes CI test failure introduced in #63.