Always shows the context window usage in tokens

A Claude Code mod that keeps the context window usage pinned under the prompt:
ctx ███░░░░░░░ 25% · 50k/200k
It refreshes after every main-thread turn (session.measure) with the same figures the native status line reads (used_percentage, total_input_tokens, context_window_size). Before the first response, or right after a compaction, it shows only the window size: ctx —/200k.
At the prompt of a terminal session:
/plugin install context-meter --marketplace Voltaire405/claude-mods
Answer y to add the marketplace, then pick a scope (user scope loads it in every session and repository). From a shell: claude plugin install context-meter --marketplace Voltaire405/claude-mods.
claude plugin validate ./context-meter
claude plugin test ./context-meterhooks/register.ts 26 lines1import type { Register, SessionContextUsage } from 'claude-code'
2
3const BAR_WIDTH = 10
4
5const compact = (n: number) => (n >= 1000 ? `${Math.round(n / 1000)}k` : `${n}`)
6
7export const formatContext = ({ tokens, window, percent }: SessionContextUsage) => {
8 if (tokens === undefined || percent === undefined) return `ctx —/${compact(window)}`
9 const filled = Math.min(BAR_WIDTH, Math.round((percent / 100) * BAR_WIDTH))
10 const bar = '█'.repeat(filled) + '░'.repeat(BAR_WIDTH - filled)
11 return `ctx ${bar} ${percent}% · ${compact(tokens)}/${compact(window)}`
12}
13
14export const register: Register = on => {
15 on('session.start', async ($, e, next) => {
16 const result = await next(e)
17 $.ui.status(formatContext((await $.session.usage()).context))
18 return result
19 })
20
21 on('session.measure', ($, e, next) => {
22 $.ui.status(formatContext(e.context))
23 return next(e)
24 })
25}
26