Status line and subagent status line
The context-statusline skill of the statusline package (Claude Code; the status line also on GitHub Copilot CLI) shows how full the context is, in the status line of the main session and per subagent in the agent panel. It keeps the work an issue by hand honest: you see the context grow before the warning fires.
jk@laptop:/repo Opus 4 ctx:42% (84k/200k) (feat/354-statusline) 5h:12% 7d:30% # statusLine
explorer haiku-4-5 ctx:18% (36k/200k) · scan the hooks package # subagentStatusLine, one row per subagentSubagent rows show ctx:<pct>% (<k>k/<size>k) (only <k>k without a window size; fields tokenCount, contextWindowSize). Colours of ctx (rows and main line) with a window size: yellow from 50 % of the window or 250k tokens, red from 80 % or 500k, whichever is lower (200k window: 100k/160k; 1M window: 250k/500k, so 25 %/50 %). Without a size and for 5h/7d: green below 50 %, yellow below 80 %, red above. The main line shows ctx:<pct>% (<used>k/<size>k) (1M for a 1,000,000 window); without a window size only ctx:<pct>%. Used tokens are the sum of context_window.current_usage input and cache fields, else derived from percent and size. Fields are from the official statusLine docs (context_window.context_window_size, used_percentage, current_usage), verified 2026-10-22. The subagent fields tokenCount and contextWindowSize come from the same page.
Install
pwsh <skill dir>/scripts/Install-Statusline.ps1 [-Force] [-Uninstall] [-NoContextWarning] [-WhatIf]Or run /context-statusline (/context-statusline help prints the usage). The installer sets statusLine and subagentStatusLine in ~/.claude/settings.json to node ~/.claude/skills/context-statusline/scripts/<file>.mjs: the scripts of the installed skill itself, so npx skills update refreshes the status line and no copy is made. The directory is derived from where the installer runs (a project-scoped deployment gives that project's path); it refuses when the script is not there. Other keys stay untouched, a settings.json.bak-<timestamp> is written first, and a second run changes nothing. Entries of older versions (copies under ~/.claude/apm-hub/statusline/) are migrated and the copies removed. On Windows the home directory is %USERPROFILE%, never Git Bash's HOME (which can point elsewhere, e.g. /y/): the commands carry the absolute path in forward-slash form (C:/Users/<user>/.claude/..., quoted when it contains whitespace) instead of ~/..., and a re-run migrates ~/... entries the installer wrote earlier; -Uninstall recognizes both forms. A statusLine you set yourself is replaced only with -Force; -Uninstall removes only the entries this installer wrote and old copies, never the skill files.
Installer details
- No copy:
statusLineandsubagentStatusLinebecome{"type":"command","command":"node <scripts>/<file>.mjs"}with<scripts>the skill's ownscripts/directory (written as~/...under$HOMEon Linux/macOS, as the absolute%USERPROFILE%path on Windows). <scripts>is derived from where the installer runs: in a~/.claude/skills/or~/.agents/skills/deployment each client gets its own copy (Claude Code~/.claude/skills/context-statusline/scripts, Copilot CLI~/.agents/skills/context-statusline/scripts); anywhere else (a project checkout) the directory it runs from. It refuses when that script is missing (skill deployed for the other client only).- Every other settings key is kept,
settings.json.bak-<timestamp>is written before a change, indent is 2 spaces. - Idempotent; entries of older versions (
apm-hub/statusline/copies) are migrated and their copies removed; a foreign entry is refused without-Force. - Restart Claude Code (or open a new session) to see the lines.
Context warning hook
npx skills installs no hooks, so the installer registers scripts/context-warning.sh of the skill (no copy) unless you pass -NoContextWarning:
- Claude Code:
hooks.UserPromptSubmitin~/.claude/settings.json,{"hooks":[{"type":"command","command":"bash <scripts>/context-warning.sh","timeout":5}]}. - Copilot CLI (
-Client copilot|all):hooks.postToolUsein<copilot home>/settings.json,{"type":"command","bash":"bash <scripts>/context-warning.sh","timeoutSec":5}. Verified live against Copilot CLI 1.0.105:hooksin the usersettings.jsonare read (same schema as.github/hooks/*.json, documented incopilot help config), the payload carriessessionIdbut notranscriptPath, so the hook reads${COPILOT_HOME:-~/.copilot}/session-state/<sessionId>/events.jsonl(on Windows~isUSERPROFILEconverted to/c/..., not Git Bash'sHOME). - Idempotent, foreign hooks are kept, the same backup and
-WhatIfrules apply;-Uninstallremoves only our hook entry (and an emptiedhookskey).
The context size is input_tokens + cache_read_input_tokens + cache_creation_input_tokens of the last usage line in the last 2 MB of the transcript (Copilot: the last session.usage_record, inputTokens). At or above the threshold the hook prints systemMessage (the user sees it in Claude Code) and additionalContext (the model sees it; on Copilot only the top-level additionalContext reaches the model, the nested hookSpecificOutput of Claude Code is ignored there; the hook prints both). On Copilot the systemMessage is not visible in -p mode and unverified interactively, so the user hint there is not guaranteed; the model hint is: finish the step, write a short hand-off, then /clear (or /compact).
| Variable | Default | Meaning |
|---|---|---|
CONTEXT_WARN_TOKENS | derived | Context size from which the hook warns; default below |
CONTEXT_WARN_STEP | 100000 | Growth before the next warning; the state resets below the threshold |
CONTEXT_WARN_DEBUG | unset | 1 prints a note on stderr when payload or transcript cannot be read |
Default of CONTEXT_WARN_TOKENS: with a known window size min(50 %, 250k) of it (the yellow ctx colour of the status line: 200k window 100k, 272k window 136k, 1M window 250k), else 150000. An explicit valid value always wins. The message ("limit <n>k") names the threshold actually used.
Where the hook gets the window size (checked against the scripts and the recorded fixtures, 2026-11-05):
- Copilot CLI:
maxPromptTokensof thesession.usage_recordinevents.jsonl(verified incopilot-events.jsonl; thepostToolUsepayload itself carries no size). - Claude Code: the
UserPromptSubmitpayload carriessession_idandtranscript_path; a window size field there is unverified and not read. The hook reads themodelof the last usage line of the transcript and takes 1M when the id ends in[1m](unverified assumption about the transcript content). Otherwise the size is unknown and150000stays; setCONTEXT_WARN_TOKENSfor a 1M model without that suffix.
The variables are read by the script, not by a client: they work for every host as long as they are in the hook's process environment. Claude Code: "env": {"CONTEXT_WARN_TOKENS": "400000"} in settings.json (verified). Copilot CLI: no documented way verified here; export them in the shell profile that starts copilot.
Invalid values (non-numeric, empty, more than 9 digits) fall back to the defaults (for the threshold: the derived default). State lives in $TMPDIR/<host>-context-warning-<session>. jq is optional (a bash scanner parses the payload without it); every path exits 0 and nothing touches the network.
GitHub Copilot CLI
Copilot CLI has an experimental statusLine and no subagent equivalent. Install-Statusline.ps1 -Client copilot (or all):
- sets
statusLineto{"type":"command","command":"node ~/.agents/skills/context-statusline/scripts/statusline.mjs","padding":1}in~/.copilot/settings.json(or$COPILOT_HOME/settings.json): the Copilot deployment of the skill, which must exist (run from the~/.claude/skills/copy the installer still picks~/.agents/skills/for Copilot and refuses when it is missing) - adds
STATUS_LINEonce tofeature_flags.enabled, keeping other flags and keys - same backup, idempotency,
-Forceand-WhatIfrules as for Claude Code;-Uninstallremoves the entry and script but leaves theSTATUS_LINEflag (another status line may rely on it)
The script prefers context_window.current_context_used_percentage (matches /context) over used_percentage. Copilot sends no rate_limits, so 5h/7d is omitted; the size part appears only if Copilot sends context_window_size. The Copilot payload fields (cwd, session_id, model.id, model.display_name, workspace.current_dir, context_window.* incl. context_window_size, cost.total_premium_requests) are taken from community guides, not from official documentation, and may change while the feature is experimental.
Requirements and behaviour
- Node 22 or newer at run time; no packages. The same command works on Linux, macOS and Windows (
~and/are expanded by Claude Code, through Git Bash if present, else PowerShell). The installer needs PowerShell 7+. - The scripts run on every refresh: no network,
git --no-optional-lockswith a 1 s timeout, always exit 0. Missing or null fields are skipped; garbage on stdin gives defaults (status line) or no output (subagent line).