Ponytail for Hermes:插件启用、斜杠命令与内置技能全解
本文基于仓库中的 Hermes 安装后指南 after-install.md,完整讲清 Ponytail 在 Hermes Agent 中的启用步骤、共享网关下的访问控制要点,以及全部六个斜杠命令与内置技能的行为语义。读完你会掌握 Hermes 插件的安装后配置流程、默认模式解析优先级(环境变量 → 配置文件 → full),并能结合 plugin.yaml 与 init.py 的注册逻辑理解规则注入和网关命令改写的底层实现。
1. 背景:Hermes 为什么有独立的"安装后"环节
Ponytail 的定位是让 AI agent 像"最懒的资深工程师"一样思考——写代码前先走完七级梯子(YAGNI → 代码库复用 → 标准库 → 平台原生特性 → 已安装依赖 → 一行 → 最小可用实现),把不必要的抽象、脚手架和依赖直接砍掉。
在 Claude Code、Codex 等单机 agent 中,安装即生效;但 Hermes 是面向多用户、多通道的 agent 网关,插件安装(hermes plugins install)与启用是两步分离的操作,且斜杠命令会被转发到共享网关上。正因为这两个差异,仓库才为 Hermes 单独提供了一份 after-install.md 安装后指南。仓库根目录的 plugin.yaml 就是 Hermes 插件清单,其中声明了插件名 ponytail、版本(与 package.json 的 4.9.0 对齐)、两个钩子(pre_llm_call、pre_gateway_dispatch)、六个命令和六个技能:
name: ponytail
version: 4.9.0
provides_hooks:
- pre_llm_call
- pre_gateway_dispatch
provides_commands:
- ponytail
- ponytail-review
- ponytail-audit
- ponytail-debt
- ponytail-gain
- ponytail-help
provides_skills:
# 与 provides_commands 同名的六个技能
2. 启用插件:安装后的必要一步
如果你的安装命令带了 --enable(如 README 中的完整形式),插件已处于启用状态,可跳过本节。否则执行:
hermes plugins enable ponytail
启用后需要重启 Hermes 或网关(restart)才能生效——钩子与命令注册发生在插件加载阶段,运行中的进程不会自动拾取新插件。
README 中给出的带 --enable 的一站式安装方式是:
hermes plugins install DietrichGebert/ponytail --enable
3. 共享网关下的安全配置:把 /ponytail 限制给可信用户
after-install.md 中有一条常被忽略但很关键的运维建议:
在共享网关中,用 Hermes 的斜杠命令访问控制(slash-command access controls)将
/ponytail限制给可信用户;运行时模式是进程局部的(process-local)。
这句话包含两层含义,源码可以印证:
- 权限层:网关会把
/ponytail-*命令改写为普通 agent 提示词再派发给后端。改写前会先调用网关的_check_slash_access(source, command)检查发起者是否有权限;被拒绝时改写函数直接返回None,命令不进入 agent 执行流。见 init.py 中的rewrite_gateway_command与_slash_access_denied。 - 状态层:运行时模式(当前是
lite/full/ultra/off)保存在插件模块的一个模块级变量_current_mode中,即"进程局部"。不同进程、不同会话之间不会共享这个值;进程重启后回到默认解析链。因此某个用户在 A 进程里/ponytail ultra不会改变 B 进程的行为——这既是隔离保障,也意味着"改模式"不是一个跨用户的全局操作。
4. 六个命令与六个技能一览
安装并启用后,Hermes 中获得六条斜杠命令(与 after-install.md 的命令列表一致):
| 命令 | 作用 | 对应技能文件 |
|---|---|---|
/ponytail [lite|full|ultra|off] |
设置强度档位;不带参数时报告当前档位 | 模式命令,无对应 SKILL.md |
/ponytail-review [target] |
只针对 diff 做过度工程审查,逐条给出"可删除清单" | skills/ponytail-review/SKILL.md |
/ponytail-audit [target] |
全仓库范围的过度工程审计,按可删收益排序 | skills/ponytail-audit/SKILL.md |
/ponytail-debt |
把代码里的 ponytail: 简写标记收割成债务台账 |
skills/ponytail-debt/SKILL.md |
/ponytail-gain |
展示实测收益记分牌(更少代码、更低成本、更高速度) | skills/ponytail-gain/SKILL.md |
/ponytail-help |
上述命令速查卡 | skills/ponytail-help/SKILL.md |
六个打包技能同时注册在 ponytail: 命名空间下:ponytail:ponytail、ponytail:ponytail-review、ponytail:ponytail-audit、ponytail:ponytail-debt、ponytail:ponytail-gain、ponytail:ponytail-help。
各技能的实际行为(以下均引自各自 SKILL.md 的实现定义):
- ponytail(主技能):注入"懒惰资深工程师"人格与七级梯子。三档强度语义:
lite= 照做但用一行指出更懒的替代方案,由用户拍板;full(默认)= 强制走梯子,标准库与原生优先,最短 diff 与最短解释;ultra= YAGNI 极端派,删除先于新增,交付一行解的同时质疑其余需求。典型例子(加缓存):lite 会说"已加缓存;functools.lru_cache一行也能覆盖";full 直接@lru_cache(maxsize=1000);ultra 则回答"profiler 没说话就不加缓存"。同时明确"不懒惰"的边界:信任边界校验、防数据丢失的错误处理、安全与可访问性永远不能砍。 - ponytail-review:只审 diff,每条发现一行,格式
L<行号>: <tag> <砍什么>. <用什么替代>.,标签共五种:delete:、stdlib:、native:、yagni:、shrink:;结尾必须给出net: -<N> lines possible.,没有可删的则回答Lean already. Ship.。它只列清单,不代改代码,且正确性/安全/性能问题明确不在其范围内。 - ponytail-audit:ponytail-review 的仓库级版本,扫描整棵树而非 diff,按"能砍多少"排序输出,结尾为
net: -<N> lines, -<M> deps possible.。 - ponytail-debt:按
grep -rnE '(#|//) ?ponytail:' .收割仓库中所有刻意留下的ponytail:简写注释(约定格式为ponytail: <天花板>, <升级路径>),按文件分组生成台账行,并对没有写明升级触发条件的标记打上no-trigger风险标签;只读不写。 - ponytail-gain:一次性展示已发布的 benchmark 中位数记分牌(5 个日常任务 × 3 个模型的离线测量),并有一条"诚实边界":绝不给当前仓库编造"你已省下 X 行"的数字,未写出来的代码没有可相减的基线;仓库级真实数字只有
/ponytail-debt的计数台账。 - ponytail-help:一次性速查卡,展示三档强度、六个技能、退出方式(说 "stop ponytail"/"normal mode" 或
/ponytail off),以及默认模式配置方式。它不改变模式、不写任何持久化文件。
5. 源码纵深:register(ctx) 如何把命令、钩子、技能接进 Hermes
init.py 根部的 register 函数是整个插件的装配点,共做三件事:
① 注册技能。 遍历 skills/ 下每个含 SKILL.md 的子目录并调用 ctx.register_skill(child.name, skill_md),于是六个技能都以 ponytail:<name> 形式可用:
for child in sorted(SKILLS_DIR.iterdir() if SKILLS_DIR.exists() else []):
skill_md = child / "SKILL.md"
if child.is_dir() and skill_md.exists():
ctx.register_skill(child.name, skill_md)
② 注册两个钩子。
pre_llm_call:在每轮 LLM 调用前执行,读取当前模式(运行时模式_current_mode未设置时走默认解析链),调用build_injected_context(mode)生成规则文本注入上下文;off时返回空上下文,等价于安静地不注入。pre_gateway_dispatch:绑定rewrite_gateway_command,负责把网关收到的/ponytail-*消息改写为指向对应技能的提示词。
③ 注册命令。 /ponytail 绑定 _handle_mode_command(带参设档、无参查档、非法参数回显 Usage: /ponytail [lite|full|ultra|off]);其余五个命令通过 _make_skill_command_handler 生成——点击/输入命令后,插件向 agent 队列注入一条形如 Load and follow the Hermes plugin skill ponytail:ponytail-review. Review the current diff ... 的提示词,把命令转化为技能调用。
5.1 默认模式解析链:运行时模式、环境变量、配置文件
源码中定义了两组模式集合,注意区分:
RUNTIME_MODES = {"off", "lite", "full", "ultra"} # /ponytail 命令可设的
CONFIG_MODES = RUNTIME_MODES | {"review"} # 默认解析链可取的
_default_mode() 的优先级为:环境变量 PONYTAIL_DEFAULT_MODE → 配置文件 defaultMode → 兜底 full。配置文件位置遵循 XDG 约定:XDG_CONFIG_HOME 下为 $XDG_CONFIG_HOME/ponytail/config.json,Windows 为 %APPDATA%\ponytail\config.json,其余 Unix 为 ~/.config/ponytail/config.json。例如:
{ "defaultMode": "lite" }
配置为 "off" 可关闭会话自动注入,需要时再手动 /ponytail 打开。review 只能经配置/解析链出现,不是 /ponytail 命令的合法参数(传 maximum 之类的值会收到 Usage 提示)。
5.2 注入的上下文不是原文照搬
build_injected_context 有三个分支:
off→ 空字符串,什么都不注入;review→ 读取 skills/ponytail-review/SKILL.md 的正文(去掉 YAML frontmatter),前面加上PONYTAIL MODE ACTIVE — level: review头;文件缺失时退回一句降级提示;- 其余档位 → 读取主技能 skills/ponytail/SKILL.md,由
_filter_skill_body_for_mode做模式过滤:删除正文中属于其他档位的表格行(如| **Lite** | ...)和示例行(如- full: ...),只保留与当前档位匹配的部分,即"注入的提示词量级随档位伸缩"。SKILL.md 也读不到时才使用内置的_fallback_instructions精简规则兜底。
这套行为的直接可观测效果:/ponytail 无参数时输出形如 Ponytail mode: ultra. Use /ponytail lite|full|ultra|off.;/ponytail ultra 输出 Ponytail mode set to ultra.,随后每轮 LLM 调用都带上 PONYTAIL MODE ACTIVE — level: ultra 开头的规则上下文。
5.3 网关命令改写:下划线兼容与访问控制
rewrite_gateway_command 处理网关消息时的完整逻辑:
- 只处理以
/开头的文本,取出首段命令名并把下划线统一为连字符(因此/ponytail_audit repo与/ponytail-audit repo等价); - 命令不在六个技能命令白名单内(如
/status、普通聊天文本)则返回None不做任何事; - 通过
_slash_access_denied调用网关的_check_slash_access(source, command):返回非None即视为拒绝,改写放弃,命令不落地; - 通过检查后返回
{"action": "rewrite", "text": <skill prompt>},其中提示词模板为Load and follow the Hermes plugin skill ponytail:<command>. <描述><用户参数>。
6. 测试证据:这些行为如何被验证
tests/hermes-plugin.test.js 用 node:test 驱动 Python 加载插件模块,对上一节每条结论都留有断言:
- 清单一致性:
plugin.yaml的版本、作者、命令、技能必须与package.json及skills/目录实际内容对齐,且声明pre_llm_call/pre_gateway_dispatch两个钩子; - 命名空间注册:调用
register(ctx)后,六个技能全部以ponytail:前缀注册且路径以/SKILL.md结尾; - 模式注入:
build_injected_context('ultra')的输出必须含PONYTAIL MODE ACTIVE — level: ultra且不泄漏其他档位的表格行;off输出为空; - 默认解析链:在临时
XDG_CONFIG_HOME写入{"defaultMode": "lite"}并设PONYTAIL_DEFAULT_MODE=ultra时,环境变量胜出(level: ultra);无参/ponytail输出状态、非法参数输出Usage:、再次查询保持ultra; - 网关改写:
/ponytail-review x、/ponytail_audit repo、/ponytail-debt、/ponytail-help全部被保留,/status与普通文本返回null;_check_slash_access返回'denied'时改写结果为null——这正是第 3 节"把/ponytail限制给可信用户"的代码级依据。
7. 安装后自检清单
按 after-install.md 的完整流程收尾:
- 确认启用:
hermes plugins enable ponytail(未随--enable安装时),随后重启 Hermes 或网关; - 共享网关场景:先在 Hermes 侧配置斜杠命令访问控制,把
/ponytail等命令限定给可信用户; - 会话内验证:输入
/ponytail(不带参数)应看到Ponytail mode: full.之类的状态行(full是默认档); - 试一条技能命令:
/ponytail-help应回显速查卡;/ponytail-review会按L<行号>: <tag> ...格式对当前 diff 给出删除清单; - 需要固定默认档位时,用环境变量
PONYTAIL_DEFAULT_MODE或配置文件~/.config/ponytail/config.json的defaultMode字段(环境变量优先级更高),无需任何强制配置项。
至此,Hermes 侧的 Ponytail 安装即告完成:六个命令、六个技能、两个钩子全部就绪,而"最懒的资深工程师"默认以 full 档在每个 LLM 轮次前就位。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00