【免费下载链接】gsd-core
Git. Ship. Done - Core
/gsd:surface是 GSD(Get. Ship. Done — Core)提供的运行时技能表面(skill surface)开关命令,用于在已安装环境下动态启用/禁用技能集群、切换命名 Profile,而无需重新执行安装流程。本文以仓库变更记录 feat-3408-skill-surface.md 为核心骨架,结合 runbook、ADR-0011、研究备忘录与 src/surface.cts 源码,完整讲解该功能的背景、子命令、10 个集群、状态持久化模型与底层引擎原理,读完即可上手管理自己的技能表面。
一、为什么需要技能表面:技能清单预算与静默丢弃
Claude Code 等运行时会在每一轮对话把已安装 skill 的name + description枚举进系统提示中的<available_skills>块,该块受skillListingBudgetFraction限制——默认是模型上下文窗口的1%,在 200k 上下文中约2000 tokens。当多个插件叠加、描述总长超过预算时,运行时只会静默截断尾部,用户根本无法察觉部分技能已被丢弃。
研究备忘录 2026-05-12-skill-surface-budget.md 给出了 GSD 当时的审计数据:
| 指标 | 数值 |
|---|---|
| 已安装技能 | 66 |
| 已安装子代理 | 33(不进入<available_skills>,经Task调用) |
| 技能描述总字符数 | 4,787 |
| 估算描述 tokens(÷4) | ~1,196 |
| 平均描述长度 | 72.5 字符 |
| 描述长度上限(scripts/lint-descriptions.cjs 强制) | 100 字符 |
| GSD 占 200k 上下文 1% 预算的份额 | ~60% |
也就是说,GSD 单靠自己就吃掉了默认技能清单预算的约六成,再叠加任何一个体量相近的插件就会超限、触发静默丢弃(issue #3408 的报告者装了 135 个技能)。更关键的是:描述已经压到 72.5 字符均值、100 字符硬上限,继续压缩文字不是出路,出路是少发射技能。根因是缺乏 profile/surface 接缝——安装器无条件写入全部技能,运行时又没有无需重装的开关。
二、整体方案:ADR-0011 的 Phase 1(安装 Profile)+ Phase 2(运行时 Surface)
方案沿用了研究备忘录的推荐路径,分两阶段落地,记录在 ADR-0011(并取代早期草案 ADR-0010):
- Phase 1 — 安装期命名 Profile:安装时用
--profile=<name>选择core/standard/full,计算requires:依赖闭包后写入运行时目录,并把所选 Profile 持久化到.gsd-profile标记文件;gsd update读取标记、尊重 Profile,不再在升级时悄悄膨胀回 full。详见同主题的变更记录 feat-3408-skill-profiles.md。 - Phase 2 — 运行时 Surface 模块:即本文主角
/gsd:surface。引擎在gsd-core/bin/lib/surface.cjs(TypeScript 真源为 src/surface.cts),复用 Phase 1 的stageSkillsForProfile/stageAgentsForProfile完成重新落地;集群定义独立放 src/clusters.cts,让引擎和未来的 SDK 调用方无需加载整个 profile 模块即可引用。
功能层面的权威说明可另见 skill-surface-budgeting.md,其中记录了三条需求约束:安装器必须解析--profile=<name>并持久化到.gsd-profile(REQ-SURFACE-01);--minimal与--core-only必须保持为--profile=core的别名(REQ-SURFACE-02);运行时表面状态必须独立于安装 Profile 标记持久化(REQ-SURFACE-03)。
三、三个命名 Profile 与requires:依赖闭包
Profile 定义在 src/install-profiles.cts 的PROFILES常量中(ADR-457 构建时发布:手写.cjs已坍缩为 TypeScript 真源,行为逐字节保留):
| Profile | 用途 | 基集(源码现状) |
|---|---|---|
core | 最小主循环表面 | new-project、discuss-phase、plan-phase、execute-phase、phase、help、update、surface |
standard | 核心 + 常用阶段/工作区命令 | core 基础上追加onboard、review、config、progress、resume-work、pause-work、workspace |
full | 完整表面(默认) | '*'哨兵,全部技能 |
值得注意两点演进:
- 研究备忘录曾指出旧 minimal allowlist 缺少
phase——它被 38 个技能引用,是典型的"依赖热点"。当前源码的core已把phase纳入基集,规避了"最小安装 + 主循环调用断裂"的潜在缺陷。 - 每个 Profile 的有效技能集合是基集的传递闭包:
effective = CLOSURE(base, requires: manifest)。standard自动包含core的全部成员,--profile=core,audit组合则解析为union(closure(core), closure(audit))。
闭包的"图"来自每个技能 frontmatter 新增的requires:字段(66 个技能全部声明)。解析函数resolveProfile对 mode 列表做flatMap(split(','))归一化,一旦命中full直接返回'*'哨兵;无效/损坏的 marker 会回退为 full,避免出现空安装。该依赖图由 CI 门禁 scripts/lint-skill-deps.cjs(接入pretest)强制校验:每个requires:必须能解析到真实技能 stem,防止 Profile 闭包静默过度安装或装坏依赖链。
四、/gsd:surface子命令全解
runbook 见 commands/gsd/surface.md(技能包装形态见 skills/gsd-surface/SKILL.md)。命令解析$ARGUMENTS的第一个 token:
| Token | 动作 |
|---|---|
list | 显示启用 + 禁用的集群与技能 |
status | list的别名,附加 token 成本汇总 |
profile <name> | 写入baseProfile并重新落地(re-stage) |
profile <n1>,<n2> | 组合 Profile(逗号分隔,无空格) |
disable <cluster> | 把集群加入disabledClusters并重新落地 |
enable <cluster> | 从disabledClusters移除集群并重新落地 |
reset | 删除.gsd-surface.json,回到安装期 Profile |
| (空) | 视作list |
list输出示例(runbook 原始格式,…为省略的其余集群):
Enabled (N skills, ~T tokens): core_loop: new-project discuss-phase plan-phase execute-phase help update audit_review: … … Disabled: utility: health stats settings … Token cost: ~T (budget cap ~500 tokens for 200k context @ 1%)status额外追加 Profile 摘要:
Base profile: standard (from .gsd-surface.json) Install profile: standard (from .gsd-profile)五、10 个技能集群:定义与成员
集群是技能表面的唯一权威分类法,定义在 src/clusters.cts 的CLUSTERS常量(构建时发布,来源为研究备忘录 §3.2 的贪心聚类)。成员允许重叠(一个技能可属多个集群),且每个已安装技能 stem 必须至少出现在一个集群中(由surface-clusters.test.cjs强制)。源码当前十个集群:
| 集群 | 成员(源码现状) | 语义 |
|---|---|---|
core_loop | next、new-project、onboard、discuss-phase、plan-phase、execute-phase、help、update | 主循环最小集 |
audit_review | code-review、review、audit-fix、audit-milestone、audit-uat、verify-work、validate-phase、plan-review-convergence、eval-review、add-tests、secure-phase | 审计与评审 |
milestone | new-milestone、complete-milestone、milestone-summary、health | 里程碑管理 |
research_ideate | sketch、spike、forensics、explore、graphify、ns-ideate | 研究/构思 |
workspace_state | pause-work、resume-work、workspace、workstreams、thread、capture、inbox | 工作区与状态 |
docs | docs-update、ingest-docs | 文档 |
ui | ui-phase、ui-review | UI 工作流 |
ai_eval | ai-integration-phase、eval-review | AI 集成与评估 |
ns_meta | ns-context、ns-ideate、ns-manage、ns-project、ns-review、ns-workflow | 命名空间元工作流 |
utility | health、stats、settings、cleanup、pr-branch、ship、undo、fast、quick、quick-batch、autonomous、config、progress、phase、review、update、help、code-review、import、manager、map-codebase、profile-user、spec-phase、ultraplan-phase、mvp-phase、execute-phase、review-backlog、debug、extract-learnings、mempalace-recall、mempalace-capture、surface | 工具杂项(最重桶) |
utility是描述 token 占比最重的集群(研究阶段约占总描述 tokens 的 36%),且最异构——大量技能是"每项目一次"而非"每会话一次",是开启按需裁剪时的首选目标。
六、状态持久化:.gsd-profile与.gsd-surface.json的分工
Phase 2 的核心设计决策是两套状态文件分离:
.gsd-profile(~/.claude/.gsd-profile):安装期身份,由安装器写入,gsd update尊重它。.gsd-surface.json(~/.claude/.gsd-surface.json):会话期集群开关,由/gsd:surface读写。
注意:本 changeset 记录的状态文件路径为
~/.claude/skills/.gsd-surface.json(skills 子目录),而最终实现(runbook 与 src/surface.cts 的SURFACE_FILE_NAME = '.gsd-surface.json'+path.join(runtimeConfigDir, ...))将其放在base Claude 配置目录~/.claude/.gsd-surface.json。runbook 的runtimeConfigDir resolution一节对此有专门说明:传给applySurface的是 base config 目录而非 skills 子目录,与installRuntimeArtifacts/uninstallRuntimeArtifacts收到~/.claude作为configDir保持一致;技能目录~/.claude/skills/gsd-*/是因为claude global布局的destSubpath = 'skills',由configDir派生而非根。本文以最终实现为准。
状态文件的结构(src/surface.cts 的SurfaceState类型,写入时经platformWriteSync原子写为缩进 2 的 JSON):
{ "baseProfile": "...", "disabledClusters": [...], "explicitAdds": [...], "explicitRemoves": [...] }读取方readSurface会做结构校验:baseProfile必须是字符串、三个数组字段必须是数组,文件缺失或损坏一律返回null(failing closed)。
七、底层引擎原理:解析顺序与两阶段提交
引擎导出的核心函数(src/surface.cts)包括readSurface、writeSurface、resolveSurface、applySurface、listSurface、pruneSkillDirs。
有效技能集解析公式(resolveSurface,源码注释原话):
Effective skill set = base profile ∪ explicitAdds − disabledClusters − explicitRemoves随后经 manifest 做传递闭包。解析顺序:
- 以
surface.baseProfile(无则回退readActiveProfile,再回退'full')解析基础 Profile; - 删除被禁用集群覆盖的技能;
- 加入
explicitAdds及其传递闭包(BFS); - 删除
explicitRemoves(仅删该 stem,不级联)。
agents由技能派生:对每个保留技能,读取 manifest 中_calls_agents_<stem>条目,收集其引用的子代理 stem。返回的名称形如surface:<baseProfile>或profile:<name>。
两阶段提交协议(applySurface,runbook 的Mutation protocol一节):所有变更操作(profile/disable/enable/reset)都先在内存推导候选状态opts.surfaceState,再交给applySurface,绝不先调writeSurface。applySurface内部先遍历layout.kinds逐个kind.stage()把每种产物(skills / agents / commands / kimi-agents 等)暂存到临时目录,全部成功后:
- 执行
retiredArtifactCleanup.pruneRetiredRuntimeArtifacts; - 对每个 kind 执行
_syncGsdDir同步到目标目录(skills 目录的裁剪统一委托给pruneSkillDirs,用户自建的gsd-*目录一律保留并告警); - 最后才发布状态:
candidateState === null时删除.gsd-surface.json(reset语义),否则writeSurface写入候选状态。
任何 kind 暂存失败都会让已安装产物和持久化状态双双保持原样——这就是"变更不落地则不写状态"的原子性保证。applySurface还有多重防护:runtimeConfigDir必须与layout.configDir相等(否则抛TypeError)、assertTestHomeSandboxed防测试逃逸到真实 home、assertDestWithinConfigHome约束目标路径。
token 成本估算(listSurface):对每个启用技能读取安装源的commands/gsd/<stem>.md,取 frontmatterdescription:值,按ceil(长度 ÷ 4)累加,与审计脚本口径一致。
八、运行时目录解析与环境变量
runbook 给出的 global 安装参考脚本:
# Claude Code — global install RUNTIME_CONFIG_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}" SCOPE="global" # Artifact destinations are derived from runtime layout # via resolveRuntimeArtifactLayout(runtime, RUNTIME_CONFIG_DIR, SCOPE) # then applySurface(RUNTIME_CONFIG_DIR, layout, manifest, CLUSTERS)- Surface 状态文件:
${RUNTIME_CONFIG_DIR}/.gsd-surface.json(即默认~/.claude/.gsd-surface.json)。 - 所有路径均可通过读取
CLAUDE_CONFIG_DIR环境变量覆盖。 - 多运行时场景下,安装期若 Profile 冲突,按最保守 Profile(最小有效技能集)解决。
九、错误处理与恢复路径
runbook 定义的错误行为:
- 未知集群名 → 列出合法集群名,不写盘直接退出;
- 未知 Profile 名 → 列出已知 Profile(
core、standard、full),退出; - 缺少
surface.cjs引擎模块 → 提示Run npm i -g @opengsd/gsd-core以重装 GSD。
enable的边界:若 surface 状态为null,说明没有任何增量,直接输出 "No surface delta active."。reset的边界:只有安装期 Profile 成功落地后,状态文件才被移除。
十、测试与 CI 保障
仓库对表面引擎有专门的回归测试(当前实际存在的测试文件,见 tests 目录):
- surface-empty-manifest-agents.test.cjs — 空 manifest 下的代理派生边界;
- runtime-artifact-layout-surface.test.cjs — 表面落地与安装引擎的产物路径/命名一致性(ADR 中提到的
surface-state / surface-clusters / surface-resolve / surface-apply / surface-list系列测试已随源码折叠合并到上述文件与主测试套件); - surface-md-paths.regression.test.cjs — 技能文档路径回归;
- 集群覆盖完整性由集群模块的
allClusteredSkills()辅助函数与对应测试保证(每个已安装 stem 必须落入至少一个集群)。
配合 Phase 1 的scripts/lint-skill-deps.cjs(接入pretest),requires:依赖完整性在 CI 阶段即被拦截。
十一、实战速览:典型操作序列
# 1) 查看当前启/禁用状态与 token 成本 /gsd:surface list # 2) 查看 Profile 摘要(含安装期 vs 当前 base) /gsd:surface status # 3) 切换到 standard Profile(无需重装) /gsd:surface profile standard # 4) 组合 Profile /gsd:surface profile core,audit # 5) 按集群关闭最重的 utility 桶 /gsd:surface disable utility # 6) 需要时再加回 /gsd:surface enable utility # 7) 反悔:清空增量,回到安装期 Profile /gsd:surface reset典型收益(ADR-0011 记录):受上下文预算约束的用户可先--profile=core安装,随后用/gsd:surface enable <cluster>增量扩容,全程无需重装;requires:闭包保证任何部分裁剪都不会悄悄破坏跨技能调用。需要注意:该命令是 GSD 侧的单方面解决方案,不依赖 Anthropic 平台的原生技能开关 API(平台侧的 per-skill toggle 与预算协商仍作为独立诉求跟进);utility桶技能体量大,按需启用是压预算最直接的手段。
【免费下载链接】gsd-core
Git. Ship. Done - Core
相关推荐
GSD Skill Surface 运行时管理全解析:使用 `/gsd:surface` 按集群开关技能、切换 Profile 而不重装
GSD Skill Surface 运行时管理全解析:使用 /gsd:surface 按集群开关技能、切换 Profile 而不重装 GSD(get shit
人工智能AI 应用提示工程开发工具工作流自动化AI Agentget-shit-done 运行时技能面开关指南:`/gsd:surface` 命令的实现原理与实战用法
get shit done 运行时技能面开关指南: /gsd:surface 命令的实现原理与实战用法 本文围绕 get shit done(GSD)随 .ch
人工智能AI 应用提示工程开发工具工作流自动化AI AgentMetabase 如何用 Guest Embeds 在不需要 Metabase 账号的情况下嵌入仪表板?
Metabase 如何用 Guest Embeds 在不需要 Metabase 账号的情况下嵌入仪表板? 如果你的目标是把 Metabase 的仪表板嵌入自己的
数据分析数据可视化后端数据库客户端企业应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考