SLOPSHOPPER

context-gauge

A band above the prompt that appears when the context window is at least 70% full

newband
A shopper browsing a rack in a slop shop
README

context-gauge

Warns you before the context window fills up, with a band above the prompt suggesting /compact.

What it does

  • Reads the context-window percentage at session start and after each main-conversation turn.
  • From 70% it shows a band above the prompt: Context 78% ▓▓▓▓▓▓▓▓░░ — consider /compact, yellow from 70%, red from 90%.
  • Shows nothing below 70%, when the percentage is unknown, or while a survey is displayed.

Install

claude --plugin-dir /path/to/ModsTools/mods/context-gauge

Limits

  • Refreshes at the end of a turn, not after /compact or a manual edit: the band can lag until the next turn.
  • The 70% / 90% thresholds are fixed (no options).
  • Informational only: it never compacts for you.

Develop

claude plugin validate mods/context-gauge
claude plugin test mods/context-gauge   # 6 tests
Source 3 files
hooks/register.tsx 38 lines
1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register } from 'claude-code'
3
4import { DANGER, isShown, label } from './gauge'
5
6const percent = atom({ plugin: 'context-gauge', key: 'percent' } as const, null)
7
8async function refresh($: EngineInterface): Promise<void> {
9  const usage = await $.session.usage()
10  await update($, percent, () => usage.context.percent ?? null)
11}
12
13export const register: Register = on => {
14  on('session.start', async ($, e, next) => {
15    await refresh($)
16
17    return next(e)
18  })
19
20  on('turn.complete', async ($, e, next) => {
21    if (e.agentId === undefined) await refresh($)
22
23    return next(e)
24  })
25
26  on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
27    const value = await read($, percent)
28    if (e.props.hasSurvey || !isShown(value)) return next(e)
29    const { Box, Text } = $.ui.resolve(e)
30
31    return (
32      <Box>
33        <Text color={value >= DANGER ? 'red' : 'yellow'}>{label(value)}</Text>
34      </Box>
35    )
36  })
37}
38
hooks/gauge.ts 13 lines
1export const THRESHOLD = 70
2export const DANGER = 90
3
4export function bar(percent: number, width = 10): string {
5  const filled = Math.min(width, Math.max(0, Math.round((percent / 100) * width)))
6
7  return '▓'.repeat(filled) + '░'.repeat(width - filled)
8}
9
10export const label = (percent: number): string => `Context ${Math.round(percent)}% ${bar(percent)} — consider /compact`
11
12export const isShown = (percent: number | null): percent is number => percent !== null && percent >= THRESHOLD
13
types/index.d.ts 8 lines
1export type Fill = number | null
2
3declare module 'claude-code' {
4  interface PluginState {
5    'context-gauge': { percent: Fill }
6  }
7}
8