Your context window as a pint of stout above the prompt. Fills as you go. Last orders at 85%.

Your context window as a pint of stout, drawn above the Claude Code prompt.
pint ▕████████████░░░░░░░░░░░░▏ 51% settling nicely
The glass fills with the context window. The head is what is left. At 85% the barman calls last orders (a toast, and the line turns to the warning colour), because that is about where autocompact tends to fire. At 95% it is time, please. After a compaction or /clear the glass is poured again and the band says which round you are on.
/pint hides or shows it.
/plugin install pint --marketplace Rudrajmehta/pint
Answer y to add the marketplace, pick the user scope. Needs Claude Code 2.1.287 or newer (mods).
git clone https://github.com/Rudrajmehta/pint && claude --plugin-dir ./pint
The folder is watched; saving hooks/register.tsx reloads it.
.claude-plugin/plugin.json, .claude-plugin/marketplace.json: manifest and the one-entry marketplace that makes the repo installable.hooks/hooks.json, hooks/register.tsx: the mod. It reads $.session.usage().context.percent after every turn and draws a band with ui.render on AbovePrompt.types/index.d.ts: the $.state contract (percent, isHidden, pours).claude plugin validate . passes.
hooks/register.tsx 88 lines1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register } from 'claude-code'
3
4// Your context window, drawn as a pint of stout above the prompt.
5// The glass fills with the context window. The head is what is left.
6// At 85% the barman calls last orders (that is also when autocompact tends to fire).
7
8const percent = atom({ plugin: 'pint', key: 'percent' } as const, null)
9const isHidden = atom({ plugin: 'pint', key: 'isHidden' } as const, false)
10const pours = atom({ plugin: 'pint', key: 'pours' } as const, 0)
11
12const GLASS = 24 // characters wide
13const LAST_ORDERS = 85
14const TIME_PLEASE = 95
15
16function glassOf(p: number): { stout: string; head: string } {
17 const full = Math.max(0, Math.min(GLASS, Math.round((p / 100) * GLASS)))
18 return { stout: '█'.repeat(full), head: '░'.repeat(GLASS - full) }
19}
20
21function lineOf(p: number): string {
22 if (p >= TIME_PLEASE) return 'time, please. /compact or /clear before the glass overflows'
23 if (p >= LAST_ORDERS) return 'last orders. autocompact is near, save what matters'
24 if (p >= 60) return 'settling nicely'
25 if (p >= 30) return 'a good start'
26 return 'fresh pour'
27}
28
29async function refresh($: EngineInterface): Promise<void> {
30 try {
31 const u = await $.session.usage()
32 const p = u.context.percent ?? null
33 await update($, percent, () => p)
34 } catch {
35 // usage is absent until the first response of a window; leave the last value
36 }
37}
38
39export const register: Register = on => {
40 on('session.start', async ($, e, next) => {
41 await $.command.register({ name: 'pint', description: 'Show or hide the pint (context window) above the prompt' })
42 await refresh($)
43 return next(e)
44 })
45
46 on('turn.complete', async ($, e, next) => {
47 const before = await read($, percent)
48 await refresh($)
49 const after = await read($, percent)
50 if (before !== null && after !== null && before < LAST_ORDERS && after >= LAST_ORDERS) {
51 $.ui.toast('pint: last orders. context at ' + after + '%')
52 }
53 if (before !== null && after !== null && after < before - 30) {
54 // a compaction or /clear poured a fresh one
55 await update($, pours, n => n + 1)
56 }
57 return next(e)
58 })
59
60 on('command.run', { command: 'pint' }, async ($, e) => {
61 const hidden = await read($, isHidden)
62 await update($, isHidden, () => !hidden)
63 const p = await read($, percent)
64 return { text: hidden ? 'pint is back on the bar' : `pint hidden (context at ${p ?? '?'}%). /pint to bring it back` }
65 })
66
67 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
68 const p = await read($, percent)
69 const hidden = await read($, isHidden)
70 if (hidden || p === null || e.props.hasSurvey) return next(e)
71 const { Box, Text } = $.ui.resolve(e)
72 const g = glassOf(p)
73 const n = await read($, pours)
74 const warn = p >= LAST_ORDERS
75 return (
76 <Box>
77 <Text dimColor>pint </Text>
78 <Text color={warn ? 'warning' : 'text'}>▕</Text>
79 <Text color="#3b2a20">{g.stout}</Text>
80 <Text color="#f3e9d2">{g.head}</Text>
81 <Text color={warn ? 'warning' : 'text'}>▏ </Text>
82 <Text bold color={warn ? 'warning' : 'text'}>{p}%</Text>
83 <Text dimColor> {lineOf(p)}{n > 0 ? ` · round ${n + 1}` : ''}</Text>
84 </Box>
85 )
86 })
87}
88types/index.d.ts 8 lines1declare module 'claude-code' {
2 interface PluginState {
3 pint: { percent: number | null; isHidden: boolean; pours: number }
4 }
5}
6
7export {}
8