Adds ccsessions to Related Projects in README and a new Integration
Example section in USAGE.md showing how to wire the cc-session-num
companion script as a Custom Command widget to display the current
session rank (#1, #2, …) in the status line.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
* feat: line-spanning foreground gradients via overrideForegroundColor
Add a `gradient:<stop>,<stop>,...` form for `overrideForegroundColor` that
paints the whole status line with a continuous gradient — each visible
character is colored by its column position, so the gradient spans the line
rather than restarting per widget. Applies to standard (non-powerline) lines;
powerline separators derive their color from adjacent backgrounds, so a
foreground gradient is intentionally not applied there.
- src/utils/gradient.ts: parse hex stops (`hex:RRGGBB` / `#RRGGBB` / bare),
interpolate in OKLab for perceptually even, non-muddy blends, and map to
truecolor or the nearest ansi256 index.
- src/utils/ansi.ts: applyLineGradient walks the assembled line with the
existing escape/cluster tokenizer, so SGR styling and OSC-8 hyperlinks pass
through untouched and visible width is unchanged (flex layout unaffected).
- src/utils/renderer.ts: applied after assembly and before truncation in the
standard path. `overrideForegroundColor` accepts the new `gradient:` form
alongside the existing `hex:` / `ansi256:` / named tagged-string forms; a
gradient spec is not treated as a per-widget solid color and degrades to a
no-op at ansi16 (keeping widgets' own colors).
Tests cover spec parsing, OKLab sampling, ansi256 quantization,
width-invariance, OSC-8 passthrough, and a renderer integration case.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat: add per-widget gradients + presets + TUI picker on the line-span core
Converges the two same-day gradient PRs into one coherent feature. #406
added line-spanning gradients via overrideForegroundColor (OKLab, zero-dep);
#404 (@akkaz) added gradient as a per-widget color with named presets and a
ColorMenu picker. Both created src/utils/gradient.ts and would conflict, so
this meshes them onto a single shared OKLab engine:
- gradient.ts: GRADIENT_PRESETS (akkaz's stops, gradient-string MIT;
rainbow/pastel re-expressed as multi-stop hue wheels for OKLab); unified
parseGradientSpec accepting presets, dash (RRGGBB-RRGGBB), and comma
(hex:..,..) forms; applyGradientToText for the per-widget sweep.
- colors.ts: per-widget gradient hook in applyColors; getColorAnsiCode
collapses a gradient to its first stop (powerline / ansi16 degrade).
- ColorMenu.tsx: 'g' opens a gradient picker (preset list + custom hex),
foreground-only, colorLevel >= 2.
- No new dependency (tinygradient dropped in favor of OKLab).
Precedence: overrideForegroundColor gradient (line-span) > widget.color
gradient (per-widget) > solid. Gradients self-degrade at render time, so
color-sanitize leaves them untouched at every level.
Builds on the per-widget design from #404 by @akkaz.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: akkaz <giomarco@cleversoft.it>
* refactor: polish gradient feature — fix truncation reset-leak, tighten, document
Pre-PR polish pass over the gradient feature.
Fix (correctness):
- renderStatusLine now applies the line-span gradient AFTER truncation, not
before. truncateStyledText cuts from the right and appends a raw "..." with no
trailing reset, so a gradient applied earlier had its closing \x1b[39m sliced
off, leaking the last color past the status line. Gradient codes are zero-width,
so the truncation measurement is unaffected by deferring. Regression test added.
Simplify:
- Add exported isGradientSpec(); reuse it across colors.ts and renderer.ts instead
of duplicating the 'gradient:' startsWith check. Drop the redundant prefix guard
in applyColors (parseGradientSpec already self-guards).
Docs:
- Document applyGradientToText's code-point (vs grapheme-cluster) iteration as a
known limitation, with the ZWJ/variation-selector consequence and the
circular-import reason it isn't unified with applyLineGradient yet.
- Note that hex:/# /bare stops are valid in both comma and dash parse forms.
- Note getColorAnsiCode's ansi16 branch intentionally emits a truecolor first-stop
escape (caller-degraded; never reached at a true ansi16 terminal).
- README + docs/USAGE.md: gradient color options (both scopes, presets, forms).
bun test 1433 pass / 0 fail; lint + tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(gradient): preserve escape sequences in widget gradients
Keep ANSI and OSC control sequences byte-for-byte intact when applying per-widget gradients so hyperlinks and pre-styled widget output are not corrupted by inserted SGR codes.
Count and color only visible non-whitespace characters while passing escape sequences through unchanged. Add a regression covering styled OSC 8 link output.
* fix(colors): suppress gradient fallback at ansi16
Prevent stored gradient color specs from emitting 24-bit SGR codes when the active terminal color level has been reduced to Basic or No Color.
Leave gradient settings intact, but return no gradient ANSI fallback at ansi16 and cover the behavior in per-widget and raw-code regression tests.
* fix(renderer): detect truncated gradient lines visibly
Preserve truncation reporting after whole-line gradients insert SGR codes between the ellipsis characters.
Check the visible text for the truncation marker instead of the raw styled bytes, and add a regression where the rendered line no longer contains a literal contiguous ellipsis.
* feat(tui): add gradients to foreground overrides
Let Global Overrides assign a whole-line foreground gradient through the same preset/custom selector used by the color screen.
Move (g) to gradient selection, add (x) as the foreground override clear key, show gradient override values in the menu, and update usage docs for the new controls and Basic/No Color degradation behavior.
In Powerline mode, carry global gradient position continuously across widget text while leaving separators and caps under Powerline contrast rules. Surface an active foreground override warning on the Powerline Setup screen so theme masking is visible.
---------
Co-authored-by: Cameron Sjo <cameronsjo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: akkaz <giomarco@cleversoft.it>
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
Adds a "Integration Example: AIWatch" section to docs/USAGE.md mirroring
the existing ccusage section, plus a Related Projects link in README, per
the placement the maintainer chose in #362.
AIWatch (ai-watch.dev) monitors live status for 30+ AI APIs/apps; the
Custom Command one-liner surfaces degraded providers in the status line
and renders empty when everything's operational.
Co-authored-by: Bentley <bentley@naemomlab.com>
* feat: Add Skills widget with cross-platform hook framework
Replaces bash/jq hook with a built-in --hook CLI handler that works
on all platforms. Widgets can declare hooks via getHooks() which are
auto-synced to Claude settings when the statusline config is saved.
* feat: tighten hook lifecycle and upgrade skills widget
Notes:\n- Hook sync now follows saved-state semantics: installing statusline syncs hooks from saved ccstatusline settings on disk, and uninstall always removes all ccstatusline-managed hooks.\n- syncWidgetHooks always strips managed hooks first, including when statusline.command is missing, then persists cleanup.\n- Skills metrics storage path is now ~/.cache/ccstatusline/skills/skills-<sessionId>.jsonl.\n- Skills unique list ordering is now most-recent-first.\n- Skills widget updates: view toggle on (v), hide-when-empty toggle on (h), explicit empty outputs when not hidden, and new list-only (l)imit editor option where 0 means unlimited (default).\n- Added list-limit custom editor flow and list-only keybind visibility in ItemsEditor.\n- Maintained Node 14 compatibility by avoiding Array.prototype.at in skills metrics parsing.\n- Added/updated regression tests for hook sync/install/uninstall behavior, skills metrics path/order, Skills widget rendering/editing, and items-editor custom keybind handling.
* chore: bump version to 2.2.1 and update release notes
---------
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
* fix: support bare repo worktrees in GitWorktree widget
The GitWorktree widget now correctly detects worktrees from bare
repositories. Previously, it only checked for `.git/worktrees/` in
the path, but bare repos store worktree metadata at
`<bare-repo>/worktrees/<name>` without the `.git` prefix.
This adds an additional check for `/worktrees/` pattern when the
`.git/worktrees/` pattern isn't found.
Fixes detection for setups like:
- Bare repo at: /path/to/repo (contains objects/, refs/, HEAD, etc.)
- Worktree at: /path/to/repo/trees/feature-x
- Git dir: /path/to/repo/worktrees/feature-x
* chore: remove accidental npm lockfile from PR branch
* chore: bump version to 2.1.10 and update recent updates
---------
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
* Add --config flag for custom settings file path
Allow users to specify an alternative settings file via `--config <path>`,
enabling distinct status line configs for different Claude Code instances.
- Add initConfigPath/getConfigPath/isCustomConfigPath to config.ts
- Fix backup path to always append .bak instead of replacing .json suffix
- Use path.dirname(SETTINGS_PATH) instead of CONFIG_DIR for mkdir
- Parse --config arg in ccstatusline.ts main() entry point
- Add tests for config path management
* Integrate --config flag with Claude Code install commands
When a custom config path is active, the install-to-Claude-Code feature
now appends --config <path> to the status line command. Also updates
isInstalled detection to recognize commands with the --config suffix.
- Add isKnownCommand() to deduplicate command-matching logic
- Add shell-safe path quoting for --config values with spaces/special chars
- Add buildCommand() to append --config when custom path is active
- Refactor isInstalled() to use isKnownCommand()
- Use isKnownCommand() in App.tsx install flow
- Add tests for isKnownCommand() and buildCommand() with CLAUDE_CONFIG_DIR safety net
* Show custom config path in TUI header
When a custom --config path is active, display it below the title bar
so users can see which settings file is being edited.
* fix: use platform-appropriate quoting for --config path
* chore: bump version to 2.1.8 and update recent updates
---------
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
Handle [1M], (1M), and optional context labels when inferring model context size; use model id + display_name in context widgets and add regression coverage for ctx, ctx(u), and context bar.
Closes#193
- add a new Link widget with OSC8 rendering, preview parity, and raw mode behavior
- fix truncation and visible-width calculation to handle ANSI/OSC sequences safely
- bump package version to 2.1.3
- update README recent updates and widget documentation
Resolves#188
* FreeMemory widget:
Description: Shows system memory usage (used/total) in a compact format like Mem: 12.4G/16.0G
Features:
- On macOS: Uses vm_stat to calculate memory like htop (Active + Wired pages)
- On other platforms: Falls back to Node.js os.freemem()/os.totalmem()
- Smart byte formatting (G, M, K, B)
- Supports raw value mode (omits "Mem:" prefix)
- Default color: cyan
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Version bump and README update
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>