Shows the context tokens in use beside the prompt footer of the desktop app, green under 100k, yellow to 150k, red beyond. Needs function hooks (early access).

Shows how many tokens the context holds, beside the prompt footer of the Claude Code desktop app: 88.1k. The terminal is left to a status line, which already carries the figure.
| tokens | color |
|---|---|
| under 100k | green |
| 100k to 150k | yellow |
| 150k and more | red |
The figure is the last API response's input side (total_input_tokens in a status line's input) and refreshes at session start, after each tool call and when a turn ends. It takes the place of the mode labels (focus, memory paused), which follow it after a •.
claude plugin marketplace add 0xBADC0FFEE/claude-code-mods
claude plugin install context-tokens@claude-code-mods
Needs CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1.
hooks/register.tsx 64 lines1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register } from 'claude-code'
3
4const TOKENS_WARN = 100_000
5const TOKENS_CRIT = 150_000
6const GREEN = '#4eba65'
7const YELLOW = '#ffc107'
8const RED = '#e5484d'
9
10const usedTokens = atom({ plugin: 'context-tokens', key: 'tokens' } as const, null)
11
12export const register: Register = on => {
13 on('session.start', async ($, e, next) => {
14 await refreshTokens($)
15 return next(e)
16 })
17
18 on('tool.call', async ($, e, next) => {
19 const result = await next(e)
20 await refreshTokens($)
21 return result
22 })
23
24 on('turn.complete', async ($, e, next) => {
25 const result = await next(e)
26 await refreshTokens($)
27 return result
28 })
29
30 on('ui.render', { component: 'SessionMode', surface: 'desktop' }, async ($, e, next) => {
31 const tokens = await read($, usedTokens)
32 if (tokens === null) {
33 return next(e)
34 }
35
36 const { Box, Text } = $.ui.resolve(e)
37 const modes = e.props.modes.join(' & ')
38
39 return (
40 <Box>
41 <Text color={tokensColor(tokens)}>{formatTokens(tokens)}</Text>
42 {modes && <Text dimColor> • {modes}</Text>}
43 </Box>
44 )
45 })
46}
47
48async function refreshTokens($: EngineInterface): Promise<void> {
49 const { context } = await $.session.usage()
50 await update($, usedTokens, () => context.tokens ?? null)
51}
52
53function tokensColor(tokens: number): string {
54 if (tokens >= TOKENS_CRIT) return RED
55 if (tokens >= TOKENS_WARN) return YELLOW
56 return GREEN
57}
58
59function formatTokens(tokens: number): string {
60 if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}M`
61 if (tokens >= 1_000) return `${(tokens / 1_000).toFixed(1)}k`
62 return String(tokens)
63}
64types/index.d.ts 8 lines1export type UsedTokens = number | null
2
3declare module 'claude-code' {
4 interface PluginState {
5 'context-tokens': { tokens: UsedTokens }
6 }
7}
8