文章

从命令历史到可审计工作流

当本地操作只停留在终端历史里,很难直接变成可检查、可重复的流程。记录 SkillTape 如何把这段距离缩短。

每个开发者都有过这样的经历:在终端里完成了一系列操作,解决了问题,然后……忘记了具体步骤。命令历史(history)保存了输入过的命令,但没有保存上下文:为什么在这个目录下执行这条命令?为什么在第三步之前需要先执行第二步?如果环境变了,这些步骤还能复现吗?

命令历史的局限

终端命令历史记录的是“执行了什么”,而不是“为什么执行”。具体来说:

  • 缺少意图:npm install 可能是为了安装依赖,也可能是为了触发 postinstall 脚本,历史记录无法区分。
  • 缺少条件:某些命令只在特定环境下有效,但环境信息不在历史里。
  • 缺少验证:命令执行成功不代表结果正确。git add . 成功了,但可能把不该提交的文件也加进去了。
  • 缺少边界:历史记录没有区分“安全操作”和“危险操作”。一条 rm -rf 和一条 ls 在历史里看起来一样。

这些问题在个人开发中可能只是偶尔的烦恼,但在团队协作或 Agent Skill 场景中会变成真正的障碍。

可审计工作流的需求

一个可审计的工作流需要回答几个基本问题:

  1. 做了什么:具体的操作步骤和参数。
  2. 为什么做:每一步的目的和前置条件。
  3. 结果如何:每一步的输出和验证结果。
  4. 边界在哪:哪些操作是安全的,哪些需要额外确认。

这不是要给每条命令写一篇论文,而是要把隐含的上下文显式化,让其他人(或未来的自己)能够理解、检查和复现。

SkillTape 的完整链路

SkillTape Beta · v0.1.0 把这个思路具体化为五个核心步骤加一个输出步骤:

Capture → Tape → Compile → Lint → Verify → Receipt → Export

Capture — 捕获已经发生的事

Capture 不是重新执行命令,而是记录已经发生的事情。它使用 Redacted PTY(伪终端)捕获命令的输入和输出,同时自动编辑敏感信息:

skilltape capture demo \
  --workspace "$workspace" \
  --command /bin/echo \
  --output "$workspace/tape" --yes --json

Capture 的安全边界值得注意:

  • 拒绝不安全的路径和符号链接边界。
  • 敏感信息(密码、token、密钥)在捕获时被编辑或仅保留摘要。
  • 每次捕获生成唯一的 Tape ID,用于后续追溯。
  • 交互式 stdin 转发支持需要用户输入的命令。

这意味着 Capture 记录的是“安全版本”的操作,不是原始的、可能包含敏感数据的操作。

Compile — 组织成可读格式

Compile 把零散的 Tape 数据组织成结构化的 Skill 包。编译后的 Skill 包含:

  • 命令序列和参数。
  • 环境信息和工作目录。
  • 必要的上下文注释。

编译后的 Skill 是人可读的,不是只有机器能理解的二进制格式。这是“可审计”的关键——审阅者能看懂 Skill 在做什么。

Lint — 结构检查

Lint 检查生成的 Skill 是否符合规范:

skilltape lint "$workspace/skill" --strict --json

--strict 模式会报告所有不符合最佳实践的部分,不仅仅是语法错误。Lint 不检查 Skill 的语义正确性(“这条命令是否合理”),只检查结构完整性(“Skill 的格式是否正确”)。

Verify — 隔离重放与验证

Verify 是整个链路中最关键的步骤。它在沙箱环境中重放 Skill,记录每一步的结果:

skilltape verify "$workspace/skill" \
  --receipt "$workspace/receipt.json" --json

隔离环境的实现依赖平台:

  • Linux:使用 Bubblewrap(bwrap),需要 user namespace 支持。
  • macOS:使用系统自带的 /usr/bin/sandbox-exec(Seatbelt 机制)。
  • Windows:故意失败关闭,直到等效的沙箱机制被集成。

沙箱限制了:

  • 文件系统访问(只能访问指定的工作区目录)。
  • 网络访问(禁止连接外部服务)。
  • 进程权限(不能执行危险的系统操作)。

如果沙箱不可用,Verify 不会“尽力而为”地在无隔离环境下执行,而是直接失败。这是一种安全设计:宁可不可用,也不在没有隔离的情况下执行未审阅的 Skill。

Receipt — 可审计的证据

Receipt 是 Verify 的输出,记录了这次隔离重放的完整信息:

  • 这次流程的 Tape ID 和 Skill 哈希值。
  • 重放的时间戳和执行环境。
  • 每一步的执行结果。
  • 最终状态:成功或失败。

Receipt 不提供超出这次重放的保证。它不证明 Skill 是“安全的”或“正确的”,只证明“这次隔离重放产生了这些结果”。

Export — 导出为 Agent 格式

Export 把 Skill 导出为特定 Agent 的格式。支持通用格式和 Claude Code 格式,导出器是确定性的——相同的 Skill 总是生成相同的输出。

实际应用

在日常开发中,这种可审计工作流的价值体现在几个场景:

故障复现

当一个问题需要其他人帮忙时,可审计的流程比口头描述更可靠。“运行 skilltape capture,然后把 Tape 发给我”比“我之前好像跑了一个什么命令”有用得多。

知识传递

新成员加入时,可审计的操作记录比文档更具体。文档说“运行构建脚本”,可审计的流程说“在这一步执行了 npm run build,输出了这些内容,耗时 3.2 秒”。

版本回溯

当需要回到某个状态时,可审计的流程能清楚地说明“当时做了什么”。Tape 记录了完整的操作序列,可以精确回溯。

Agent Skill 开发

当需要把本地操作转化为可重复的 Skill 时,可审计的流程是天然的输入。Capture → Compile → Lint → Verify 这条链路本身就是从“本地操作”到“可分享 Skill”的转化过程。

与 SkillSync 的衔接

SkillTape 解决的是“执行后如何留下可审计记录”的问题,而 SkillSync 解决的是“执行前如何检查来源和差异”的问题。两者的衔接方式是:

  1. 先用 SkillSync 检查 Skill 的来源、兼容性和差异。
  2. 审阅检查报告,确认没有 fail 状态的发现。
  3. 用 SkillTape 对明确的本地操作进行 capture、compile、lint、verify。
  4. 保留 Receipt 作为这次操作的审计证据。

这种“先检查、再执行、后记录”的模式,把判断拆成了可以逐项查看的材料。

接下来

可审计工作流的目标不是完美记录一切,而是在需要的时候能够找到足够的证据。SkillTape 的公开版本覆盖了基本的捕获、编译、检查、重放、验证和导出流程,但还有很多可以改进的地方。比如:

  • Windows 上的沙箱支持。
  • 更丰富的 Export 格式(更多 Agent 的适配)。
  • 与 CI/CD 流程的自动集成。
  • 团队环境中的审计记录共享。

这些都是值得继续探索的方向。

评论