Status bar above the prompt: working/idle, tool count, last tool, last turn duration.


Claude Code now has mods: plugins made of TypeScript function hooks that can draw UI right inside the terminal, react to everything Claude does, and change how it works. This repo contains four mods I use every day. There's a pixel critter that lives above your prompt, a control panel for model, effort and parallel agents, a project launcher box, and a live status bar. It also has everything you need to build your own in about 10 minutes.
⚠️ Mods are early access. The function-hooks API can change between Claude Code releases. Everything here was built and tested on Claude Code 2.1.294.
Open Claude Code in a terminal and paste:
/plugin install pixel-buddy --marketplace Bocskay-Botond/claude-code-mods
Answer y to add the marketplace, press Enter for the user scope, and you're done. A little orange critter appears above your prompt. Start typing and watch it pull out a laptop. 🧡
Want the full setup? 👉 quick-start/
| Mod | What it does | Commands |
|---|---|---|
| 🐾 pixel-buddy | A 12×4 pixel Claude critter above the prompt. It types on a tiny laptop while you type, patrols while Claude works, celebrates when a turn finishes, plays (keepy-uppy, jump rope, butterflies, bubbles, reading) when you're idle, and falls asleep after 3 minutes. | /buddy /pet |
| 🛠️ tristens-tools | A tools menu and status line: model & effort picker, Clean View (hides tool noise and shows a simple checklist), Prompt Upgrade, Agent Dock (split each request across 1–100 helper agents and watch them live), and a Roadtrip racing minigame. | /tools /dock /roadtrip |
| 📁 project-box | A folder-tree card beside the status bar listing your projects by category. Click a category, then a project, to see its note and path. pixel-buddy walks over and "types the cd" for you. | /projects |
| 📊 statusbar | A minimal one-line status bar: working/idle, tool count, last tool, last turn duration, turns. The simplest real mod in the repo, so read this one first. | — |
| 👋 hello-mod | The tutorial example: a slash command, a toast and a band in about 35 lines. | /hello |
Install any of them the same way:
/plugin install <mod-name> --marketplace Bocskay-Botond/claude-code-mods
claude-code-mods/
├── .claude-plugin/
│ └── marketplace.json # makes this repo a plugin marketplace
├── mods/
│ ├── pixel-buddy/ # 🐾 the critter
│ ├── tristens-tools/ # 🛠️ tools menu, Agent Dock, Roadtrip
│ ├── project-box/ # 📁 project launcher card
│ └── statusbar/ # 📊 one-line status bar
├── examples/
│ └── hello-mod/ # 👋 your first mod, fully commented
├── quick-start/ # ⚡ 5-minute setup
├── docs/
│ ├── installation.md # every way to install & manage mods
│ ├── writing-your-own-mod.md
│ ├── api-cheatsheet.md # events, $ nouns, UI elements
│ └── troubleshooting.md
├── mod-builder-prompt/ # 🤖 a prompt that makes Claude build mods for you
└── assets/ # 🖼️ social preview (HTML source + PNG)
Every mod is the same four small files:
my-mod/
├── .claude-plugin/plugin.json # name, version, description
├── hooks/hooks.json # { "modules": ["./register.tsx"] }
├── hooks/register.tsx # the code
└── types/index.d.ts # the state your mod keeps (optional)
on(event, hook) / next(e) middleware chain worksclaude plugin test and ship it as a GitHub marketplaceclaude --version)No Node, no npm install, no build step. Claude Code compiles the TypeScript itself.
The fastest way is to ask Claude. Inside Claude Code:
Make me a mod that shows a 🍅 pomodoro timer above the prompt and plays a toast when it ends.
Claude Code has a built-in skill for this: it writes the mod, hot-reloads it into your session and tests it. For a better result, paste the prompt from mod-builder-prompt/ first.
Prefer to do it by hand? docs/writing-your-own-mod.md walks through hello-mod line by line, and docs/api-cheatsheet.md has the events and elements you'll use most.
project-box shows a demo list until you give it yours. Copy the example and edit it:
# macOS / Linux
cp mods/project-box/project-box.example.json ~/.claude/project-box.json
# Windows (PowerShell)
Copy-Item mods\project-box\project-box.example.json $HOME\.claude\project-box.json
Restart Claude Code (or run /reload-plugins) and your projects show up. Colors can be any terminal color name (magenta, cyan, green, yellow, blue, red). Set "live": true for a green dot.
| Problem | Fix |
|---|---|
| Nothing appears after install | Run /reload-plugins, or restart Claude Code. Make sure you're in a terminal: /plugin isn't available in the desktop app's Code tab. |
Marketplace file not found | Check the repo name: Bocskay-Botond/claude-code-mods |
| A mod silently does nothing | Start with claude --debug. A failing hook is skipped and logged with the reason. |
| Two bands fight for space | pixel-buddy, project-box and tristens-tools are designed to stack. Turn things off with /buddy, /projects, or /plugin → disable. |
More: docs/troubleshooting.md
Built a cool mod? PRs are welcome!
mods/<your-mod>/ (four files, see above)claude plugin validate mods/<your-mod> and claude plugin test mods/<your-mod> pass.claude-plugin/marketplace.json and to the table in this READMEMIT. Do whatever you want, just don't blame me if your critter falls asleep on the job. 😴
tristens-tools (Clean View, Agent Dock, Roadtrip and the tools menu). Go watch it!If this made your terminal a little more fun, ⭐ star the repo and share it with someone who lives in Claude Code.
Now go build a mod. Your terminal has been boring for long enough. 🚀
hooks/register.tsx 54 lines1import { atom, read, update } from 'claude-code'
2import type { Register } from 'claude-code'
3
4import type { Bar } from '../types'
5
6const initial: Bar = { phase: 'idle', tools: 0, lastTool: '', seconds: 0, turns: 0 }
7const bar = atom({ plugin: 'statusbar', key: 'bar' } as const, initial)
8
9export const register: Register = on => {
10 let startedAt = 0
11
12 on('prompt.submit', async ($, e, next) => {
13 startedAt = await $.clock.now()
14 await update($, bar, b => ({ ...b, phase: 'working', tools: 0, lastTool: '' }))
15
16 return next(e)
17 })
18
19 on('tool.call', async ($, e, next) => {
20 await update($, bar, b => ({ ...b, tools: b.tools + 1, lastTool: e.tool }))
21
22 return next(e)
23 })
24
25 on('turn.complete', async ($, e, next) => {
26 const seconds = Math.round(((await $.clock.now()) - startedAt) / 1000)
27 await update($, bar, b => ({ ...b, phase: 'idle', seconds, turns: b.turns + 1 }))
28
29 return next(e)
30 })
31
32 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
33 if (e.props.hasSurvey) {
34 return next(e)
35 }
36
37 const b = await read($, bar)
38 const { Box, Text } = $.ui.resolve(e)
39 const isWorking = b.phase === 'working'
40
41 return (
42 <Box>
43 <Text color={isWorking ? 'yellow' : 'green'}>{isWorking ? '● working' : '○ idle'}</Text>
44 <Text dimColor>
45 {' │ '}tools {b.tools}
46 {b.lastTool ? ` (${b.lastTool})` : ''}
47 {' │ '}last turn {b.seconds}s
48 {' │ '}turns {b.turns}
49 </Text>
50 </Box>
51 )
52 })
53}
54types/index.d.ts 14 lines1export type Bar = {
2 phase: 'idle' | 'working'
3 tools: number
4 lastTool: string
5 seconds: number
6 turns: number
7}
8
9declare module 'claude-code' {
10 interface PluginState {
11 statusbar: { bar: Bar }
12 }
13}
14