跳到正文
claudemods

支持 /tally 的 Claude Code 工具调用计数器

统计 Claude 每轮和每个会话的工具调用次数,在加载指示器旁显示计数,并新增 /tally 查看明细。

权限

  • 拦截工具调用能看到 Claude 发起的每一次工具调用(tool.call / tool.check),并可以阻止或修改它。
  • 修改界面在 Claude Code 界面中绘制内容:横条、面板、状态文字、弹出通知(ui.render / $.ui.*)。
  • 添加命令/工具注册新的斜杠命令或工具,供你或 Claude 调用($.command.register / $.tool.register)。
实测版本
v2.1.291
最近实测
需要
Claude Code ≥ 2.1.287
显示位置
加载动画、对话记录、状态栏

在 Claude Code 中安装:

/plugin install cm-tool-call-counter --marketplace rotbit/claudemods-marketplace
全部安装方式 ↓

这个插件能做什么?

工具调用计数器(Tool Call Counter)是一款 Claude Code 工具调用计数插件。Claude 工作时,加载指示器(spinner)那一行会多出一个后缀,显示本轮的调用次数,例如 · 7 tools,这样你不用翻看对话记录就能知道这一轮有多忙。随时输入 /tally,即可看到本会话迄今为止的统计表:

**Tool calls** · this turn: 7 · this session: 41 (2 errors)

| Tool | Calls | Errors |
| --- | ---: | ---: |
| Bash | 18 | 2 |
| Read | 15 | 0 |
| Edit | 8 | 0 |

当你想知道某一轮为什么耗时很久、Claude 是否在反复读取相同的文件,或者它的 shell 命令多久失败一次时,它就很有用。你还可以选择让状态栏持续显示累计总数:🔧 41 tool calls (2 errors)。需要 Claude Code 2.1.287 或更高版本。

演示

录屏中,我们让 Claude 执行一个需要用到多个工具的任务。随着调用发生,加载指示器的后缀不断递增;之后运行 /tally,就会打印出按工具划分的统计表。

安装

使用安装区块中的任意一种方式安装。/tally 会在会话启动时注册。

$ install cm-tool-call-counter

需要 Claude Code ≥ 2.1.287

  1. 1.在 Claude Code 中一行安装

    /plugin install cm-tool-call-counter --marketplace rotbit/claudemods-marketplace

    粘贴到正在运行的会话中(v2.1.275+)。Claude Code 会先询问是否添加该插件市场。

  2. 2.从终端安装

    claude plugin marketplace add rotbit/claudemods-marketplace
    claude plugin install cm-tool-call-counter@claudemods

    然后在所有已打开的会话中运行 /reload-plugins。

  3. 3.免安装试用

    git clone https://github.com/rotbit/claudemods-marketplace
    claude --plugin-dir ./claudemods-marketplace/cm-tool-call-counter

    仅在当前会话中加载该插件,不会写入你的设置。

工作原理

计数由一个观察所有工具的 tool.call 钩子完成。以下摘自 hooks/register.ts:

on('tool.call', async ($, e, next) => {
  const tool = String(e.tool)
  await update($, turn, t => addCall(t, tool))
  const now = await update($, session, t => addCall(t, tool))
  if (showInStatus) $.ui.status(statusText(now))

  const ran = await next(e)

  if (ran.deny !== undefined || ran.isError === true) {
    await update($, turn, t => addError(t, tool))
    const failed = await update($, session, t => addError(t, tool))
    if (showInStatus) $.ui.status(statusText(failed))
  }
  return ran
}).catch(($, e, next) => next(e))

on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
  if (!showInSpinner) return next(e)
  const { count } = await read($, turn)
  if (count === 0) return next(e)
  return next({ ...e, props: { ...e.props, suffix: spinnerSuffix(e.props.suffix, count) } })
})

每次调用在开始时就会被计入两个 $.state 原子:一个是由 turn.start 钩子重置的 turn,另一个是 session。随后钩子通过 next(e) 把调用原样传下去;如果结果被拒绝或带有 isError 标记,就记录一次错误。即使计数过程抛出异常,.catch 也会照常执行这次调用,所以插件永远不会阻塞任何工具。

针对 Spinner 渲染位置的 ui.render 钩子只改写 suffix 属性,其余内容全部交给 next,因此加载指示器仍由 Claude Code 自己绘制。由于计数保存在 $.state 中,数字一变,加载指示器就会立即重绘。/tally 是在 session.start 中通过 $.command.register 注册的,而针对 tally 的 command.run 钩子会返回由 hooks/tally.ts 中的 formatTable 生成的 { text }。

自定义

在 /config 中修改这些选项。加载指示器的文字来自 spinnerSuffix,状态栏文字来自 statusText,两者都在 hooks/tally.ts 中。若想让 /tally 表格换一种排序方式,请修改 formatTable 中的 sort 调用。

设置项类型默认值作用
showInSpinnerbooleantrueShow in spinner. Append " · N tools" (this turn's count) to the working spinner.
showInStatusbooleanfalseShow in status line. Also show the session's total tool calls and errors in the status line.

在 Claude Code 中通过 /config 修改这些设置,插件会热重载。

权限与安全

之所以会出现拦截工具调用,是因为插件为所有工具挂接了 tool.call。它只做观察:从不拒绝或修改任何调用,除了工具名称之外也不查看其他参数。修改界面对应加载指示器后缀和可选的状态栏文字。添加命令/工具对应 /tally。

它不运行命令、不读取文件、不使用网络,也不会在会话之间保存任何数据。可以用 /plugin disable cm-tool-call-counter 停用它,或者用 claude --safe-mode 启动一个关闭所有插件的会话。

拦截工具调用
能看到 Claude 发起的每一次工具调用(tool.call / tool.check),并可以阻止或修改它。
修改界面
在 Claude Code 界面中绘制内容:横条、面板、状态文字、弹出通知(ui.render / $.ui.*)。
添加命令/工具
注册新的斜杠命令或工具,供你或 Claude 调用($.command.register / $.tool.register)。

兼容性与故障排除

已在 macOS 终端中使用 Claude Code 2.1.291 测试。如果你看不到计数:

  • 确认 claude --version 为 2.1.287 或更高版本,并且该插件已在 /plugin 中启用。
  • 通过 shell 安装后,运行 /reload-plugins;会话重新启动该插件后,/tally 就会出现。
  • 只有当本轮至少发生过一次工具调用时,后缀才会显示。
  • /config 中的 showInSpinner 可能处于关闭状态。

计数只覆盖插件在当前进程中加载以来的这段时间,所以重新加载后会归零。

常见问题

工具调用计数器会改变或拖慢工具调用吗?
不会。它只是记下这次调用,通过 next(e) 让调用原样运行,如果调用失败再记一次错误。即使计数本身出错,.catch 处理器也会照常执行这次调用。
在 /tally 中,什么算作错误?
结果带有 isError 的调用,或者被其他钩子拒绝的调用,例如某个安全插件拒绝了一条 Bash 命令。
会话计数在重启后还会保留吗?
不会。计数保存在 $.state 中,只在当前 Claude Code 进程中有效。新会话或重新加载插件都会从零开始。
/tally 会调用模型吗?
不会。command.run 钩子直接根据插件收集到的计数作答,所以是即时的,也不消耗 token。
不打开 /tally 也能看到总数吗?
在 /config 中开启 showInStatus,即可让会话总数和错误数一直显示在状态栏中。
上下文仪表 在 Claude Code 中运行

上下文仪表

在状态栏显示上下文窗口占用、5 小时与 7 天套餐用量和会话花费,并在接近上限时发出提醒。

  • 状态栏
  • 弹出通知
  • 修改界面

已在 v2.1.291 实测

危险命令拦截 在 Claude Code 中运行

危险命令拦截

在 rm -rf /、强推 main、DROP TABLE、curl | sh 等破坏性 Bash 命令执行前将其拒绝。

  • 弹出通知
  • 拦截工具调用
  • 修改界面

已在 v2.1.291 实测

提示框上方的 Git 分支 在 Claude Code 中运行

提示框上方的 Git 分支

在 Claude Code 输入框上方用一行横条显示当前 git 分支、已修改文件数和领先/落后状态。

  • 输入框上方
  • 执行命令
  • 拦截工具调用
  • 修改界面

已在 v2.1.291 实测

更多 斜杠命令、上下文、额度与费用、状态栏与提示栏。