Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
},
"metadata": {
"description": "Session optimizer, split into three independently installable plugins: context-guard (Stop-hook context budget + memory-writer checkpoint subagent + subagent spend tracker), refine-gate (UserPromptSubmit prompt-binding gate + /refine skill), and statusline (multi-line status bar + install skill).",
"version": "2.0.0"
"version": "2.1.0"
},
"plugins": [
{
Expand Down Expand Up @@ -57,8 +57,8 @@
{
"name": "statusline",
"source": "./plugins/statusline",
"description": "Multi-line Claude Code statusline with RGB-gradient context bars tied to per-model checkpoint thresholds (shared with context-guard), monthly cost tracking, per-session telemetry, rate-limit gauges, and live subagent spend. Ships an install skill that copies the bundled assets into ~/.claude and wires settings.json.",
"version": "2.0.0",
"description": "Multi-line status bar: a discrete heat-track context bar tied to per-model checkpoint thresholds (shared with context-guard), one deduplicated cost ledger that prices each session from its own transcript plus its subagents, 5h/7d rate-limit gauges with burn-rate pacing (the projection of usage at reset, not just the percentage), per-session telemetry (tok/s, compactions, prompt-cache countdown), and terminal-width fitting that drops the lowest-priority segments instead of letting the host truncate. Words, not emoji. Ships an install skill.",
"version": "2.1.0",
"author": {
"name": "Clement Deust",
"email": "admin@ai-architect.tools"
Expand Down
30 changes: 25 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,39 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install pytest
sudo apt-get update
sudo apt-get install -y shellcheck

# Pinned rather than taken from apt: the distro build is several releases
# behind, and the two versions do not report the same findings — it raises
# SC2317 where 0.11.0 raises SC2329, and SC2015 on `A && B || true` which
# 0.11.0 no longer flags. An unpinned linter makes a local run greener
# than the gate, which is how three findings reached CI unseen.
- name: Install shellcheck 0.11.0
run: |
v=v0.11.0
curl -fsSL "https://github.com/koalaman/shellcheck/releases/download/${v}/shellcheck-${v}.linux.x86_64.tar.xz" \
| sudo tar -xJf - --strip-components=1 -C /usr/local/bin "shellcheck-${v}/shellcheck"
shellcheck --version

- name: Refine gate contract tests
run: pytest tests/test_refine_gate.py -v

- name: Subagent tracker tests
run: pytest tests/test_subagent_usage.py -v

- name: Statusline unit tests
- name: Statusline heat-track tests
run: bash tests/statusline/test_heat_rgb.sh

- name: Shellcheck statusline script
run: shellcheck plugins/statusline/assets/statusline-command.sh
- name: Statusline fitting, pace and module tests
run: bash tests/statusline/test_fit_and_pace.sh

- name: Shellcheck statusline renderer, modules, ledger and tests
run: |
shellcheck plugins/statusline/assets/statusline-command.sh
shellcheck plugins/statusline/assets/statusline-lib/*.sh
shellcheck plugins/statusline/assets/costs.sh
# The suites are shell too, and a checker that skips them lets the
# code that guards the renderer rot unwatched.
shellcheck tests/statusline/*.sh

- name: Validate marketplace, plugin, and hook JSON
run: |
Expand All @@ -45,3 +64,4 @@ jobs:
done
python -m json.tool plugins/statusline/assets/statusline-budget.json > /dev/null
python -m json.tool plugins/statusline/assets/ctxguard-thresholds.json > /dev/null
python -m json.tool plugins/statusline/assets/pricing.json > /dev/null
77 changes: 77 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,83 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.1.0] - 2026-07-26

Statusline only. No change to context-guard or refine-gate.

### BREAKING

- **`statusline-costs.py` is removed.** Every dollar figure now comes from one
ledger, `costs.sh` over `~/.claude/statusline-costs.jsonl`. The Python
aggregator summed every assistant line of every transcript and over-counted
~2.2x, because Claude Code re-logs one API response 2-3 times (streaming /
tool continuation); a correct total must deduplicate on
`message.id:requestId` before pricing. Measured over 172 local transcripts:
$3438.84 deduped vs $7645.04 raw. `costs.sh` also prices the full recursive
`<transcript>/subagents/` subtree, so Task, worktree-isolated and workflow
agents are all billed — none of them appear in Claude Code's own
`.cost.total_cost_usd`. Installs carrying a stale `~/.claude/statusline-costs.py`
should delete it; the SessionStart hook now does so.
- **The renderer ships as a directory.** `statusline-command.sh` is a
composition root that sources `statusline-lib/*.sh`, which must be installed
next to it. A missing module is a hard failure that names the file rather
than a partial statusline. `$STATUSLINE_LIB` overrides the location.

### Added

- `costs.sh` + `pricing.json` as bundled assets (the ledger and its prices).
- Terminal-width fitting: each line is held to 85% of the probed width, and
`fit_line` drops whole trailing segments — lowest priority first — rather
than letting the host truncate mid-word and cost the block a row. Width is
probed from the controlling tty, `$COLUMNS`, then `tput cols` (only when
stdout is a terminal); `$STATUSLINE_COLS` overrides.
- Verbosity preset now falls back to `s` below 90 columns. The config's
`"size"` is a preference capped by width; `$STATUSLINE_SIZE` remains a hard
pin honoured at any width.
- **Pace** on both rate-limit windows: used% over the share of the window
elapsed, which is the linear projection of usage at reset (`1.0x` lands
exactly on the cap). The percentage carries the worse of the absolute and
pace severities; the pace figure carries its own. Nothing is printed below
10% of the window elapsed, where the extrapolation is not informative.
- Tests: `tests/statusline/test_fit_and_pace.sh` (46 tests — fitting, pace,
severity, the width probe, preset resolution, the module loader's failure
path, and the §4.1 size cap), `tests/statusline/measure_widths.sh`
(per-preset width measurement).
- CI now shellchecks `tests/statusline/*.sh` as well as the assets. A checker
that skips the suites lets the code guarding the renderer rot unwatched.

### Changed

- The identity line renders `model | dir | effort | thinking`. Segment order is
priority order under width fitting, and the previous order put `dir` last,
which made the working directory the first thing dropped on a narrow
terminal.
- The renderer is split into ten modules, one concern per file, none over 500
lines (`rules/coding-standards.md` §4.1; the single file had reached 1022).
Behaviour-preserving: verified byte-identical across a 34-configuration
preset x width golden render.
- Docs: both READMEs described an emoji-based layout that the word-based
design-system rendering had already replaced.

### Fixed

- `stat -f` is BSD-only; every mtime read now goes through `file_mtime`, which
tries the BSD and GNU spellings. On Linux the bare call silently read 0,
forcing a cache refresh on every invocation.
- A non-numeric `used_percentage` (`"n/a"`) rendered as a healthy 0%: awk reads
an unquoted non-numeric token as an uninitialised variable. Values are now
validated before awk sees them.
- `tput cols` returns terminfo's blind 80 when stdout is a pipe, which is how
the host captures the renderer — it is now consulted only when stdout is a
terminal, so IDE and web sessions no longer silently downgrade.
- A non-numeric `$STATUSLINE_COLS` was printed straight through, breaking every
arithmetic width comparison downstream. The override is an escape hatch, not
an exemption from `probe_cols`'s postcondition: an invalid value now falls
through to the probes.
- The terminal-size probe leaked `Device not configured` on every refresh with
no controlling tty: the failing redirection is reported by the shell itself,
so the whole group is now redirected, not just the command.

## [2.0.0] - 2026-07-22

### BREAKING
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ ones you want; none requires the others.
|---|---|---|
| [**context-guard**](plugins/context-guard) | `/plugin install context-guard@session-optimizer-marketplace` | A `Stop` hook enforces a per-model context budget: at the WARN threshold it writes a mechanical checkpoint stub and delegates persistence to a budgeted `memory-writer` subagent as a reflection pause; at the hard cap it forces checkpoint → `/clear` → resume. A `SubagentStop` tracker surfaces true session spend (main thread + subagents). |
| [**refine-gate**](plugins/refine-gate) | `/plugin install refine-gate@session-optimizer-marketplace` | A `UserPromptSubmit` hook + `/refine` skill that bind vague prompt references ("the SSE solution", "like before", "still broken") to concrete artifacts with evidence, then select an execution strategy from a research-backed table — before any code is touched. |
| [**statusline**](plugins/statusline) | `/plugin install statusline@session-optimizer-marketplace` | A multi-line status bar: RGB-gradient context bar tied to per-model checkpoint thresholds, cost, telemetry (tok/s, compactions, cache countdown), rate-limit gauges, live subagent spend. Ships an install skill — after installing, ask Claude to "install the statusline" and it wires everything. |
| [**statusline**](plugins/statusline) | `/plugin install statusline@session-optimizer-marketplace` | A multi-line status bar: discrete heat-track context bar tied to per-model checkpoint thresholds, one deduplicated cost ledger covering subagent spend, telemetry (tok/s, compactions, cache countdown), rate-limit gauges with burn-rate pacing, and terminal-width fitting. Ships an install skill — after installing, ask Claude to "install the statusline" and it wires everything. |

## Why

Expand Down
4 changes: 2 additions & 2 deletions plugins/statusline/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "statusline",
"description": "Multi-line Claude Code statusline (Catppuccin Mocha) with RGB-gradient context bars tied to per-model checkpoint thresholds, monthly cost tracking, per-session telemetry (tok/s, compactions, prompt-cache countdown), rate-limit gauges, and live subagent spend. Ships an install skill that copies the bundled assets into ~/.claude and wires settings.json.",
"version": "2.0.0",
"description": "Multi-line Claude Code statusline with a discrete heat-track context bar tied to per-model checkpoint thresholds, one deduplicated cost ledger covering subagent spend, per-session telemetry (tok/s, compactions, prompt-cache countdown), rate-limit gauges with burn-rate pacing, and terminal-width fitting. Words, not emoji: every value is named. Ships an install skill that copies the bundled assets into ~/.claude and wires settings.json.",
"version": "2.1.0",
"author": {
"name": "Clement Deust",
"email": "admin@ai-architect.tools"
Expand Down
Loading
Loading