Commit Graph
110 Commits
Author SHA1 Message Date
990f2703b1 fix: support bare repo worktrees in GitWorktree widget (#138)
* 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>
2026-03-04 11:47:59 -05:00
Matthew Breedlove 59d43589c9 test: stabilize CI by isolating cross-file mocks
Convert module-level mocks to scoped spies and restore global stubs between tests to prevent Bun/Vitest cross-file leakage and flaky Actions failures.
2026-03-04 11:26:34 -05:00
2956842911 Attempt to add backups (#123)
* Attempt to add backups

* fix: quiet invalid claude settings parse output in TUI

---------

Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
2026-03-04 10:31:30 -05:00
Matthew Breedlove 5c0d211ddf test: isolate config-path behavior across suite 2026-03-04 09:59:30 -05:00
Matthew Breedlove 7925ec3e9a fix: support Unicode code points >4 hex digits for separators (resolves #133) 2026-03-04 09:31:53 -05:00
Matthew Breedlove 87fac953aa fix: correct ANSI reset order in applyColors (resolves #79) 2026-03-04 09:29:33 -05:00
d79eefb043 feat: Add --config flag for custom settings file path (#166)
* 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>
2026-03-04 09:10:37 -05:00
Matthew Breedlove 79b8e4e2f5 refactor: implement phase 7 test/tooling simplification with tests 2026-03-04 01:39:48 -05:00
Matthew Breedlove fc09688879 refactor: implement phase 6 jsonl/usage modularization with async prefetch tests 2026-03-04 01:28:27 -05:00
Matthew Breedlove a34a632b82 refactor: implement phase 5 utility cleanup with tests 2026-03-04 00:43:05 -05:00
Matthew Breedlove 25b69228dd feat(usage): split reset timers into block and weekly widgets
Closes #194
2026-03-04 00:14:49 -05:00
Matthew Breedlove 7e2ad30f77 fix(context): support 1M model name formats in fallback parsing
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
2026-03-03 21:49:49 -05:00
Matthew Breedlove b90840f68c refactor: implement phase 4 tui component simplification with tests 2026-03-03 20:14:30 -05:00
Matthew Breedlove b13ea14a8c fix: coerce status JSON numeric strings and bump version
Coerce numeric strings in StatusJSON parsing to keep status line rendering resilient with third-party payload tweaks.

Closes #192
2026-03-03 18:30:04 -05:00
Matthew Breedlove da7eaffe03 refactor: implement phase 3 widget pattern extraction with tests 2026-03-03 18:24:39 -05:00
Matthew Breedlove 9aea4c1265 refactor: implement phase 2 tui/settings simplification with tests 2026-03-03 12:53:21 -05:00
Matthew Breedlove 2d05b3b891 refactor: implement phase 1 terminal/render dedup with tests 2026-03-03 12:43:44 -05:00
Matthew Breedlove 6edc1b4277 feat: add git insertions and deletions widgets
Closes #115
2026-03-03 00:22:13 -05:00
Matthew Breedlove 0c6bf4b02c feat: add Link widget and fix ANSI/OSC truncation calculation
- 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
2026-03-02 23:59:14 -05:00
Matthew Breedlove eff030a9d8 Add 'star us on github' menu item, version bump to 2.1.2 2026-03-02 23:21:39 -05:00
4459379038 fix: Avoid creating an empty c:\dev\null file on windows during terminal width detection. (#132)
On Windows, the Unix-specific commands (ps, stty, tput) and shell
redirects (2>/dev/null) don't work and cause issues:
- tput doesn't exist on Windows
- 2>/dev/null creates a literal file named "null" instead of
  redirecting stderr

This fix adds a platform check at the start of getTerminalWidth()
and canDetectTerminalWidth().  We cannot rely on process.stdout.columns when run as a subprocess of claude code to tell us the actual terminal width.  By simply returning that terminal width detection is unavailable on windows, we avoid the empty file being created, and disable explicit truncation behavior since we can't detect the width.


Fixes #117

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: preserve legacy terminal width behavior on Windows

Return null/false for win32 in terminal width helpers to keep width detection disabled on Windows and avoid Unix-style fallback paths that can create C:\dev\null.

---------

Co-authored-by: ItsDaRa <ItsDaRa@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
2026-03-02 20:28:11 -05:00
a03b7c2238 feat: add API usage widgets (session, weekly, reset, context bar) (#168)
* feat: add API usage widgets (session, weekly, reset timer, context bar)

Add four new widgets that display Claude Code API usage data:
- session-usage: 5-hour session utilization with progress bar
- weekly-usage: 7-day utilization with progress bar
- reset-timer: countdown to session reset
- context-bar: context window usage with progress bar

Fetches data from /api/oauth/usage using existing OAuth credentials
(macOS Keychain + Linux file fallback). Includes 180s cache with
30s rate limiting to minimize API calls.

Also enhances ContextPercentage widget to use context_window data
from Claude Code's stdin JSON when available.

Closes #94

* fix(api-usage): zod-validate usage data and move cache to ~/.cache/ccstatusline

- parse credentials/cache/API response via zod with nullable field support\n- move usage cache+lock to ~/.cache/ccstatusline/usage.{json,lock}\n- add missing getCategory() methods on API usage widgets\n- resolve context percentage brace-style lint issue

* Refactor usage widgets and unify timer/usage display modes

Split API usage widgets into dedicated files and a shared usage utility, replacing the monolithic ApiUsage widget module.

Key changes:

- add src/utils/usage.ts for API fetch/caching, parsing, error mapping, progress-bar helpers, and shared 5-hour window math

- move widgets to standalone files: SessionUsage, WeeklyUsage, ResetTimer, ContextBar

- remove src/widgets/ApiUsage.tsx and update widget exports/registry wiring

- make BlockTimer usage-aware with usage API first and JSONL fallback via shared resolver

- make ResetTimer follow BlockTimer UX: time/progress/short-progress modes, raw value support, invert toggle, and JSONL fallback when usage timing is unavailable

- make SessionUsage and WeeklyUsage match timer interaction model: progress mode cycling, invert toggle, invert-clearing when returning to text mode, and raw-value support

- update ItemsEditor to hide/disable invert keybind when widget is in text mode

- remove eager block-metric parsing from ccstatusline render path so JSONL fallback is only invoked when usage timing is missing

- add comprehensive tests for usage window fallback behavior and widget mode/toggle/raw output behavior

Validation:

- bun test

- bun run lint

* Prefer status JSON context-window metrics with robust fallbacks

- add a shared context-window metrics utility to normalize context_window fields (window size, percentages, usage, and token snapshots)

- make context window size from status JSON authoritative for context calculations when present; derive usable limit as 80% of reported size

- keep model-id fallback behavior for missing context_window data, including case-insensitive [1m]/[1M] detection

- update Context %, Context % (usable), Context Length, and Context Bar to use status JSON first and fall back to JSONL token metrics when needed

- update Session Clock to use cost.total_duration_ms first with JSONL duration fallback

- keep Tokens Input/Output JSON-first, while reverting Tokens Cached/Total to cumulative session JSONL totals

- simplify render pipeline behavior to always parse current session JSONL token metrics when transcript_path exists

- add/expand tests for context-window parsing, denominator precedence, 1M-without-suffix scenarios, case-insensitive suffix fallback, token widget source behavior, context bar rendering, and session clock behavior

* Align Context Bar with Context Length semantics

- switch Context Bar usage basis from total current_usage (input+output+cache) to context-length usage (input+cache), matching Context Length widget

- keep statusline JSON-first behavior with JSONL/model fallbacks unchanged

- keep short-by-default progress mode and long/short toggle behavior

- update ContextBar tests for new token basis and progress-mode expectations

* usage: honor CLAUDE_CONFIG_DIR and use runtime-safe HTTPS API fetch

* Fix context bar overflow and preserve usage error states

* Group usage widgets under new Usage picker category

* Rename context remaining toggle to used/remaining shortcut

---------

Co-authored-by: Peter van Velzen <pvvelzen@emico.nl>
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
2026-03-02 17:31:12 -05:00
Matthew Breedlove fc3934097b chore: Fix for test failures when testing with vitest, remove 'test' script from package.json, prefer running tests using 'bun test' 2026-02-27 13:19:08 -05:00
3d43476d6b Free Memory Widget (#155)
* 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>
2026-02-24 14:20:00 -05:00
ecd8d0b6cc perf: cache block timer metrics to reduce I/O (#161)
* perf: cache block timer metrics to reduce I/O

Cache block start time to ~/.cache/ccstatusline/block-cache.json to avoid
parsing all JSONL files on every status line render. Cache is invalidated
when the 5-hour block expires.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use hashed per-config block cache files

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
2026-02-21 16:06:27 -05:00
Matthew Breedlove 3abc41f122 refactor git widgets to use shared git command helpers
Centralize cwd resolution and git command execution for git widgets, and expand widget-level and utility tests for failure and edge cases.

Closes #176
2026-02-21 14:49:46 -05:00
Matthew Breedlove 20691a70b0 Set Windows UTF-8 code page for piped statusline (closes #186) 2026-02-21 14:20:55 -05:00
f83e7d2f6d Add Git Root Dir widget (#119)
* Add Git Root Dir widget

Add a new widget that displays the git repository root directory name.
- Shows directory name with 📁 icon (e.g., "📁 my-repo")
- Supports rawValue option for icon-free display
- Supports hideNoGit option to hide message when not in a git repo

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Change Git Root Dir widget icon to text label

Replace 📁 emoji with "Repo:" text label for better compatibility.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Remove label from Git Root Dir widget

Display only the repository name without any prefix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix GitRootDir root path handling and raw mode

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
2026-02-21 12:00:31 -05:00
62903d8183 Add Session Name widget (#142)
* Add Session Name widget

Adds a native widget to display the Claude Code session name set via the
/rename command. The widget reads the transcript file and extracts the
customTitle from custom-title entries.

- New SessionName widget with rawValue support
- 9 unit tests
- README documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add category metadata to session name widget

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
2026-02-21 11:34:10 -05:00
0092c241a6 feat: add abbreviate home option to Current Working Directory widget (#144)
* feat: add abbreviate home option to Current Working Directory widget

Add a new 'abbreviate home' toggle (h key) that replaces the home
directory path with ~ (e.g., /Users/matt/Projects → ~/Projects).

- Can be combined with segments for paths like ~/.../Projects/my-project
- Mutually exclusive with fish-style abbreviation
- Includes tests for the new functionality

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: correct cwd home abbreviation edge cases

Preserve platform path separators when combining home abbreviation with segments.
Require exact home-directory boundary matching to avoid false substitutions.
Align one-segment abbreviateHome preview with runtime output.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
2026-02-21 11:17:41 -05:00
Ani AggarwalandGitHub 7cf85dffb1 fix: recognize [1m] suffix on all models, not just Sonnet 4.5 (#172)
The getContextConfig function was hardcoded to only match
claude-sonnet-4-5 models with the [1m] suffix. Other models like
claude-opus-4-6[1m] also support 1M context but were falling back to
the 200k default, causing incorrect context percentage display.

The [1m] suffix itself is sufficient to indicate 1M context regardless
of model family.
2026-02-21 10:58:24 -05:00
Matthew Breedlove d025c707e6 fix: prevent shortcut keys from leaking into TUI editors
Closes #184
2026-02-21 10:44:12 -05:00
Matthew Breedlove 76d9af84a5 Improve TUI widget picker UX and clear-line safety
Closes #19
2026-02-21 10:35:47 -05:00
879255523b Add line reorder move mode and fix GitWorktree tests (#154)
* fix(test): replace vi.mocked with direct mock reference in GitWorktree tests

vi.mocked(execSync) was undefined because the vi.mock factory runs
before imports resolve. Use a top-level vi.fn() reference instead.

* feat(tui): add move mode to LineSelector for reordering lines

Press 'm' to enter move mode, use arrow keys to swap lines,
Enter/Escape to exit. Visual feedback mirrors ItemsEditor pattern
with blue diamond marker and [MOVE MODE] label.

* chore: update bun.lock

* Fix for model in statusLine JSON being passed as string vs object, closes #157, version bump

* fix(test): make GitWorktree execSync mock hoist-safe

---------

Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
2026-02-02 16:03:52 -05:00
Matthew Breedlove d457e55913 Fix for model in statusLine JSON being passed as string vs object, closes #157, version bump 2026-02-02 14:32:33 -05:00
Matthew Breedlove 03d19692ab Lint fixes, version bump 2025-11-17 16:58:03 -05:00
79a954c16e Add Claude Code Session ID widget (#111)
* feat: Add Claude Session ID widget

* Add ClaudeSessionIdWidget to widget registry, add label, support raw mode, fix cross-platform issues by using session ID directly from statusline JSON

---------

Co-authored-by: Marty <marty@croakingtoad.com>
Co-authored-by: Matthew Breedlove <matt@revenite.ai>
2025-11-17 16:56:59 -05:00
da325930ad Fix: Dynamic context window calculation for Sonnet 4.5 (1M tokens) (#107)
* Fix: Dynamic context window calculation for Sonnet 4.5 (1M tokens)

- Create model-context utility with dynamic context window mapping
- Sonnet 4.5 models now use 1M context (800k usable)
- Older models default to 200k context (160k usable)
- Update ContextPercentage and ContextPercentageUsable widgets
- Update renderer.ts flex mode calculations (2 locations)
- Add comprehensive test coverage (14 new tests, 36 total passing)

Fixes incorrect percentage display for Sonnet 4.5:
- Before: 42k tokens showed 21.0% (using 200k denominator)
- After: 42k tokens shows 4.2% (using 1M denominator)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Style: Apply ESLint auto-fixes for consistency

- Standardize indentation to 4 spaces
- Apply formatting rules from eslint.config.js
- No logic changes, formatting only

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Refactor: Code review fixes for context window changes

- Fix misleading test name (line 69 of context-percentage.test.ts)
- Strengthen model ID pattern matching (claude-sonnet-4-5 vs sonnet-4-5)
- Standardize export style (inline export for consistency)

All tests passing (19/19 for affected files)
TypeScript and ESLint checks passed

* Enhance CLAUDE.md: Update piped input example for Sonnet 4.5 and add test commands

- Changed piped input example to reflect the new model ID for Claude 4.5
- Added instructions for running tests and tests in watch mode
- Updated context window metrics description to include dynamic model-based context windows

Improves clarity and usability for developers working with the project.

* Fix: Require [1m] suffix for Sonnet 4.5 1M context window detection

Address PR feedback that Sonnet 4.5 only has 1M context on API usage
when the model ID includes the [1m] suffix (long context beta access).

Changes:
- Update getContextConfig() to check for [1m] suffix (case-insensitive)
- Models without suffix now safely default to 200K context
- Add comprehensive test coverage for suffix detection
- Update all test fixtures to use correct model ID format
- Document suffix requirement in CLAUDE.md

This ensures conservative behavior - only models with explicit [1m]
suffix receive 1M context allocation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-13 08:53:54 -05:00
Ramiro RiveraandGitHub 8477dc5e6b REFactor: Simplify getBlockMetrics function and improve conditional checks in renderMultipleLines (#102) 2025-11-13 08:52:29 -05:00
Ramiro RiveraandGitHub 9f26a071a7 FEAT: Support CLAUDE_CONFIG_DIR (#99)
* chore: automatic change from linting

* feat: support CLAUDE_CONFIG_DIR on utilities

* feat: support CLAUDE_CONFIG_DIR from the main app UI

* fix: reduce duplication and handle installation using new constants

* feat: missed one place using hardcoded path

* chore: update CLAUDE.md

* docs: Update README
2025-10-07 23:36:13 -04:00
Howard ZhangandGitHub 1ad9304039 Fix bunx availability check on windows (#96) 2025-10-04 18:16:57 -04:00
Alexander BuyanovandGitHub 055bf22308 Fix #97: context widgets showing 0% due to synthetic API error messages (#98)
Investigation revealed that Claude Code now appends synthetic error messages to transcript files when API errors occur (rate limits, authentication failures, etc.).
These synthetic messages have:
- model: "<synthetic>"
- isApiErrorMessage: true
- All token usage fields set to 0

The getTokenMetrics() function in src/utils/jsonl.ts calculates the current context length by finding the most recent main chain entry(isSidechain !== true) sorted by timestamp. When an API error occurs, the synthetic error message becomes the "most recent entry", causing contextLength to be calculated as 0.
2025-10-04 18:16:15 -04:00
Matthew Breedlove bb73dd63c0 Tabs -> Spaces 2025-10-03 15:37:41 -04:00
herrytsai 19a8724989 Fix Block-Timer not showing any values 2025-09-25 11:37:14 +08:00
7140c3faa5 Fix #88: Fix Block Timer showing incorrect elapsed time due to flawed block calculation (#90)
* revert 798b637

* Fix #88: Fix Block Timer showing incorrect elapsed time due to flawed block calculation

\## Problem

The Block Timer widget was displaying incorrect elapsed times when multiple work sessions occurred on the same day with gaps between them. For example, with work sessions at:
- Morning: 11:00-16:00 (first message at 11:42, last at 14:52)
- Evening: 17:00-22:00 (first message at 17:44)

At 20:10, the Block Timer showed **4hr 10m** instead of the expected **3hr 10m**.

\## Root Cause

The existing algorithm in `findMostRecentBlockStartTime()` had a fundamental flaw in how it calculated block start times:

1. It correctly identified continuous work by finding gaps ≥ 5 hours
2. It floored the continuous work start to the hour
3. **But then it used `Math.floor(totalWorkTime / sessionDurationMs)` to calculate the current block**

This division-based approach assumed continuous 5-hour blocks without gaps:
```
[Block 0: 11:00-16:00][Block 1: 16:00-21:00]...
```

In reality, blocks have gaps between them:
```
[Block 0: 11:00-16:00]--gap--[Block 1: 17:00-22:00]...
```

\### Incorrectly Identified Cases

The algorithm failed in scenarios where:
- **Multiple work sessions with small gaps** (< 5 hours): Treated them as one continuous session and calculated wrong block boundaries
- **Current time in a gap**: Could incorrectly show elapsed time from a previous block
- **Messages spanning multiple days**: Division logic ignored actual message timestamps and gaps

\### Example of the Bug

With messages at 11:42 and 17:44, gap of ~2h 52m:
1. No 5-hour gap found → continuous work from 11:00
2. At 20:10: `totalWorkTime = 9h 10m`
3. `completedBlocks = floor(9.17 / 5) = 1`
4. `blockStart = 11:00 + (1 × 5h) = 16:00`
5. Elapsed = 20:10 - 16:00 = **4h 10m** (wrong!)

Correct calculation should be:
- Block 1: 11:00-16:00 (ended)
- Gap: 16:00-17:44
- Block 2: 17:00-22:00 (current)
- Elapsed = 20:10 - 17:00 = **3h 10m** ✓

\## Solution

Replaced the flawed division-based calculation with a proper block-building algorithm:

1. **Find definitive boundary**: Look back for 5+ hour gap (or start of data)
2. **Build blocks forward from timestamps**:
- Sort timestamps chronologically
- For each timestamp after the boundary:
   - If no current block OR timestamp is after current block end: start new block (floor to hour, add 5h for end)
   - Otherwise: timestamp is within current block
3. **Find current block**: Check if `now` falls within any constructed block's timespan
4. **Return block start** if found and has activity, otherwise null

This correctly handles gaps of any size and builds the actual block structure from message timestamps.

\## Tests Added

Created comprehensive unit tests in `src/utils/__tests__/jsonl.test.ts` covering:

\### Real Scenarios
- **Morning and evening blocks with gap**: Messages at 11:42 and 17:44 → correctly identifies 17:00 block start at 20:10
- **Multiple messages in single block**: Messages within 5 hours → single block with floored start time
- **Multi-block scenario**: Messages at 00:13, 05:56, 06:01, 14:33, 20:01 → correctly identifies 20:00 block at 22:43

\### Edge Cases
- **Current time in gap between blocks**: Returns null (no active block)
- **No messages within 5 hours**: Returns null (session expired)
- **Block boundary timing**: Correctly handles time exactly at 5-hour boundary
- **5+ hour gap detection**: Properly detects boundary when gap ≥ 5 hours
- **Messages at exact hour boundaries**: Handles flooring when message is already at :00

\### Invalid Inputs
- **Empty content**: Returns null
- **Invalid JSON**: Returns null gracefully

All tests pass with the corrected algorithm, ensuring the Block Timer and Five Hour Moons widgets now display accurate elapsed times.

---------

Co-authored-by: alexander.buyanov <alexander.buyanov@konux.de>
2025-09-24 10:07:16 -04:00
798b637c58 Fix #86 Adjust block metrics gap threshold for short breaks (#87)
Detect block boundaries after 60 minutes of inactivity instead of requiring a 5-hour gap.
This prevents block start times from carrying over into short midday breaks and ensures elapsed time matches ccusage.

Co-authored-by: alexander.buyanov <alexander.buyanov@konux.de>
2025-09-19 12:18:48 -04:00
d23af975b2 feat: Add fish-style path abbreviation to CurrentWorkingDir widget (#80)
* feat: Add fish-style path abbreviation to CurrentWorkingDir widget

- Added new toggle option for fish-style path abbreviation
- Keeps home directory as ~, first and last directories complete
- Abbreviates middle directories to first letter only
- Preserves dot for hidden directories (e.g. .config → .c)
- Maintains backward compatibility with segments feature
- Both options are mutually exclusive (fish-style takes precedence)

Example: ~/Documents/Projects/my-project → ~/D/P/my-project

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Modify cwd widget fish-style code to use handleEditorAction instead of renderEditor, misc lint fixes

---------

Co-authored-by: Jishuai <aqianlikuaizaifeng@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Matthew Breedlove <sirmalloc@gmail.com>
2025-09-19 01:25:16 -04:00
Matthew Breedlove 0a5f0e58b9 Fix for menu item description text on main menu 2025-09-18 21:31:46 -04:00
3010addb70 Fix #84: Block timer should reset after idle gap (#85)
Block windows were staying “active” after multiple hours with no token usage, so the block timer kept counting even though ccusage reported the session closed.
Aligning the activity detection with actual token usage prevents those phantom sessions and keeps the timer in sync with the upstream report.

Co-authored-by: alexander.buyanov <alexander.buyanov@konux.de>
2025-09-18 21:25:53 -04:00
Jake NelsonandGitHub 2ecaf023b7 feat: add remaining mode to context % widgets (#83) 2025-09-17 22:34:41 -04:00