Move Qt/Tauri/full Web SPA under archive/, ship hermit as CLI/TUI plus libcstcore and cst-webui/1 HTTP+SSE (turn lifecycle hooks, capabilities). Co-authored-by: Cursor <cursoragent@cursor.com>
7.8 KiB
扩展:Skills、插件、MCP 与自定义子 agent
Hermit 的可替换面是本页这些扩展;不是内置 core 工具
(read_file / write_file / apply_patch / run_shell / …)或权限/沙箱——那些是
agent 契约与 --tools minimal 基线,不能当用户插件卸掉。
所有扩展只在默认工具档(--tools default)下加载;--tools minimal 时
cst_extensions_load 直接跳过。下文的“配置目录”优先 ~/.config/hermit/,
若无则回退 ~/.config/cst-agent/($XDG_CONFIG_HOME/…;Windows 为 %APPDATA%\…)。
| 放在哪 | 什么 | 何时加载 |
|---|---|---|
<ws>/.agent/skills/*/SKILL.md、<ws>/.claude/skills/*/SKILL.md |
skill | 总是 |
<配置目录>/skills/*/SKILL.md |
skill | 总是 |
<ws>/.agent/plugins/*/plugin.json |
插件 | 工作区被信任后(/plugins trust) |
<配置目录>/plugins/*/plugin.json |
插件 | 总是 |
<ws>/.agent/mcp.json |
MCP 服务器 | 工作区被信任后 |
<配置目录>/mcp.json |
MCP 服务器 | 总是 |
<ws>/.agent/agents/*.md、<配置目录>/agents/*.md |
子 agent 角色 | 总是 |
同名时先出现的生效:工作区 > 配置目录 > 插件。改完后 /skills reload、/plugins reload 或 /mcp reload
重新加载(会重启 MCP 服务器)。启动时首页和 headless 的 stderr 会打印一行汇总,例如
2 skills · 1 plugin (3 tools) · 1 MCP server。
Skills
一个 skill 是一个目录,里面有 SKILL.md,可以附带脚本、参考资料等文件:
.agent/skills/pdf-forms/
├── SKILL.md
├── reference.md
└── scripts/fill.py
---
name: pdf-forms
description: Fill PDF forms with the bundled script; use when the user asks to fill or inspect a PDF form.
---
# PDF forms
1. List the fields: `python3 scripts/fill.py --list form.pdf`
2. ...
- system prompt 里只有一张索引(
- pdf-forms: Fill PDF forms…,总长 ≤ 4 KB),模型认为相关时调用skill(name)读正文和文件列表,再用skill(name, file="reference.md")读附带文件(只能读 skill 目录内的文件)。 - 没有 frontmatter 时,名字取目录名,描述取正文第一行非标题文字。
/skill pdf-forms 把 a.pdf 填好会把 skill 正文直接放进这条消息再发送。
插件(plugin.json)
~/.config/cst-agent/plugins/jira/
├── plugin.json
├── issue.py
└── skills/ # 可选:插件自带的 skills
{
"name": "jira",
"description": "Read Jira issues.",
"tools": [
{
"name": "jira_issue",
"description": "Fetch one Jira issue (summary, status, comments).",
"command": ["python3", "issue.py"],
"parameters": {
"type": "object",
"properties": {
"key": {"type": "string", "description": "issue key, e.g. CST-42"},
"comments": {"type": "integer", "description": "how many comments"}
},
"required": ["key"]
},
"perm": "net",
"timeout": 30
}
],
"skills": "skills",
"mcpServers": {
"jira-search": {"command": "npx", "args": ["-y", "some-jira-mcp"]}
}
}
工具字段:
| 字段 | 说明 |
|---|---|
name |
工具名(非 [A-Za-z0-9_-] 的字符换成 _,≤ 63 字节),不能和已有工具重名 |
description |
给模型看的说明 |
command |
字符串数组:直接执行,数组里能在插件目录找到的相对路径会换成绝对路径;或一个字符串:交给 sh 执行(可以用管道) |
parameters(或 inputSchema) |
JSON Schema;required 会在执行前校验 |
perm |
read(不询问,可并行)/ write / net / shell(默认),按对应类别审批 |
timeout |
秒,默认 60,最多 600;超时整组进程被杀,退出码 124 |
执行约定:
- 参数按 schema 转成类型正确的 JSON 对象(
{"key":"CST-42","comments":3}),从 stdin 读。 - 工作目录是工作区根目录;环境变量
CST_PLUGIN_DIR(插件目录)、CST_WORKSPACE、CST_TOOL。 - stdout + stderr 就是工具结果(上限 512 KB),退出码非 0 视为失败。
perm为shell且审批模式是auto、系统有沙箱时,命令在沙箱里运行(只能写工作区和临时目录)。- 目前插件工具只支持 POSIX 系统(Linux / macOS / Termux)。
一个最小的 Python 工具:
import json, sys
args = json.load(sys.stdin)
print(f"hello {args['name']}")
MCP 服务器(mcp.json)
格式与 Claude Desktop / Cursor 相同:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
},
"github": {
"command": "github-mcp-server",
"args": ["stdio"],
"env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"},
"autoApprove": ["get_issue", "search_code"]
},
"old": {"command": "foo", "disabled": true}
}
}
| 字段 | 说明 |
|---|---|
command、args |
启动命令(按 PATH 查找);只支持 stdio 传输,带 url 的服务器会显示为 failed |
env |
追加的环境变量;${NAME} 取当前环境里的值,密钥不必写进文件 |
cwd |
工作目录(相对路径相对于工作区;插件里的服务器默认在插件目录) |
disabled |
true 时不启动 |
autoApprove |
true 或工具名数组:这些工具按只读处理(不询问、可并行) |
- 服务器在后台启动(握手、分页
tools/list),TUI 不等待;工具在握手完成后出现。headless 运行会先等最多 30 s。 - 工具注册为
mcp__<server>__<tool>,参数 schema 原样交给模型;默认按网络工具审批(auto模式下会询问,a可记住)。 - 结果里的 text 内容拼接返回;图片/音频只给出类型和大小;
isError视为失败。单次调用 60 s 超时,Esc 会发送notifications/cancelled。 - 服务器退出后状态变为 exited(
/mcp显示 stderr 最后一行),之后的调用直接报错;/mcp reload重启。 - 侧栏显示
MCP 就绪数/总数和每个服务器的工具数。
工作区信任
工作区里的 .agent/plugins/ 和 .agent/mcp.json 会在你的机器上执行命令,clone 下来的仓库可能带着它们,
所以默认不加载,首页会提示 “untrusted workspace: /plugins trust”。
/plugins trust:信任当前工作区(按真实路径记在settings.json的trusted_workspaces),立即加载。/plugins untrust:取消信任。- skills 和子 agent 角色只是文本,不受信任设置影响。
自定义子 agent 角色
.agent/agents/reviewer.md:
---
name: reviewer
description: Reviews a diff for bugs and missing tests; read-only.
tools: read_file, grep, glob, run_shell
readonly: true
model: deepseek-v4-pro
max_steps: 12
---
You review changes. Run `git diff` first, read the touched files around each
hunk, and report concrete problems with file:line and a suggested fix.
Do not restate the diff.
| 字段 | 说明 |
|---|---|
name |
角色名(默认取文件名);与内置 general / explore / plan 同名时覆盖内置角色 |
description |
写进主 agent 的角色索引,决定它什么时候选这个角色 |
tools |
允许的工具白名单(默认全部,task 和 ask_user 始终不给子 agent) |
readonly |
true 时去掉写文件和 shell 工具,并允许多个同类 task 并行 |
model |
用别的模型(同一 provider) |
max_steps |
子 agent 每轮的模型调用上限 |
正文是角色说明,追加在子 agent 的 system prompt 末尾。主 agent 调用
task(description="review auth", prompt="…", agent="reviewer");子 agent 的转录保存在
.agent/sessions/<会话 id>/sub-N.jsonl,/agents 里选中一条记录可以查看它的提示、工具调用和报告。