---
name: setup-statusline
description: Manually install the maxvision statusline. Copies wrappers to ~/.claude/hooks/ (stable user-scope location) and writes the absolute path to ~/.claude/settings.json `statusLine.command`. Backs up any existing statusLine entry. The SessionStart auto-install hook normally handles this — use this command if you opted out via MAXVISION_SKIP_AUTO_STATUSLINE=1 or want to force a fresh install.
allowed-tools:
  - Bash
---

# Setup Statusline

Writes the statusline configuration so the maxvision statusline appears at the
bottom of every Claude Code session. Uses the **GSD-style pattern**: wrappers
live in `~/.claude/hooks/` (stable across plugin updates), and
`~/.claude/settings.json` `statusLine.command` references them by absolute
path. We do NOT use `${CLAUDE_PLUGIN_ROOT}` because Claude Code does not expand
that variable in `statusLine` context (only in hooks/MCP JSON configs).

This skill simply re-invokes the same `maxvision-statusline-auto-install.py`
hook that runs on every SessionStart — so the logic is identical: copy
wrappers, stamp version header, update settings.json with absolute path,
backup any pre-existing entry.

## Usage

```bash
set -euo pipefail
# Bypass the MAXVISION_SKIP_AUTO_STATUSLINE opt-out so the manual recovery
# command always runs, even for users who disabled the SessionStart hook.
# Without this unset, the hook short-circuits and the manual command becomes
# a no-op — defeating the purpose of the recovery path.
unset MAXVISION_SKIP_AUTO_STATUSLINE
python3 "${CLAUDE_PLUGIN_ROOT}/hooks/maxvision-statusline-auto-install.py"
```

`${CLAUDE_PLUGIN_ROOT}` DOES expand inside `Bash` tool invocations from
plugin-bundled skills (this is the Skill execution context, NOT statusLine
context). The hook resolves its own absolute paths internally via `__file__`.

## Restart guidance

After running, close all Claude Code sessions and reopen. The statusline
appears at the bottom of the new session.

## Rollback

If you want to restore the previous statusLine, edit `~/.claude/settings.json`
and copy any `_statusLine_backup_<timestamp>` field value back into the
`statusLine` field.

## Drift detection

The auto-install hook also runs on every SessionStart and compares the version
header stamped on `~/.claude/hooks/maxvision-statusline.{sh,ps1,mjs}` against
the current plugin VERSION. If they differ (e.g. you ran `claude plugin
update` and the plugin shipped a new wrapper), the hook automatically recopies
the fresh wrappers from plugin cache. No manual re-run needed.

## Phase A — rate-limit bars + cache indicator (2026-05-26)

The statusline reads `rate_limits.{five_hour,seven_day}.used_percentage` +
`resets_at` and `context_window.current_usage.cache_{read,creation}_input_tokens`
from the Claude Code stdin JSON (CC ≥ 2.1.90). When present, the following
segments append after the context bar:

- `5h ██░░░░░░░░ 24% [3h41m]` — session 5h rate-limit usage + reset countdown
- `7d ████░░░░░░ 41% [4d 12h]` — weekly rate-limit usage + reset countdown
- `cache:↻` — cache HIT this turn (`cache_read_input_tokens > 0`)
- `cache:+` — cache WRITE this turn (`cache_creation_input_tokens > 0`)

Bar color reflects urgency: dim < 70%, yellow 70-89%, red ≥ 90%.

Set `MAXVISION_STATUSLINE_USAGE_BARS=0` to disable. On older Claude Code
releases (pre-2.1.90) without these fields, the segments silently skip and the
legacy statusline behavior is preserved.

## Phase B — countdown + color thresholds + savings (2026-05-26)

The cache indicator now appends a 5-minute countdown derived from
`~/.claude/cache/maxvision/cache-state.json` (a single global file shared
across all concurrent Claude Code sessions on this machine — Anthropic's
prompt cache is account-wide):

- `cache:↻ 4:32` — cache HIT this turn, 4m32s before the prompt cache expires (dim).
- `cache:↻ 2:18` — same, but yellow when 1–3min left (warning).
- `cache:↻ 0:42` — same, but red when <1min left (danger).
- `cache:+ 4:59` — cache WRITE this turn (new breakpoint).
- `cache:3:14` — no cache event this turn, but the previous breakpoint is still warm.
- (empty) — cache expired and no event this turn.

A `saved:$N.NN` segment trails the indicator when the state file has
accumulated cache reads. Computed as `tokens × Anthropic-input-rate × 0.9` per
model (Opus / Sonnet / Haiku rates hardcoded; unknown models fall back to the
Sonnet rate). Lifetime-cumulative across all CC sessions on this machine.

State writes are atomic (`fs.renameSync` after tempfile) with a 3× retry on
Windows EPERM (concurrent writer / antivirus contention). Failures are
swallowed silently — the statusline never blocks a session. Per-session
`sessions/<id>/last-seen.json` dedups refresh-interval re-renders so a single
turn's cache reads are counted exactly once.

### Live countdown (opt-in)

The statusline normally re-runs only after assistant messages. To see the
countdown decrement during idle, add `refreshInterval` to your
`~/.claude/settings.json`:

```jsonc
{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/hooks/maxvision-statusline.sh",
    "refreshInterval": 10
  }
}
```

This re-runs the statusline every 10 seconds in addition to the event-driven
updates. Minimum is `1`; `10` balances liveness against overhead. The plugin
does NOT auto-set this — it respects whatever `refreshInterval` you already
configured.

> Prefer not to edit JSON by hand? Run `/maxvision:enable-live-countdown` —
> it shows a unified diff and prompts for confirmation before saving.

### Extended TTL (opt-in)

If you opted into Anthropic's 1-hour extended prompt cache via
`cache_control.ttl: "1h"`, set `MAXVISION_CACHE_TTL_SEC=3600` in your shell
profile so the countdown reflects the longer window. CC stdin does not expose
which TTL is active.

Set `MAXVISION_STATUSLINE_USAGE_BARS=0` to disable both Phase A and Phase B.
