Context window fill in the status line, with a heads-up before it runs out

Mods for Claude Code, one folder each. A mod is a plugin of function hooks: panes, status lines, slash commands, tool guards.
| Mod | What it does |
|---|---|
| cost-pane | Token and USD spend per session and per day, in the status line and a /cost-pane pane |
| context-guard | Context window fill in the status line; a toast once it passes 80% |
| cache-watch | A toast when a turn rebuilt the prompt cache: tokens written, turn cost, likely cause (idle, model change) |
| turn-timer | Speaks (say on macOS) and toasts when a turn longer than 2 minutes finishes |
git clone git@github.com:anthonyhungnguyen/claude-code-mods.git ~/.claude/mods
List each mod folder you want in ~/.claude/settings.json, separated by ::
{ "env": { "CLAUDE_CODE_PLUGIN_DIRS": "~/.claude/mods/cost-pane:~/.claude/mods/context-guard:~/.claude/mods/cache-watch:~/.claude/mods/turn-timer" } }
New sessions load them. Check a mod with claude plugin validate ~/.claude/mods/<mod>.
hooks/register.ts 32 lines1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register } from 'claude-code'
3
4const WARN_AT = 80
5const warnedA = atom({ plugin: 'context-guard', key: 'warned' } as const, false)
6
7// warn once per climb past WARN_AT; dropping back under (a compact, a /clear) re-arms it
8export const nextWarned = (percent: number, warned: boolean) =>
9 percent >= WARN_AT ? { warned: true, toast: !warned } : { warned: false, toast: false }
10
11async function check($: EngineInterface) {
12 const percent = Math.round((await $.session.usage()).context.percent ?? 0)
13 $.ui.status(`🧠 ${percent}% context`)
14 const { warned, toast } = nextWarned(percent, await read($, warnedA))
15 await update($, warnedA, () => warned)
16 if (toast) $.ui.toast(`Context at ${percent}%. Consider /compact before it auto-compacts.`)
17}
18
19export const register: Register = on => {
20 on('session.start', async ($, e, next) => {
21 const done = await next(e)
22 await check($)
23 return done
24 })
25
26 on('turn.complete', async ($, e, next) => {
27 const done = await next(e)
28 if (!e.agentId) await check($)
29 return done
30 })
31}
32types/index.d.ts 8 lines1export type Percent = number
2
3declare module 'claude-code' {
4 interface PluginState {
5 'context-guard': { warned: boolean }
6 }
7}
8