
这是什么
一个把「做过一次的事」变成可复用 agent 技能的桌面录制器。在 macOS 以及 Windows 11 的 x64 与 ARM64 上,它录下低帧率的屏幕视频、应用与窗口切换、浏览器地址、剪贴板预览、可选的自带终端(含完整命令输出),以及可选的口述旁白——旁白由 Whisper 在本机转写。在你点下 Analyze 之前,什么都不离开这台电脑;点下 Analyze 之后,时间线交给随包发布的 GitHub Copilot CLI,由它重建出一个总体意图和一份有序步骤表,而这份结果还可以逐条人工修改。从已批准的 analysis 出发,它生成 Skill——一份由可审阅计划渲染出来的 SKILL.md 流程,固定值以 {{id}} 占位、渲染时才替换成字面量——或一条定时 Automation,面向 Microsoft Scout、Microsoft 365 Copilot Cowork 或任意支持技能的 agent;架构清单里 Copilot Studio 仍是禁用状态。发送之前有一道在机器上运行的密钥与个人信息检测,而技能生成优先使用目标 agent 的原生工具(例如 gh 命令行),而不是回放录下来的点击。它以源码发布:安装脚本下载一个锁定版本的 Node.js 运行时,在本机构建那个确切的 tag 提交;仓库以 MIT 许可公开,建于 2026-07-29。
谁做的这是微软的仓库,不是个人项目,走的是微软的 MIT 许可与 CLA 流程。164 次提交里 159 次出自两个人:Giorgio Ughini 78 次,Adi Leibowitz 81 次(分布在三个邮箱、两个关联账号上);同事补了两次,Dependabot 两次。120 次提交带共同作者尾注,其中 100 条只写「Copilot App」——也就是说这段历史大多是在微软自己的编码 agent 参与下写出来的。
它是怎么搭起来的
组成 · 6一个本地优先的桌面应用,内部有两级 agent。Electron 承载录制器与 React 界面;采集、会话存储、帧提取与旁白转写都发生在这台机器上,而唯一通向外部的那道缝上坐着一层密钥与结构化个人信息的检测,于是外发文本可以被遮挡、屏幕上的值也可以被模糊,然后才轮到 Analyze。采集的信号首先是一批廉价的操作系统事件——应用切换、窗口标题、地址、剪贴板变化、终端命令与完整终端输出——低帧率视频只是机会性的补充,只有在事件本身说不清时才由 describer 去取帧。那个 describer 与两个 builder 都是 GitHub Copilot CLI agent,它们的行为说明是仓库里普通、可手改的字符串导出,而不是打包好的技能目录;每份说明旁边都有一份 common/ 里的 Zod 契约,规定 agent 允许提交什么。目标 agent 到底能做什么,则由一份带自校验的架构清单逐目标声明:Scout 有技能也有自动化,Cowork 只有技能、因为它的能力目录里没有浏览器自动化,通用 agent 技能只能导出,Copilot Studio 在场但被禁用。于是这个程序真正难的地方都是边界——什么留在本地、生成的步骤允许伸向哪个工具、以及用户拿到的文件是否与批准过的计划一致。
- common/
- 28 个共享契约与逻辑文件,共 140 KB:analysis 与技能计划的类型、
{{id}}token 所用的取值替换、automation 与 bundle 模型、25 KB 的 IPC 表面、12 KB 的敏感内容模块、关联与描述辅助函数、架构清单——几乎每个文件旁边都有一份单元测试。 - electron/
- 主进程与两级 agent。采集侧:24 KB 的录制控制器、31 KB 的音频录制器(带自己的采集 preload)、13 KB 的视频录制器、16 KB 的帧提取器与关联器,以及窗口、地址与剪贴板收集器。分析侧:describer(13 KB 说明、22 KB 工具、17 KB 实现)与两个 builder——技能(19 KB)与自动化。另有 terminal(node-pty、shell 发现与集成)、五个各带测试的
copilot-signin*模块,以及 Scout、Cowork 与通用 agent 技能三份能力目录。 - src/
- 20 个渲染层文件,共 261 KB,其中 68 KB 是一份样式表:65 KB 的会话 Library、30 KB 的 Recorder、29 KB 的计划编辑器、19 KB 的录制控制条,另有 SKILL.md 审阅弹窗、敏感内容复查页、自带终端、「会录下什么」面板,以及几个带测试的放置与审阅状态模块。
- evals/
- 四套针对「真正有方差的部分」的评测——describer 场景与它们的模拟页面、自动化 builder、技能 builder,以及端上脱敏管线——每套都有评分表,大多配确定性打分器,其中一个可选模型评审;另有一份
evals/tsconfig.json,被根 TypeScript 配置刻意排除在外。 - scripts/、install.ps1 与 install.sh
- 打包与合规层:79 KB 的许可证与再分发检查器(配 39 KB 测试)、经过审阅的 Electron 下载与启动器、带自测的 Windows 依赖安装、lockfile 可移植性、成品包校验、三个针对产物边界与架构的小断言脚本,以及两个按提交锁定的源码安装器(34 KB PowerShell 与 20 KB shell)。
- .github/
- 三个工作流——Windows 上的 x64 与 ARM64、Non-Windows 上的 macOS 与 Ubuntu、以及手动触发的便携构建——所有 action 都固定到完整提交 SHA,Dependabot 配成每周一次并带七天冷却期。旁边是
copilot-instructions.md,把 agent 的 pull request 引向当前发布分支。
取舍,以及它替代了什么
以「源码发布」为默认通道 替代 每个 tag 都挂上安装包、便携二进制或构建产物
RELEASING.md说得很明确:dist/、dist-electron/、node_modules/以及任何由安装脚本拼出来的应用都绝不能挂上去,而且 release 里的源码归档本身不是安装器。二进制发布是另一个决定,附带自己的义务:与版本匹配的合规包、在每个原生平台与架构上分别构建、公布 SHA-256,并声明这个包到底有没有签名。优先用目标 agent 的原生工具,而不是回放录下来的点击 替代 重放录像里那一套界面操作
两种产物都被做成先伸手去拿
gh、web_fetch或设备上的命令行,而不是模拟点击;行为说明里也直接这样排序:优先设备上的一等 CLI,尤其是通过gh走 GitHub,只有在真正只能走界面时才退回浏览器自动化。builder 评测套件之所以存在,正是因为这条偏好被违反过一次——builder 选了 Playwright 而不是gh——而能力目录后来被改到能让这套评测通过。先给一份可审阅的计划,再落任何文件 替代 一轮之内直接生成 SKILL.md
propose_plan会停下来等审阅,submit_skill只在批准之后才执行,一轮只提一次案。0.7.0 把同一条原则延伸到产物本身:可选的审阅把成品文件只读地渲染出来、什么都不写,并让 Add 或 Export 直接安装同一批字节、不再多花一次模型调用;而改动计划会让预览作废,而不是悄悄渲染出过期文本。把固定值做成渲染时才替换的 token 替代 把录像里恰好出现的字面量直接写进正文
一个固定不动的网址、仓库 slug 或路径只声明一次,带上标签,并在步骤里用
{{id}}引用,于是用户只改一处、处处生效。说明书也从另一头划了界:每次运行都会变的东西不该做成固定值,也不能因为录像里用过一次就把某台机器的路径钉死。把 Copilot CLI 钉死,并在登录期间关掉缓存自动更新 替代 接受自动更新缓存里碰巧留着的那一版
随包发布的 1.0.71 不接受
--web-flow,所以依赖被钉到经过审阅的 1.0.78,并用--no-auto-update login --web-flow运行,好让浏览器 OAuth 变得确定。配套的回归测试用一只拒绝授权的假浏览器跑真实的 PKCE 与回环流程——既测了握手,又不联系 GitHub、也不登录任何账号。
依据README.md(13,195 字符)、RELEASING.md、evals/README.md、electron/skillbuilder/instructions.ts、common/skill.ts、common/architecture-registry.ts、common/analysis.ts、electron/describer/instructions.ts、.github/copilot-instructions.md、.github/dependabot.yml、package.json、.github/workflows/ 下三个文件、CONTRIBUTING.md、docs/future-features.md,以及完整的 254 个文件树及其体积。
制作过程
6 个阶段- 01
十周、十三个版本,以及「改动先进 release 分支」
仓库创建于 2026-07-29(最早一次提交的日期是 2026-07-24),共 164 次提交——七月 107 次、八月 34 次、九月 23 次——发过 十三个 release:
v0.1.0、v0.2.0、v0.2.1是在同一个晚上 19:50 前后接连发布的,版本线一直走到 2026-09-21 的v0.7.0。有一天连发了三个版本:2026-09-16 的v0.6.0(08:49)、v0.6.1(12:06)、v0.6.2(13:27)——这是「一处修复验证过就立刻发补丁、不攒批次」的节奏。真正不寻常的是改动落在哪里:.github/copilot-instructions.md告诉编码 agent,pull request 必须指向当前活跃的release/<semver>分支而不是main,因为main滞后于发布分支,只有在切版本并合并时才前进。那份文件里写的当前分支还是release/0.3.0,一个每发一版就要改一次、却没人回头看的文档就是这个样子。RELEASING.md则把机制写清楚:发布 pull request 只升package.json与package-lock.json的版本、不打标签;等合并后的main提交把所有工作流跑绿,才打注解标签;release notes 里要写完整提交 SHA,以及install.ps1与install.sh的 SHA-256。围绕它的是约 4,168 个星、440 个 fork 和 41 个开着的 issue。 - 02
历史里只有两个名字,以及一条写着「Copilot App」的尾注
贡献者列表有六项,但活基本是两个人干的:Giorgio Ughini 提交 78 次(用了两个邮箱),Adi Leibowitz 提交 81 次(三个邮箱、两个 GitHub 账号:
adilei与adilei-powerapps)。同事 Dan Fiedler 贡献了把 GitHub Actions 固定到完整 SHA 的那一次,Ramakrishnan Raman 两次,Dependabot 两次。真正值得读的是尾注统计:164 次提交里有 120 次带共同作者行,其中 100 条只写「Copilot App」,17 条写adilei,两条是依赖机器人,一条是 Ughini 自己。也就是说,仓库是逐条提交声明「这段历史大多有微软自己的编码 agent 参与」的。外部贡献则是持续到来、然后等着:两个加简体中文界面的 pull request(#72 与 #94,作者还不是同一个人)都还开着;技能运行时评测提案 #70 从 2026-08-24 开到现在,维护者在里面问「so, what is this exactly doing?」;音频停止刷写修复 #93、Windows 启动脚本 #67 同样开着。每一条下面都跟着同一句 CLA 机器人留言,而 #68 的作者干脆写明了:Windows 与 Non-Windows 的工作流停在action_required,要等维护者批一下才会跑。仓库层面的自动化则相当克制:.github/dependabot.yml只盯 GitHub Actions 这一件事,每周跑一次、带七天冷却期;CONTRIBUTING.md全文只有七行,把贡献权利、MIT 许可和第三方材料的出处要求一次说完。 - 03
先有计划,才有文件
Skill Builder 是一段两阶段的对话,它的说明书用一个小标题把这件事钉死:「Two phases — never skip the plan」。agent 先读已批准的 analysis,调用
propose_plan交出它的泛化方式、打算固化的固定值和有序步骤,然后停下;用户用自然语言回复,计划被修订,一轮只允许一次提案。真正写出产物的submit_skill,只在消息里说计划已批准之后才会被调用。计划本身是带类型的,不是一段散文:common/skill.ts用 Zod 规定每个步骤要么是calculation(读取、推导、判断、格式化),要么是action(提交、发送、创建、删除);而每次运行都一样的字面量会变成一个固定值,带 id、给人看的标签和确切字符串,步骤正文用{{id}}引用它。渲染是刻意字面的:renderSkillMarkdown写出 YAML frontmatter——kebab-case 的名字(slug 化后最多 60 字符)、经JSON.stringify输出的 description(因为这样得到的是合法的 YAML 双引号标量,正文里的冒号或逗号弄不坏文件)、可选的allowed-tools列表——然后是替换掉全部 token 的正文。0.7.0 补上了这桩交易的另一半:可选的只读 Review SKILL.md 把完整文件渲染出来却什么都不写,Add 或 Export 直接用同一批字节、不再多花一次模型调用;而用户一旦改动计划,预览即作废。计划里还有一份allowedTools,写的是权限模式,例如Bash(gh *);而每个步骤的tools里写的是运行时标识符,例如glob或bash——说明书专门交代,两者不要混为一谈,也不要用「reasoning」「filesystem」这类含糊的标签。 - 04
那个催生出一整套评测的回归
evals/之所以存在,是因为真正会出问题的地方不在录制器。describer 评测会把一份合成会话(session.json加events.jsonl)铺进一个隔离的临时会话目录,跑真实管线与真实的Describer,再拿结果对评分表,一个场景十五到二十五秒,没有视频、也没有实拍带来的抖动。评分是确定性的、不调用模型:意图必须点对主体,步骤数要落在区间内,应该出现的应用要出现,关键动作要构成有序子序列,被复制的具体值要露面;而录制器的起止框、权限弹窗、带跟踪参数的跳转绝不能变成步骤——命中一条禁用项直接判失败,否则满分里过八成即算通过。可选的--judge再加一名 Copilot 评审,按零到五分打忠实度,默认关闭以保持可复现。builder 评测是被一次真实回归催出来的,它的 README 说得很直白:泛化 GitHub 相关工作时,builder 更愿意用 Playwright 驱动浏览器,而不是gh命令行——即便 Scout 就跑在用户自己那台装了gh、也已登录的机器上。现在十个场景把「原生能力」钉住,其中两个直接盯 gh 与浏览器的这个案子,也正是这套评测推动了scout-catalogue.ts的那处修正。第三套评测检查技能计划的结构,第四套守住端上脱敏管线,而它的真实图片 OCR 变体在字体、权重或网络不满足时会以退出码 0 自行跳过。场景本身是一批固定文件:十一个业务流程——把网页价格抄进表格、从发票里抽行、整理发布说明、把线索录进 CRM、在 Windows 上部署并记下线上地址——外加三个更长的终端相关场景,以及一组用于真实端到端拍摄的模拟网页。 - 05
一条 npm test、三个工作流、一个 79 KB 的合规脚本
测试跑在 Node 自带的测试器上,配合
--experimental-transform-types,再加一个小解析钩子:把无扩展名的 import 指向.ts,并把唯一那处electron引入换成无头替身——于是这套测试跑的是真实应用源码,却不需要打包器。package.json里的npm test一行逐个点名 43 个文件,而各 pull request 里引用的测试数一路往上爬:2026-08-23 是 176,2026-09-15 是 225,第二天 237,2026-09-21 是 267。持续集成是三个工作流。Windows 那个跑在windows-latest与windows-11-arm上,先证明install.ps1会拒绝一个可变的源码引用,再真做一次按提交锁定的源码安装(禁掉自动启动),然后校验 lockfile 可移植性、生成许可证清单、跑测试、构建、打出原生安装包并核对包架构。Non-Windows 在 macOS 与 Ubuntu 上做同一套,macOS 额外准备完整的对应源码包,并断言平台上 libvips 的许可证文本确实在包里。便携预览构建只在手动触发时运行,因为工作流里那句注释写着:普通合并不该为打包花掉十到十五分钟。围绕这一切的合规机器比应用本身还大:scripts/compliance.mjs有 79 KB,配一份 39 KB 的测试;package.json里是逐版本的allowScripts审批;RELEASING.md有一张表,规定 Copilot SDK、Electron、sharp-libvips、ONNX Runtime 与 Tesseract 这几样任一升级前都必须重读该版本的条款。 - 06
把 CLI 钉死,以及在一次 404 之后重写安装说明
有两处修复很能说明这个项目有多少精力花在「让别人的工具变得可预测」上。第一处把
@github/copilot钉在 1.0.78,并用--no-auto-update login --web-flow运行它——原因是此前随包发布的 1.0.71 不接受--web-flow,而缓存里自动更新过的 CLI 会让浏览器登录取决于某台机器上恰好留着哪个版本。它的回归测试写法不常见:用一只会拒绝授权的假浏览器去驱动随包 CLI 的 OAuth 地址、PKCE 挑战与回环回调,因此全程不联系 GitHub、也不授权任何账号。第二处是只在 Windows 出现的补救路径:在那种公共 registry 被封、而获批镜像又不需要交互登录的受管机器上,npm ci会针对获批 registry 重试恰好一次——且只在没有任何显式 npm 配置、本机设备信息又能给出 Microsoft Entra 租户线索时这么做,并且只作用于那个子进程;绝不靠保存 npm 设置、放宽 TLS、跳过完整性校验或改动脚本审批来实现。文档则从另一头得到同样的待遇:有用户把 README 模板里的<40-character-release-commit>原样粘进终端、撞上 404 之后,两个 pull request 把可复制的占位命令换成指向 release 页面的指引与三步大白话——理由是要装这个东西的人未必是开发者。同一批改动里还有一件小事值得记:安装器锁的回归测试原本从冷启动的 PowerShell 里取时间,后来换成直接用 .NET 的 sleep,好让这条测试不再因为启动快慢而晃动;而 0.7.0 的验证记录写的是 267 个测试通过。
相关档案
全部档案 →第 070 号
OpenChatCut
一个本地优先的视频剪辑器,剪辑方式是跟它说话:内置 agent 与外部 Codex、Claude Code 会话调用的是界面自己在用的同一套剪辑工具,于是每一处改动都落在一条真实的多轨时间线上——是片段、转场、字幕、特效或音频,仍然能拖、能撤销、能导出。工程与素材留在本机,预览与最终渲染都出自 Remotion。
第 061 号
Reticle
一个 MCP 服务器加一个只在开发期生效的 SDK:让编码 agent 从应用内部去读、去操作一个正在运行的 web 或桌面应用,然后给出判词和该改的文件与行号,而不是一张截图。
第 085 号
OpenBot
CopilotKit 开源的一套 AI 同事平台:每个同事分到一台自己的电脑——一个装着 Chromium、一块工作区卷、一套自己的登录态的容器。同事可以是任何说 AG-UI 的端点;而它对浏览器、文件、MCP 或 shell 做的每一次动作,都要先经过同一个网关——按 CEL 策略裁决、写下一行审计、然后才真的执行,或者拒绝并说出是哪条规则拦下的。