Read it, then pass the check at the end to open step 4.
Count turns in a band above the prompt
Updated
What this step is for
Your first useful mod only watches: it counts the turns of a session and shows the count in a dim line above the prompt. Watching is the safest move a mod has, because it never changes what Claude does. Our own version of this band shows the context size and the minutes left on the prompt cache; the next spoke article explains why that number matters.
You will meet the two parts every drawn mod needs: a value that lives in the session
(atom), and a ui.render hook that draws from it.
Do it
mkdir -p ~/claude-mods/turn-band/.claude-plugin ~/claude-mods/turn-band/hooks ~/claude-mods/turn-band/types
cd ~/claude-mods/turn-band
.claude-plugin/plugin.json. The types line names the contract for the values the mod keeps:
{
"name": "turn-band",
"version": "0.1.0",
"description": "Counts this session's turns above the prompt.",
"author": { "name": "you" },
"types": "./types/index.d.ts"
}
types/index.d.ts:
export type Turns = number
declare module 'claude-code' {
interface PluginState {
'turn-band': { turns: Turns }
}
}
hooks/hooks.json:
{ "modules": ["./register.tsx"] }
hooks/register.tsx. JSX compiles against the engine’s h, and the elements come from the
surface that draws, so the same code draws in a terminal and in the Desktop app:
import { atom, read, update } from 'claude-code'
import type { Register } from 'claude-code'
const turns = atom({ plugin: 'turn-band', key: 'turns' } as const, 0)
export const register: Register = on => {
// Main conversation only: a subagent's turn has an agentId.
on('turn.complete', async ($, e, next) => {
if (!e.agentId) await update($, turns, n => n + 1)
return next(e)
})
on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
const n = await read($, turns)
if (n === 0) return next(e) // nothing to say yet: let the engine draw its own
const { Text } = $.ui.resolve(e)
return <Text dimColor>turns {n}</Text>
})
}
Load it:
claude --plugin-dir ~/claude-mods/turn-band
Check it
claude plugin validate ~/claude-mods/turn-bandpasses and liststurn.completeandui.render{component=AbovePrompt}.- In the session, send any prompt. When the reply ends, a dim
turns 1appears above the prompt; the next reply makes itturns 2. - Edit the text to
turn {n}, then run/reload-plugins. The line changes, and the count does not reset: the value lives in the session, not in your module.
Check what you read in “Count turns in a band above the prompt”
Three questions drawn from a larger pool, so no two papers are quite the same. Two right passes it and opens the next step. The questions are public; scoring them needs an account, and the key never leaves the server.
Loading the check…