
最近把 Claude Code 当作主力终端工具用越用越觉得 Mods 这个玩法值得单独写一篇。说得直白点Mods 就是给 Claude Code 加外部工具的自定义模块尤其适合两类场景一类是让 Claude 调用你自己写的脚本、接入本机数据另一类是让它在终端里把结果“画”成一眼能看懂的界面面板。它不是某个单一功能而是一整套围绕 Agent 的工具扩展思路。这篇文章是我实际趟过一遍后的经验总结不写官方文档只讲怎么落地适合想深度定制 Claude 的开发者、终端重度用户以及所有不愿意把 AI 当聊天框用的人。1. 先想明白Claude Code Mods 到底解决什么问题1.1 从“能对话”到“能干活”中间差一个工具链很多人第一次打开 Claude Code 的反应是这不就是个跑在终端里的聊天机器人吗表面看确实像但它的底层循环完全不一样。Claude Code 是典型的 Agent 架构每个任务会经历“理解意图 - 调用工具 - 观察结果 - 继续执行”的循环。默认情况下它自带的工具包括读写文件、执行终端命令、做文本搜索这些能力已经能覆盖不少场景但边界也很明显它只能用它“看得见”的工具无法天然理解你项目里的私有脚本、你的部署流程、你平时用的那些命令行工具。Mods 解决的就是这个缺口。我在实践中的理解是一个 Mod 本质上是一个“工具模块”它由一段可执行逻辑加一份描述说明组成告诉 Claude Code 在什么场景下调用这段逻辑、传入什么参数、期望拿到什么输出。你可以把系统监控脚本包装成 Mod把 Git 分支清理脚本包装成 Mod甚至把一个终端仪表盘包装成 Mod。一旦注册成功Claude 就不再是只会空谈的对话模型而是变成能主动调起你工具链的操作者。这中间最关键的一点是Claude Code 本身并不关心你的 Mod 是用 Python、Node 还是 Shell 写的它只关心两件事——能不能执行以及输出够不够结构化。所以 Mods 的门槛其实非常低任何写过脚本的人都能上手最难的反而是任务拆解想清楚哪些重复性工作值得被包装成工具。1.2 Mods、MCP、Skills 的边界在哪里聊 Mods 离不开三个容易混淆的概念Mods、MCP 和 Skills。我在不同社区看到过好几种说法这里用我自己的理解把它们摆开讲。MCPModel Context Protocol是 Anthropic 提出的开放协议目标是标准化“模型如何调用外部工具”。通过 MCP一个工具服务可以暴露给任意支持该协议的客户端Claude Code 只是其中一个受益者。你用claude mcp add注册一个服务Claude 就能按协议发现工具、传参、读取结果。MCP 是重量级方案适合需要复用、跨客户端共享的工具。Skills 则完全是另一层东西。它更像是一份“操作手册”或“技能包”注入到 Claude 的上下文里教它怎么处理某一类任务。比如“如何优雅地写一个 Python 包”可以是一个 Skill它不一定调用外部脚本而是改变模型的推理路径。Skills 解决的是“会不会做”的问题Mods 解决的是“有什么工具可用”的问题。那 Mods 到底是什么位置我的看法是Mods 是介于二者之间的一种实践形态。最简单的 Mod 可以是一个.claude/commands/下的自定义命令文件里面写清执行脚本的步骤Claude 按命令调用进阶的 Mod 则可以包装成 MCP Server让工具通过标准协议被动态发现。所以不要纠结名词把它们看成一套工具链MCP 是管道Mods 是管道上的设备Skills 是使用设备的说明书。真正干活的时候三者经常混着用边界不重要能跑通才重要。2. 给 Claude 加工具一条能落地的 Mods 实操路线2.1 先把运行环境收拾干净这部分全是硬条件缺一个后面都会卡壳。Claude Code 官方推荐通过 npm 安装所以 Node.js 是必须的。我实测下来 Node 18 能跑但 Node 20 更稳尤其是后面要跑一堆 MCP Server 的时候高版本对子进程处理更友好。安装命令没什么花头就一句npm install -g anthropic-ai/claude-code装完先验证版本claude --version如果提示找不到命令八成是 npm 全局目录没进 PATH。Linux/macOS 上常见的是~/.npm-global或 nvm 管理的路径把它加到.bashrc或.zshrc里就行。Windows 上我更推荐用 WSL2 跑 Claude Code不是不能原生跑而是很多终端复用工具和 ANSI 渲染在 WSL2 里表现顺滑得多后面做界面渲染时会少掉一堆乱码坑。初次启动执行claude会进入登录流程。这里有个经验登录后立刻跑一个简单任务验证权限比如“帮我列出当前目录文件”。Claude 第一次执行命令会询问是否允许选允许并把权限记住后续会话就顺畅了。另外我强烈建议在终端复用工具里跑 Claude Code。我自己习惯用 tmux 做会话管理或者用 Tabby 这种现代终端工具。原因很简单Agent 执行任务时的输出非常长一旦滚动屏幕光靠系统终端自带的缓冲区根本不够用。tmux 可以在多个 Claude Code 会话之间跳来跳去Tabby 的 TrueColor 支持和字体渲染效果也更好跑界面类 Mod 时视觉差距非常明显。2.2 写第一个 Mod一个带描述的本地工具脚本环境准备好了下面我们写一个真正能用的 Mod。我选一个最常见的需求查看目录下体积最大的文件。这个功能默认的 Claude Code 不会做但只要你把脚本和说明给它马上就能变成顺手工具。第一步是写执行逻辑。我用 Python因为处理文件列表、格式化输出都比较直接。脚本放在~/.claude/scripts/bigfiles.py#!/usr/bin/env python3 import os, sys, json def human_size(num): for unit in [B, KB, MB, GB, TB]: if num 1024.0: return f{num:.1f} {unit} num / 1024.0 return f{num:.1f} PB def main(directory, top_n10): if not os.path.isdir(directory): print(json.dumps({error: f目录不存在: {directory}})) return 1 files [] for root, dirs, fnames in os.walk(directory): for name in fnames: path os.path.join(root, name) try: files.append((os.path.getsize(path), path)) except OSError: pass files.sort(reverseTrue) result [ {size: human_size(size), path: path} for size, path in files[:top_n] ] print(json.dumps(result, ensure_asciiFalse, indent2)) return 0 if __name__ __main__: if len(sys.argv) 2: print(用法: python bigfiles.py 目录 [top_n]) sys.exit(1) top_n int(sys.argv[2]) if len(sys.argv) 2 else 10 sys.exit(main(sys.argv[1], top_n))脚本输出 JSON而不是给人看的文本这一点非常关键。Claude Code 读取工具输出时结构化的 JSON 比一大段格式化文本更容易被模型准确解析。很多人在第一步就写那种花里胡哨的表格输出反而增加模型理解的噪声。接下来是 Mod 的“说明文件”。在 Claude Code 中自定义命令存放在项目或用户目录的.claude/commands/文件夹下文件名就是命令名。我创建~/.claude/commands/bigfiles.md--- description: 查看指定目录下体积最大的文件 argument-hint: 目录 [数量] --- 执行 python ~/.claude/scripts/bigfiles.py 目录 [数量] 来获取该目录下体积最大的文件列表。 分析脚本返回的 JSON 结果以表格形式展示文件大小使用人类可读单位并按大小降序排列。这个文件做的事情是“教会 Claude 怎么用这个工具”。第一行argument-hint让调起命令时能提示参数正文则告诉模型执行哪条命令、期望怎么读结果。没有这个文件Claude 也可以直接执行脚本但有了它你输入/bigfiles就能稳定触发正确姿势不会被模型的随机性带到沟里。2.3 把 Mod 注册进 Claude Code 并验证实际使用是在 Claude Code 会话里输入/bigfiles ~/projects 10Claude 会读取bigfiles.md中的说明执行对应的 Python 脚本然后把 JSON 结果转成 Markdown 表格。整个过程你会看到它先“思考”然后运行命令最后给出一个漂亮的列表。如果第一次运行提示权限问题在弹出询问时选择 Allow 即可。这里还有一个升级玩法把 Mod 暴露成 MCP Server。标准 MCP 协议的好处是工具可以被动态发现Claude 不需要你手动敲斜杠命令它看到任务需要时自己会去调用。实现也不难用 Python 的 MCP SDK 写一个入口from mcp.server.fastmcp import FastMCP import subprocess, json mcp FastMCP(bigfiles) mcp.tool() def big_files(directory: str, top_n: int 10) - str: 返回目录下体积最大的文件列表 result subprocess.run( [python, ~/.claude/scripts/bigfiles.py, directory, str(top_n)], capture_outputTrue, textTrue ) return result.stdout if __name__ __main__: mcp.run()然后在终端执行claude mcp add big-files -- python ~/.claude/scripts/bigfiles_mcp.py之后新建会话Claude 就能在合适场景下主动调用big_files这个工具。我个人的建议是如果这个工具只给你自己用斜杠命令就足够了如果你希望 Claude 在复杂的多步任务里自主决定何时调用那一定要走 MCP。前者是“你通知它用”后者是“它自己想到要用”体验完全不同。3. 在终端里画界面把 Mods 的输出变成可视化面板3.1 终端界面的底层逻辑ANSI 转义与 TUI“在终端画界面”听起来很玄其实底层就是文本加控制字符。终端从来不是图形画布它只接受字节流通过 ANSI 转义序列来控制光标位置、颜色、背景色。比如说\x1b[31m表示红色\x1b[1;1H表示把光标移到第一行第一列。你看到的各种终端仪表盘、进度条本质上都是一串串带控制码的文本。理论讲完但我不建议任何人手写 ANSI。现代 TUI 开发有很多现成库Python 生态有rich和textualGo 生态有bubbletea和lipglossNode 生态也有ink。它们内部把 ANSI 细节封装好了你只负责描述“要画什么”。这里我选rich因为对 Claude Code 场景最方便Claude 执行完 Python 脚本脚本直接把渲染好的界面打进 stdout终端立刻显示。需要注意的是Claude Code 本身不是图形环境它只是把工具的输出原样展示到终端。所以“画界面”这件事实际上是你的 Mod 脚本在画Claude Code 负责把画笔递给脚本再把画布展示给你。这也意味着Mod 脚本必须自己完成所有渲染不能依赖 Claude 去美化输出。3.2 用 Python 写一个系统状态面板作为 Mod我平时最常用的一个 Mod 是系统状态仪表盘一次性展示 CPU、内存、磁盘、负载和终端宽度。这个脚本很适合演示“界面类 Mod”因为代码量不大视觉效果又很直观。先装依赖pip install rich psutil然后写~/.claude/scripts/dashboard.py#!/usr/bin/env python3 import shutil import psutil from rich.console import Console from rich.table import Table from rich.panel import Panel from rich.progress import BarColumn, Progress, TextColumn console Console() cpu psutil.cpu_percent(interval0.5) mem psutil.virtual_memory() disk shutil.disk_usage(/) def progress_bar(percent): progress Progress( TextColumn([bold]{task.description}), BarColumn(), TextColumn({task.percentage:3.0f}%), consoleconsole, ) task progress.add_task(, total100) progress.update(task, completedpercent) return progress table Table(titleSystem Dashboard, show_headerFalse, title_stylebold cyan) table.add_row(CPU, f{cpu:.1f}%) table.add_row(Memory, f{mem.percent:.1f}% ({mem.used // (1024**3)} GB / {mem.total // (1024**3)} GB)) table.add_row(Disk, f{disk.percent:.1f}% ({disk.free // (1024**3)} GB free)) console.print(Panel(table, border_stylegreen)) console.print() console.print(progress_bar(cpu)) console.print(progress_bar(mem.percent)) console.print(progress_bar(disk.percent))这个脚本把数据采集和渲染放在一起输出直接是一块带边框的面板。运行python ~/.claude/scripts/dashboard.py终端里会显示漂亮的彩色进度条和统计表格。如果你觉得面板还不够“界面”还可以用rich.Layout把多块内容拼成网格布局或者用textual做真正的可交互控件那已经接近桌面应用的体验了。3.3 让 Claude Code 调用面板并自动渲染脚本本身已经能画界面但我们的目标是让 Claude Code 知道什么时候画。我注册一个/dash命令在~/.claude/commands/dash.md里写--- description: 显示当前系统状态仪表盘 --- 运行 python ~/.claude/scripts/dashboard.py 获取系统状态。 渲染完成后基于输出给出一句简要的健康度评估。如果 CPU 超过 80%提示可能存在性能瓶颈如果内存占用过高建议排查常驻进程。这样你在 Claude Code 里输入/dashClaude 会执行脚本把面板打印到终端然后根据数据补充一句诊断。这已经不是单纯的“看数据”而是把可视化和分析结合起来了。更进一步你还可以把这个面板做成 MCP 工具让 Claude 在多步任务中自己决定要不要“看一眼系统状态”。比如你在让它编译一个大项目它可以先跑一次仪表盘看看内存是否够用再决定编译参数。我实际用下来的感受是一旦工具接口的返回是渲染好的界面Claude 对数据的理解会明显更好因为它能直接“看到”颜色和进度条而不是面对一堆原始数字。4. 常见问题与排查技巧实录4.1 安装与环境问题先列几个我踩过的高频坑。npm install很慢或者卡住优先检查 registry 是不是被设置成了奇怪的地址用npm config get registry看一眼国内环境可以切成镜像源不要硬等。安装完成后执行claude提示找不到命令我前面说过是 PATH 问题但 Windows 用户要额外检查是不是 npm 全局目录本身没创建成功。Windows 下还有一个典型报错大概意思是 “claude’s workspace requires the virtual machine platform on windows. enable”。这个看着吓人其实解决方案很直接到“启用或关闭 Windows 功能”里勾选“虚拟机平台”重启电脑。如果重启后依然有问题我的建议是不要死磕直接上 WSL2Claude Code 在 WSL2 里的稳定度高一个量级尤其是涉及子进程和终端渲染的场景。还有一个很容易忽略的问题登录状态有效期。Claude Code 用久了会突然提示认证失效这时候不要急着重装在会话里重新走一次登录流程通常就能恢复。我习惯在~/.claude.json里定期备份关键配置换机器时能少折腾半小时。4.2 工具加载与执行问题Mod 脚本写好了但 Claude 就是不肯按预期执行这是大家问得最多的。第一步检查权限Claude Code 对命令执行有一套确认机制如果之前选了“拒绝”后续它会铭记在心。可以在会话里显式说“这次允许运行所有命令”或者干脆在配置里调整权限策略别让权限问题成为脚本执行的绊脚石。第二步检查命令文件路径。.claude/commands/必须放在正确的目录下用户级配置放在~/.claude/commands/项目级配置放在项目根目录的.claude/commands/。文件名不能有空格后缀必须是.md。我见过有人建了.claude/command/少了个 s结果斜杠命令死活出不来这不是 bug是路径不对。还有一个不太容易发现的坑脚本输出编码。Windows 的 GBK 终端遇到 UTF-8 字符会直接乱码即使脚本逻辑正确Claude 解析结果也会疯掉。解决办法是在 Python 脚本最前面加上sys.stdout.reconfigure(encodingutf-8)同时把终端编码强制切到 UTF-8。这个坑在中文路径和中文注释的场景下特别容易出现别问我怎么知道的。4.3 终端渲染异常问题“画界面”类 Mod 最常见的故障是颜色乱码。终端里出现一堆[31m这样的字符说明当前终端不支持 ANSI 颜色或渲染能力被关闭了。Claude Code 在普通 Windows PowerShell 里跑时容易遇到这个问题换 Windows Terminal、Tabby 或者 WSL2 的 PTY 基本能解决。如果你在 tmux 里跑记得先确认 tmux 开启 TrueColor 支持否则颜色层次会明显变淡。另一个高频问题是输出被截断或者错位。Claude Code 的上下文窗口有限如果工具输出超大段带格式的文本模型可能只保留中间一部分。这里给 Mod 开发者一个硬建议脚本输出控制在一屏以内实在内容多就分批次输出或者输出一个摘要版。界面类 Mod 的暴击点在于一旦输出被截断整个面板就残缺了比纯文本数据损失更大。最后终端面板对宽度非常敏感。同样的脚本在 120 列和 80 列的窗口里效果完全不同我习惯在脚本开头用shutil.get_terminal_size()检测宽度太窄时自动退化成普通文本列表别硬画。4.4 实践中的几点个人体会文章快写完了聊点文档里不写的东西。我现在的习惯是凡是连续让 Claude 做三次以上的事都值得做成 Mod。最初可能只是一个斜杠命令加一段脚本时间久了本地会积累出一批私人工具终端越来越像自己的驾驶舱。第二个体会是Mod 的“说明文件”远比脚本本身重要。脚本写得再漂亮如果说明文件没讲清输出格式和使用时机Claude 就会陷入自由发挥结果五花八门。好的说明文件应该像给新同事写的交接文档用途、参数、输出格式、常见误用都写清楚这份投入会在后续每个会话里回本。第三点是关于安全的。给 Claude 开放自定义工具意味着它有了执行任意命令的能力所以不要往 Mod 里塞敏感信息也不要把不由你维护的第三方脚本毫无审查地注册进去。我一般会在说明文件里限定参数范围比如目录只允许某个白名单路径避免模型路径遍历到我不希望它碰的地方。最后分享一个小技巧让 Claude 自己写 Mod。我经常把需求直接甩给它“帮我写一个脚本读取当前目录的 Git 仓库状态输出成表格”然后等它生成代码我再手动调整细节并放到.claude/commands/下。这种迭代方式非常快相当于你负责设计意图它负责写草稿半小时内就能攒出一套很顺手的工具集。这个玩法我还在继续折腾尤其是把多个 Mod 组合成一个复合流程的时候会出现很多一个人想不出来的自动化组合值得慢慢发掘。