Skip to content

Elide long branch names, and add a hydration reminder - #8

Merged
oleg-koval merged 7 commits into
mainfrom
feat/branch-trim-and-hydration
Aug 6, 2026
Merged

oleg-koval merged 7 commits into
mainfrom
feat/branch-trim-and-hydration

Conversation

@oleg-koval

Copy link
Copy Markdown
Owner

TL;DR (for humans)

Two things, both from working with the bar rather than reading the code.

Long branches ate the line. A 69 character branch pushed ●11 ↓34 off the end, so the markers you watch while working were the ones you lost. Branch names over 28 cells now keep both ends and elide the middle: dubo-175-retire-k8s-lease-leader-election-from-the-sync-path-kill-gic becomes dubo-175-retir…path-kill-gic. Ticket prefix at the front, subject at the back, counts back on screen.

Hydration reminder. 💧 47m after 45 minutes without a drink, 💧 1h40m drink at twice that. Invisible until due, same as the break nudge, and it shares the same idle-gap clock.

Nothing changes for short branch names, and both reminders are one env var away from off.


Behaviour

--rested break: resets work clock and water
--drank drank at my desk: resets water only
--rest-status prints both clocks and both thresholds
10 min idle resets both, since getting up is when you refill

New knobs: GLINT_BRANCH_MAX (28), GLINT_WATER_EVERY (45), GLINT_WATER=0.

Notes for the reviewer

  • Both clocks are read and written by one clocks() function. Two separate trackers on one state file would race each other; rest_minutes() is now a thin wrapper, so existing callers and tests are untouched.
  • shorten_branch favours the prefix on odd budgets (a ticket id is worth more than one trailing character) and floors at 8 cells, so a tiny GLINT_BRANCH_MAX cannot elide a name down to punctuation.

Receipts

  • 79 tests pass (was 67). The long-branch case is an end-to-end render against a real git repo asserting ●1 survives, dubo-175 survives, and the full branch name does not appear.
  • That test initially failed for an unrelated reason worth knowing: git init with no commit leaves an unborn branch, rev-parse --abbrev-ref HEAD answers HEAD, and glint skips the git segment entirely. The fixture now commits first.
  • Rendered by hand at 52/47 min and 95/100 min to confirm both ladders escalate together, then --drank followed by --rest-status to confirm water resets while the work clock keeps running.

Your screenshot showed the problem: a 69 character branch
(dubo-175-retire-k8s-lease-leader-election-from-the-sync-path-kill-gic) filled
the line, and the markers you actually watch while working, the dirty count and
ahead/behind, got pushed past the edge. Branch names longer than 28 cells are
now elided in the middle, keeping the ticket prefix and the subject and losing
the words between them: dubo-175-retir...path-kill-gic. Budget is
GLINT_BRANCH_MAX, with a floor of 8 cells so it can never elide to nothing.

Hydration joins the rest group on the same terms as the break nudge: invisible
until due, 45 minutes by default, firmer at twice that. It shares the idle-gap
clock rather than keeping its own, so both are read and written by one function
(two writers on one state file would race). A break resets water too, since
getting up is when you refill the glass, which leaves --drank for the times you
drink at your desk. --rest-status now prints both clocks.

The long-branch test builds a real git repo with a commit, because an unborn
branch makes rev-parse answer HEAD and the git segment never renders at all.

79 tests.

Co-Authored-By: Claude Code <[email protected]>
@coderabbitai

coderabbitai Bot commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@oleg-koval, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 932bf89f-fc5e-4195-ac4f-92604df9f41b

📥 Commits

Reviewing files that changed from the base of the PR and between a974463 and 658f916.

📒 Files selected for processing (4)
  • README.md
  • glint.py
  • install-codex.sh
  • test_glint.py
📝 Walkthrough

What changed: Added hydration tracking, long-branch elision, and Codex CLI support with tmux integration.

  • Logic: Hydration reminders use configurable thresholds, while 10 minutes of idle time resets both clocks.
  • API surface: Added --drank, dual-clock --rested and --rest-status, Codex harness handling, tmux output, explicit width, and true --print dry runs.
  • Data model: Shared clocks() state persists work and hydration timestamps with optional file locking.
  • Rendering: Long branch names preserve both ends within GLINT_BRANCH_MAX, and Codex payloads provide model, quota, and session data.
  • Config: Added GLINT_WATER_EVERY, GLINT_WATER=0, and GLINT_BRANCH_MAX; added an installer for managed Codex tmux status output.
  • Tests: Added coverage for hydration state, branch rendering, Codex session parsing, quota data, harness validation, tmux-related rendering, and end-to-end behavior.
  • Risk / watch areas: Shared rest-state writes now update two timestamps, and Codex session logs plus tmux configuration create external integration points that require compatibility checks.

Walkthrough

Version 1.3.0 adds hydration reminders, shared work and water clocks, Codex session integration, tmux installation support, configurable branch-name shortening, and updated documentation and tests.

Changes

Glint 1.3.0 feature update

Layer / File(s) Summary
Hydration clocks and status flow
glint.py, test_glint.py, README.md
Shared work and water timestamps support hydration thresholds, reset commands, dual-clock status output, and independent rendering.
Codex payload and tmux integration
glint.py, install-codex.sh, test_glint.py, README.md
Codex rollout logs are translated into status payloads. The installer configures and validates a managed tmux status block.
Configurable branch display
glint.py, test_glint.py, README.md
Long branch names are middle-elided with configurable display limits.
Release metadata and documentation
glint.py, CHANGELOG.md, README.md
The version changes to 1.3.0. Release notes and feature documentation describe the new behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Codex
  participant codex_payload
  participant glint
  participant tmux
  Codex->>codex_payload: provide session rollout logs
  codex_payload->>glint: return translated payload and quota data
  glint->>tmux: render ANSI status output
  tmux-->>Codex: display managed status-right block
Loading

Possibly related PRs

  • oleg-koval/glint#5: Adds the rest-clock functionality extended here with shared hydration tracking.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: middle-eliding long branch names and adding hydration reminders.
Description check ✅ Passed The description directly explains the branch rendering, hydration reminder, clock, configuration, testing, and Codex changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@glint.py`:
- Around line 684-689: Update water_reset’s recording path around _load_own_json
and _write_private so --drank preserves the loaded start value but always writes
last as now, preventing stale activity timestamps from affecting the next
render.
- Around line 608-609: Update the hydration state initialization around
prev_water so a missing "water" field defaults to now rather than prev_start,
while preserving the existing handling for states that already contain water.
- Around line 561-568: Update the branch-name truncation logic around the limit
calculation and name slicing to measure displayed terminal-cell width rather
than Python code-point length. Use the project’s existing terminal-width utility
if available, and select head and tail portions so the ellipsis plus both
portions stay within limit while preserving the existing minimum limit and
prefix-favoring behavior.
- Around line 601-615: Make the clock state read-modify-write operation
transactional by using the same lock across the full sequence in both clocks()
and water_reset(). Acquire the lock before _load_own_json and hold it through
the conditional _write_private call, ensuring concurrent renders and --drank
updates cannot overwrite each other; preserve the existing clock validation and
write behavior.

In `@README.md`:
- Line 49: Update the Hydration entry in the README table to accurately describe
the independent water timestamp and reset behavior: replace the “Shares the
break clock” wording with “Shares the break state file; a break resets both
clocks,” and retain the existing --drank behavior description.

In `@test_glint.py`:
- Around line 324-327: Update shorten_branch() to enforce limits using
display-cell width via vis_width(), while preserving the branch prefix and
suffix. In test_glint.py lines 324-327, add a wide-Unicode branch case and
assert vis_width(output) is at most the requested limit. In CHANGELOG.md lines
29-36, retain the “28 cells” claim only after confirming shorten_branch()
measures the retained prefix and suffix by display-cell width.
🪄 Autofix

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e691dc78-16b2-4a12-85ab-4f1e4cbb45b8

📥 Commits

Reviewing files that changed from the base of the PR and between 6887c8a and 5205c11.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • README.md
  • glint.py
  • test_glint.py

Comment thread glint.py Resolved
Comment thread glint.py Resolved
Comment thread glint.py Resolved
Comment thread glint.py Resolved
Comment thread README.md Resolved
Comment thread test_glint.py Resolved
@coderabbitai

coderabbitai Bot commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Fixes Applied Successfully

Fixed 3 file(s) based on 6 unresolved review comments.

Files modified:

  • README.md
  • glint.py
  • test_glint.py

Commit: a79a0cdb8d664133faf434a20411c2d1b52b5f23

The changes have been pushed to the feat/branch-trim-and-hydration branch.

Time taken: 3m 13s

coderabbitai Bot and others added 2 commits August 5, 2026 11:51
Fixed 3 file(s) based on 6 unresolved review comments.

Co-authored-by: CodeRabbit <[email protected]>
No agent CLI other than Claude Code lets you supply the status line as a
command. Verified rather than assumed: Codex 0.146's tui.status_line takes a
fixed list of built-in item ids (openai/codex#20244, #17827), opencode 1.17 has
no statusLine anywhere in its shipped config schema or its 130MB bundle (the
proposal is anomalyco/opencode#30295, and a search summary claiming it shipped
is wrong), Hermes documents its bar as fixed, and the installed Cursor CLI
binary contains no statusline strings at all.

Codex does not need a hook. It already writes what matters to
~/.codex/sessions/<date>/rollout-*.jsonl: token_count records carrying
last_token_usage, cached_input_tokens and model_context_window, plus rate_limits
with used_percent, window_minutes and resets_at. codex_payload() translates
those into the same shape Claude Code pipes in, so nothing downstream changes,
and --tmux renders it into the tmux status bar instead of Codex's own.

main() split into argument handling plus build_line(payload), which is what
makes a second harness possible at all. The cache segment now prefers numbers
an adapter supplies, since only Claude Code has a transcript to derive them
from. to_tmux() rewrites SGR colours as tmux formats, doubles literal '#'
(tmux reads it as the start of a format) and strips hyperlinks.

Cost and lines changed are omitted for Codex because Codex does not record
them; better a missing segment than an invented number.

Two bugs the installer only revealed when run: --print fetched and overwrote
glint.py before previewing (it clobbered a working copy once), and the tmux
value nested double quotes inside a double-quoted string, which ended it
mid-path. --print is now a true dry run and the inner path is single-quoted.

88 tests.

Co-Authored-By: Claude Code <[email protected]>

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@glint.py`:
- Around line 578-582: Update the loop in the name truncation logic to avoid the
unused `ch` variable that triggers Ruff B007, either by iterating over
`range(len(name))` or renaming the variable to `_ch`; preserve the existing
head_chars and vis_width behavior.
- Around line 842-848: Update the record-reading block around _records to use a
context manager for open, and normalize the selected session_meta payload to an
empty mapping when it is null before calling meta.get("cwd"). Preserve the
existing fallback when no session_meta record exists and the OSError handling
that skips unreadable paths.
- Around line 732-742: Wrap the complete rest_reset read-modify-write flow in
_FileLock(path), including loading the previous state and writing the reset
values, so it cannot race with clocks(). Preserve the existing fallback to now
and the current success/failure return behavior.
- Around line 618-625: Update __enter__ lock acquisition to include O_NOFOLLOW
when opening self.lock_path and use non-blocking or timed flock acquisition
instead of blocking indefinitely. Preserve the existing best-effort behavior by
proceeding without the lock when acquisition is unavailable, while retaining the
current cleanup and return flow.

In `@install-codex.sh`:
- Line 62: Update the CMD construction in install-codex.sh to escape single
quotes in DEST before interpolating it into the tmux shell command, ensuring
paths containing apostrophes remain valid and cannot be parsed as shell syntax.
- Around line 109-110: Remove the `|| true` from the render validation command
in the installation flow so failures from `python3 "$DEST" --harness codex
--width 160` propagate and cause the script to exit nonzero.
- Line 26: Update the --no-rest handling in the argument parser and the tmux
command construction around CMD so GLINT_REST=0 is included in the command
environment when the option is selected, rather than only exported in the
installer process. Preserve the existing command and default rest behavior when
--no-rest is not provided.

In `@README.md`:
- Around line 209-219: Apply the two README documentation fixes: change the
fenced example containing the tmux status line to use the text language marker,
and hyphenate “300-minute window” in the quota description. Do not alter the
surrounding content.

In `@test_glint.py`:
- Around line 399-405: Prevent both render tests from modifying shared rest or
water state: in test_glint.py lines 399-405, add GLINT_REST_STATE pointing
inside the TemporaryDirectory home and set GLINT_WATER=0 in the subprocess
environment; in test_glint.py lines 413-417, isolate build_line’s state with a
temporary GLINT_REST_STATE path or disable both GLINT_REST and GLINT_WATER.
🪄 Autofix

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e58f090a-b769-4907-a691-8b734af5c8d0

📥 Commits

Reviewing files that changed from the base of the PR and between 5205c11 and a974463.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • README.md
  • glint.py
  • install-codex.sh
  • test_glint.py

Comment thread glint.py Resolved
Comment thread glint.py Resolved
Comment thread glint.py Resolved
Comment thread glint.py Resolved
Comment thread install-codex.sh Resolved
Comment thread install-codex.sh Resolved
Comment thread install-codex.sh Resolved
Comment thread README.md Resolved
Comment thread test_glint.py Resolved
@coderabbitai

coderabbitai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Fixes Applied Successfully

Fixed 4 file(s) based on 9 unresolved review comments.

Files modified:

  • README.md
  • glint.py
  • install-codex.sh
  • test_glint.py

Commit: 4df4e93d7fee4b192a28a6eddc14ee7d698e3e17

The changes have been pushed to the feat/branch-trim-and-hydration branch.

Time taken: 3m 42s

coderabbitai Bot and others added 4 commits August 6, 2026 08:30
Fixed 4 file(s) based on 9 unresolved review comments.

Co-authored-by: CodeRabbit <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: oleg koval <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: oleg koval <[email protected]>
codex_payload had two stacked attempts at the same context-manager change:

    try:
        with open(path, ...) as f:      <- no body, so this is a syntax error
    try:
        with open(path, ...) as fh:
            head = list(_records(fh.read(65536)))

IndentationError on import, so every job failed at `import glint` on both 3.8
and 3.12. Removed the orphaned two lines and kept the `fh` version, which is
the one with a body. Nothing else touched.

Co-Authored-By: Claude Code <[email protected]>
@oleg-koval
oleg-koval merged commit 2469adb into main Aug 6, 2026
7 checks passed
@oleg-koval
oleg-koval deleted the feat/branch-trim-and-hydration branch August 6, 2026 08:39
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.

1 participant