SLOPSHOPPER

plan-progress

Claude's own task list as a progress bar above the prompt, read from its todo and task tools: no model calls, no tokens

newbandguardcommand
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · plan-progress
› fix the failing auth test and add an audit log call ⏺ Read(src/auth.ts) ⎿ Read 6 lines ⏺ Update(src/auth.ts) ⎿ Added 2 lines, removed 1 line ⏺ Bash(bun test) ⎿ 3 pass, 1 fail ● Done. refresh now rejects expired claims and logs an audit event. ✻ Worked for 42s · done 4:20 PM › /plan-progress ⎿ plan-progress: Plan bar hidden. ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts
README

givememod

Say /givememod and Claude Code builds a mod for the task in front of you.

License Stars Last Commit Page

English · Русский · 中文

<img src="docs/teaser-en.gif" alt="Seven tasks in the Claude Code desktop app and terminal: each time /givememod reads the situation and builds the mod that fits it: a plan bar, a hold on risky commands, a test watcher, a context gauge, a files pane, answer buttons, a kept favorite" width="860">

givememod is a Claude Code skill that makes Claude Code mods on demand. It reads the conversation you are in, proposes a small mod that fits it (a progress bar of the plan, a counter of files touched, a guard on the one risky command of this task, a watcher on your tests), builds it from tested templates, loads it live and tunes it until you like it. The mods you like become favorites; the rest disappear with the session.

Why

Since October 2026 Claude Code has mods: small plugins that run inside Claude Code and can draw a band above the prompt, open a sidebar, hold a tool call until you answer, or add a command that answers instantly. More than 3,000 public mods appeared in the first weeks. Most are general products. What is missing is the small mod you want for this task: the bar for this migration, the checklist for this bug, the guard for this deploy. givememod writes that one in a minute, and knows what the 3,000 others already figured out.

Features

  • One command — /givememod a progress bar for this refactor, or just "make me a mod for this"
  • Reads the situation — plan in play, many files, long jobs, risky commands, subagents, waiting on CI, answers ending in options: it proposes the mod that fits, and on a long task offers one by itself, once
  • 11 tested templates — plan progress, files touched, context gauge, turn receipt, goal pin, risky-command hold, command watcher, reply buttons, pinboard with a tool for Claude, focus timer, blank starter; each passes claude plugin validate and its tests
  • Loads live — written into the session's mods folder, it appears when the reply ends; every tweak reloads the same way
  • Favorites — keep a mod and it goes to your skills folder, where Claude Code loads it in every session with no install; the next time a similar task comes up it is proposed first
  • The whole corpus inside — 29 building blocks with code, a drawing cookbook, every documented trap with the official limits, the test kit, a review checklist for third-party mods
  • A map of 3,057 public mods — what people build, why, how, and the best example for each job, every one linked
  • What the best mods know — 222 mod repositories read file by file: the techniques, glyphs, palettes, icons, sprites, sounds, helper files and tools worth reusing, each with its source and licence
  • Zero tokens by default — the templates make no model calls and add nothing to the context

Quick Start

Paste this into Claude Code (terminal or the desktop Code tab):

Install the Claude Code plugin givememod from https://github.com/timoncool/givememod. In the shell run `claude plugin marketplace add timoncool/givememod`, then `claude plugin install givememod@givememod`, and check that `claude plugin list` shows givememod enabled. Then tell me to run /reload-plugins (or restart Claude Code) so that /givememod appears, and after that to type /givememod in any conversation.

Or by hand, in any terminal:

claude plugin marketplace add timoncool/givememod
claude plugin install givememod@givememod

Mods need Claude Code 2.1.287+ (2.1.286+ in the desktop Code tab). The plugin is installed for your user, so it is there in terminal and desktop sessions alike; inside a terminal session /plugin install givememod@givememod works too.

Usage

/givememod a bar of the plan above the prompt
/givememod hold any rm -rf or force push until I confirm
/givememod watch `npm test` every 20 seconds
/givememod which mod would help here?
make me a mod that counts the files you touch

The first time a mod is written in a session, Claude Code asks Enable hot reloading for this session? — choose Enable for this session. The mod appears when the reply ends; ask for changes and each one reloads the same way.

TemplateWhat you get
plan-progressPlan ███░░ 3/5 · Fixing the bug, read from Claude's own task list
files-touchedFiles: 4 read · 2 edited · 1 new and a /files pane
context-gaugeContext 62% 124k / 200k ▂▃▅▆
turn-receipta line under each answer: time, tools, files changed, failures; a toast on long turns
goal-pinthe goal of the conversation pinned above the prompt with a timer
risky-holdrm -rf, reset --hard, force push, DROP wait for your Run it
watch-commanda command rerun on a timer, its state under the prompt, a toast when it changes
reply-choicesnumbered options at the end of an answer become buttons
pinboarddecisions, todos and links Claude pins through its own tool, in a sidebar
focus-timera countdown above the prompt
starterthe blank skeleton for anything else

Keep a mod: say "keep this one". It is copied to ~/.claude/skills/<name>/ (or to the project's .claude/skills/ to keep it for one project) and noted in ~/.claude/givememod/FAVORITES.md. Claude Code loads a folder there with a plugin.json as <name>@skills-dir from the next session, with nothing to install; claude plugin disable <name>@skills-dir switches it off.

Other things it does: explains why a mod does nothing, reviews a third-party mod before you install it (what it can reach, what it costs per turn), and answers "who already built X?" from the map of public mods.

Made with givememod

Mods it built in real sessions (the sessions were in Russian): a spec check that counts which points of the brief are done, open or not started; a Spotify player above the prompt; and a 12-stage GTA V dubbing pipeline, with the running step's own counter and a tick when it finishes.

<img src="docs/made-with/tz-check.png" alt="Spec check: a bar above the prompt counting the points of the brief, 27 of 29 done" width="760"> <img src="docs/made-with/spotify.png" alt="Spotify player: previous, pause and next buttons and the track playing" width="760"> <img src="docs/made-with/pipeline.png" alt="GTA V dubbing pipeline: stage 5 of 12 with the running step and its counter" width="760"> <img src="docs/made-with/pipeline-done.png" alt="The step finished: 100%, done" width="760"> <img src="docs/made-with/pipeline-next.png" alt="GTA V dubbing pipeline: stage 6 of 12" width="760">

slapbox. Began as "a mod to spank Claude when it messes up" in a givememod session and grew into a mod of its own: eight slappers, nine butts, and Claude hears the tally with your next message.

<img src="https://raw.githubusercontent.com/timoncool/slapbox/main/docs/teaser.gif" alt="slapbox: a cartoon butt above the prompt slapped by hand, slipper, whip, ruler and frying pan" width="760">

What is inside

PartContents
SKILL.mdthe pipeline: situation → candidate → build → check → tune → favorite
references/picker.mdsituation → template table, the one-line proposal, the usual tweaks
references/blocks.md29 building blocks with code: band, pane, tabs, guard, hold, tool.check, prompt rewrite, timers, state, restyling Claude Code's own rows, model tools, model calls, Raster and blit, Client modules, sound, nouns, animation without redraw storms, every surface, talking to the model, deferred actions, state shared by sessions
references/ui-cookbook.mdrender sites, elements per surface, focus and hotkeys, the hint line, desktop quirks measured
references/gotchas.mdevery documented trap as symptom → cause → fix, the official limits, what the built-in guard skips, open issues, stale early-access claims
references/testing.mdthe claude-code/testing kit with stubs that work
references/review-and-cost.mdvetting a third-party mod, prompt-cache cost, composing mods
references/landscape.md3,057 public mods decomposed: 17 jobs, the mechanisms, the best examples, ideas worth stealing, crowded vs open niches
references/techniques.mdhow the best mods solve recurring problems, each move linked to the file that does it
references/resources.mdglyphs, palettes, icons, pixel art, sounds, data tables, helper files and tools from public mods, with licences
references/api-index.mdevery event, $ method and next field of the API, one line each, generated from the types of the build
references/catalog/mods.tsvevery public mod with stars, link, hooks, calls and reach
templates/11 mods with tests
examples/Anthropic's sample mods and the best community mods, with licenses

How it works

  1. Situation: what you asked, the shape of the work, session state, the project, your favorites.
  2. Candidate: the smallest mod that helps; /givememod builds it at once and names the runner-up, and unasked it is only offered, in one line.
  3. Build: a template copied into the session's mods folder and adapted with the building blocks, following the rules the loader enforces.
  4. Check: claude plugin validate and claude plugin test before you see it.
  5. Tune: shorter, under the prompt, in a sidebar, only while Claude works, another colour, ask before X.
  6. Favorite: kept mods go to your skills folder, load in every session and are proposed first next time.

Other Projects by @timoncool

ProjectDescription
Angry SwitcherSwear at Claude Code all you like, it reads the clean version
satoriSelf-learning loop for Claude Code: corrections become skills
telegram-api-mcpFull Telegram Bot API as MCP server
civitai-mcp-ultimateCivitai API as MCP server
trail-specTRAIL — cross-MCP content tracking protocol
ACE-Step StudioAI music studio — songs, vocals, covers, videos
VideoSOSAI video production in the browser

Authors

Acknowledgements

Built on Anthropic's mods documentation, the built-in mods and sample mods. The map of public mods comes from karanb192/awesome-claude-code-mods. Traps and patterns were merged from the community mod skills listed in references/sources.md — BeLazy167, Sstobo, DannyMac180, jclfocused, ysoftman, BorjaGM1, emanueledenaro, jamubc, tomada1114, nogu66, karanb192 and others. Example mods by hamzafer, sezaakgun and jarrodwatts (MIT).

Support the Author

I build open-source software and do AI research. Most of what I create is free and available to everyone. Your donations help me keep creating without worrying about where the next meal comes from =)

All donation methods | dalink.to/nerual_dreming | boosty.to/neuro_art

  • BTC: 1E7dHL22RpyhJGVpcvKdbyZgksSYkYeEBC
  • ETH (ERC20): 0xb5db65adf478983186d4897ba92fe2c25c594a0c
  • USDT (TRC20): TQST9Lp2TjK6FiVkn4fwfGUee7NmkxEE7C

Star History

<a href="https://github.com/timoncool/givememod/stargazers"> <img alt="Star History Chart" src="docs/stars-light.svg" /> </a>

License

MIT. Example mods keep their own licenses (MIT, Apache-2.0), with the license file beside them.

Source 2 files
hooks/register.tsx 101 lines
1import { atom, read, update } from 'claude-code'
2import type { Register } from 'claude-code'
3
4import type { PlanTask } from '../types'
5
6const BAR_CELLS = 12
7
8const tasks = atom({ plugin: 'plan-progress', key: 'tasks' } as const, [] as PlanTask[])
9const isHidden = atom({ plugin: 'plan-progress', key: 'isHidden' } as const, false)
10
11function bar(done: number, total: number, cells: number): string {
12  const filled = total === 0 ? 0 : Math.round((done / total) * cells)
13  return '█'.repeat(filled) + '░'.repeat(cells - filled)
14}
15
16function clip(text: string, width: number): string {
17  return text.length <= width ? text : `${text.slice(0, Math.max(1, width - 1))}…`
18}
19
20export const register: Register = on => {
21  on('session.start', async ($, e, next) => {
22    const r = await next(e)
23    await $.command
24      .register({ name: 'plan-progress', description: 'Show or hide the plan progress bar', immediate: true })
25      .catch(() => {})
26    return r
27  })
28
29  on('tool.call', { tool: 'TodoWrite' }, async ($, e, next) => {
30    const r = await next(e)
31    if (e.agentId !== undefined || r.deny !== undefined || r.isError === true) return r
32    const list = (e.todos ?? []).map((t, i) => ({
33      id: String(i),
34      title: t.content,
35      active: t.activeForm || t.content,
36      status: t.status,
37    }))
38    await update($, tasks, () => list)
39    return r
40  })
41
42  on('tool.call', { tool: 'TaskCreate' }, async ($, e, next) => {
43    const r = await next(e)
44    if (e.agentId !== undefined || r.deny !== undefined || r.isError === true) return r
45    const created = (r.result as { task?: { id?: string } } | undefined)?.task
46    await update($, tasks, list => {
47      const id = created?.id ?? String(list.length + 1)
48      return [...list.filter(t => t.id !== id), { id, title: e.subject, active: e.activeForm || e.subject, status: 'pending' as const }]
49    })
50    return r
51  })
52
53  on('tool.call', { tool: 'TaskUpdate' }, async ($, e, next) => {
54    const r = await next(e)
55    if (e.agentId !== undefined || r.deny !== undefined || r.isError === true) return r
56    await update($, tasks, list =>
57      e.status === 'deleted'
58        ? list.filter(t => t.id !== e.taskId)
59        : list.map(t =>
60            t.id !== e.taskId
61              ? t
62              : {
63                  ...t,
64                  title: e.subject ?? t.title,
65                  active: e.activeForm ?? t.active,
66                  status: e.status && e.status !== 'deleted' ? e.status : t.status,
67                },
68          ),
69    )
70    return r
71  })
72
73  on('command.run', { command: 'plan-progress' }, async $ => {
74    const hidden = !(await read($, isHidden))
75    await update($, isHidden, () => hidden)
76    return { text: hidden ? 'Plan bar hidden.' : 'Plan bar shown.' }
77  })
78
79  on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
80    const list = await read($, tasks)
81    if (e.props.hasSurvey || list.length === 0 || (await read($, isHidden))) return next(e)
82    const done = list.filter(t => t.status === 'completed').length
83    const current = list.find(t => t.status === 'in_progress')
84    const width = e.props.bodyColumns
85    const cells = width < 60 ? 6 : BAR_CELLS
86    const head = `Plan ${bar(done, list.length, cells)} ${done}/${list.length}`
87    const tail = current ? ` · ${current.active}` : done === list.length ? ' · done' : ''
88    const { Box, Text } = $.ui.resolve(e)
89    const below = await next(e)
90    return (
91      <Box flexDirection="column">
92        <Text wrap="truncate-end">
93          <Text color={done === list.length ? 'success' : 'claude'}>{head}</Text>
94          <Text dimColor>{clip(tail, Math.max(8, width - head.length - 1))}</Text>
95        </Text>
96        {below}
97      </Box>
98    )
99  })
100}
101
types/index.d.ts 8 lines
1export type PlanTask = { id: string; title: string; active: string; status: 'pending' | 'in_progress' | 'completed' }
2
3declare module 'claude-code' {
4  interface PluginState {
5    'plan-progress': { tasks: PlanTask[]; isHidden: boolean }
6  }
7}
8