SLOPSHOPPER

my-mod

Counts Claude's tool calls in the status line and adds a /my-mod command.

newguardcommandstatus
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · my-mod
› 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 › /my-mod ⎿ my-mod: Bash: 4 ⎿ my-mod: Write: 2 ⎿ my-mod: Read: 1 ⎿ my-mod: Grep: 1 ⎿ my-mod: Edit: 1 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts ⚠ my-mod: tools: 9
README

🧩 my-mod

A starting point for your own Claude Code mod: a status line, a tool-call hook, a slash command, an option and tests.

Try it

npx degit Singh-AP/awesome-claude-mods/templates/mod-template my-mod
cd my-mod
claude plugin validate --strict .   # what it hooks and calls
claude plugin test .                # run the tests
claude --plugin-dir .               # load it in a session

Edit hooks/register.ts while the session runs: the mod hot-reloads when you save.

Next

Source 2 files
hooks/register.ts 27 lines
1import type { Register } from 'claude-code'
2
3import { describeCounts } from './counts'
4
5// Module state starts over on every hot reload; keep what must survive in
6// $.state (this session) or $.store (across sessions).
7const counts = new Map<string, number>()
8
9export const register: Register = (on, options) => {
10  const label = String(options.label ?? 'tools')
11
12  on('session.start', async ($, e, next) => {
13    await $.command.register({ name: 'my-mod', description: 'Show tool calls by tool' })
14    return next(e)
15  })
16
17  // Every tool call, main thread and subagents. `next(e)` runs it.
18  on('tool.call', async ($, e, next) => {
19    counts.set(e.tool, (counts.get(e.tool) ?? 0) + 1)
20    const total = [...counts.values()].reduce((a, b) => a + b, 0)
21    $.ui.status(`${label}: ${total}`)
22    return next(e)
23  })
24
25  on('command.run', { command: 'my-mod' }, async () => ({ text: describeCounts(counts) }))
26}
27
hooks/counts.ts 10 lines
1// Pure helpers (no `$`) are easy to unit test.
2
3export function describeCounts(counts: ReadonlyMap<string, number>): string {
4  if (counts.size === 0) return 'No tool calls yet.'
5  return [...counts.entries()]
6    .sort((a, b) => b[1] - a[1])
7    .map(([tool, n]) => `${tool}: ${n}`)
8    .join('\n')
9}
10