SLOPSHOPPER

tool-calls

Live /tool-calls pane listing this session's tool calls as they run and finish.

newpaneguardcommand
v0.1.0MITupdated 2026-10-06nankris/claude-code-mods/tool-calls
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · tool-calls
│ ┃ Tool calls ✕ › fix the failing auth test and add an audit log call │ ┃ done Read │ ┃ done Grep ⏺ Read(src/auth.ts) │ ┃ done Edit ⎿ Read 6 lines │ ┃ done Write ⏺ Update(src/auth.ts) │ ┃ done Write ⎿ Added 2 lines, removed 1 line │ ┃ done Bash ⏺ Bash(bun test) │ ┃ done Bash ⎿ 3 pass, 1 fail │ ┃ done Bash │ ┃ done Bash ● Done. refresh now rejects expired claims and logs an audit event. │ │ ✻ Worked for 42s · done 4:20 PM │ │ › /tool-calls │ ⎿ tool-calls: Tool calls pane opened. │ │ ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts

Draws

Pane · Tool calls
done Read done Grep done Edit done Write done Write done Bash done Bash done Bash done Bash
README

claude-code-mods

Three small Claude Code mods. A mod is a plugin made of function hooks that runs inside a Claude Code session and can draw a band above the prompt, a side pane, or a status-line note.

ModWhat it does
turn-bandA dim line above the prompt after each reply: Last turn: 5s, 1 tool calls.
tool-callsType /tool-calls to open a side pane listing tool calls as they run (runs) and finish (done). Keeps the last 200.
bash-watchShows failed: <command> in the status line when a Bash command fails, and clears it on the next success.

Install once (all sessions)

claude plugin marketplace add nankris/claude-code-mods
claude plugin install turn-band@claude-code-mods
claude plugin install tool-calls@claude-code-mods
claude plugin install bash-watch@claude-code-mods

Check with claude plugin list. Switch one off with claude plugin disable turn-band.

Try one for a single session

Clone the repo, then point Claude Code at a mod folder:

claude --plugin-dir /path/to/claude-code-mods/turn-band

Repeat the flag to load several mods at once.

Check and test

claude plugin validate ./turn-band
claude plugin test ./turn-band

Each mod folder holds .claude-plugin/plugin.json, hooks/hooks.json, hooks/register.tsx and a hooks/register.test.ts. turn-band and tool-calls also have types/index.d.ts, which declares the state they keep.

Limits

  • Mods only draw inside Claude Code (a terminal, or the desktop app's Code tab). They do not appear in the regular Chat or Cowork views.
  • Install commands like /plugin install are typed in a terminal session.
  • Mods run inside the Claude Code process. Read the source of any mod, including these, before installing it.

License

MIT. See LICENSE.

Source 2 files
hooks/register.tsx 53 lines
1import { atom, read, update } from 'claude-code'
2import type { Register } from 'claude-code'
3
4import type { ToolCall } from '../types'
5
6const PANE = 'tool-calls'
7const calls = atom({ plugin: 'tool-calls', key: 'calls' } as const, [])
8
9export const register: Register = on => {
10  on('session.start', async ($, e, next) => {
11    await $.command.register({
12      name: 'tool-calls',
13      description: 'Show the tool calls of this session in a pane',
14    })
15
16    return next(e)
17  })
18
19  on('command.run', { command: 'tool-calls' }, async $ => {
20    await $.ui.open({ id: PANE, title: 'Tool calls' })
21
22    return { text: 'Tool calls pane opened.' }
23  })
24
25  on('tool.call', async ($, e, next) => {
26    const call: ToolCall = { id: e.tool_use_id, tool: e.tool, isDone: false }
27    await update($, calls, list => [...list, call].slice(-200))
28    const ran = await next(e)
29    await update($, calls, list =>
30      list.map(one => (one.id === call.id ? { ...one, isDone: true } : one)),
31    )
32
33    return ran
34  })
35
36  on('ui.render', { component: 'Pane', requestId: PANE }, async ($, e) => {
37    const { Box, Text } = $.ui.resolve(e)
38    const list = await read($, calls)
39    const room = Math.max(1, (e.viewport?.rows ?? 24) - 4)
40
41    return (
42      <Box flexDirection="column">
43        {list.length === 0 && <Text dimColor>No tool calls yet.</Text>}
44        {list.slice(-room).map(call => (
45          <Text dimColor={call.isDone}>
46            {call.isDone ? 'done' : 'runs'} {call.tool}
47          </Text>
48        ))}
49      </Box>
50    )
51  })
52}
53
types/index.d.ts 8 lines
1export type ToolCall = { id: string; tool: string; isDone: boolean }
2
3declare module 'claude-code' {
4  interface PluginState {
5    'tool-calls': { calls: ToolCall[] }
6  }
7}
8