Skip to content

随附的第一方 source

Plexus 随附一组第一方 capability source——网关一启动,agent 就有真实的东西可发现。本页逐一交代:capability id、所需授权、如何启用 / 配置前置条件,以及如实的只读 vs 可写暴露面。

这些 source:

Source访问前置条件
Obsidianobsidian-fsread磁盘上的一个 vault 文件夹
Obsidianobsidian-restread + writeObsidian Local REST API plugin
Apple CalendarreadmacOS + Calendar TCC
Apple Remindersread + writemacOS + Reminders TCC
Apple Notesread + 仅限创建的 writemacOS + Automation TCC
Apple Mail只读macOS + Automation TCC
Apple Contacts只读macOS + Automation TCC
Apple Photosread(export 向受限目录写出一个文件)macOS + Automation TCC
Shortcutsshortcutsread + execute(默认记录模式)macOS shortcuts CLI
Browserbrowser只读(Safari + Chrome)macOS(Safari 历史需要完全磁盘访问权限)
Browser controlbrowser-controlread + execute(驱动一个真实的 Chrome)Google Chrome;在你授权一个域名之前是惰性的
Workspaceworkspaceread + write磁盘上一个已授权的工作目录
Claude Codeclaudecodeexecute(受沙箱约束)PATH 上有 claude + macOS sandbox-exec
Codexcodexexecute(受沙箱约束)PATH 上有 codex CLI + macOS sandbox-exec

两种启用形态

Apple source(CalendarRemindersNotesMailContactsPhotos)、ShortcutsBrowserBrowser control,加上三个受沙箱约束的演示 / agent source(WorkspaceClaude CodeCodex)都是编译进网关的,自动注册,没有添加步骤。Obsidian 适配器则是受管 source,在运行时添加(CLI 或 /admin)。两类下面都会讲到。

安全姿态(对它们全都适用)

默认拒绝,且以你的授权为界:连接 agent 时,你为它勾选可触达的 capability 授权子集,子集之外的授权请求直接拒绝——绝不挂起。子集之内,连接时勾选的 read 成为常驻授权;勾选的带副作用的 capability(write / execute)保持逐次——每次调用都挂起等待人类批准(即 grant_pending_user 那套动作——见连接一个 agent),除非你在连接时为那一项 capability 显式 opt-in 常驻,或之后在批准它的请求时选一个真实的信任窗口。agent 永远无法给自己授予变更性调用。信任模型见项目 README看信任闭环


Obsidian

Obsidian vault 说到底就是一个装 .md 文件的文件夹。Plexus 提供两种暴露方式——按你是否需要写入来选。

obsidian-fs——直接、只读、路径受限

Capability id类别授权暴露面
obsidian.vault.readcapabilityread构造上只读
obsidian.vault.searchcapabilityread大小写不敏感的子串搜索,覆盖笔记路径 + 内容(默认 20 条命中,上限 100)
obsidian.vault.how-to-citeskill使用指引(当上下文读)

构造上只读——代码里根本没有写入或执行路径——并且路径受限../ 穿越、绝对路径、逃出 vault 的符号链接,一律拒绝,绝不读出。

**前置条件:**磁盘上有一个 vault 文件夹即可。不需要 Obsidian 应用,不需要 plugin,不需要密钥。

启用(受管 source——添加后持久化到 ~/.plexus/sources.json,热加载,无需重启)。在仓库根目录:

sh
# via the plexus CLI
bun run packages/cli/src/bin/plexus source add obsidian-fs --vault-path ~/Documents/MyVault

# or the launcher shortcut (persists the same managed source)
bun run start --vault ~/Documents/MyVault

也可以在 /adminWhat I expose 标签页添加。确认它已经上线:

sh
bun run packages/cli/src/bin/plexus source list
# → … obsidian-fs … enabled · live … capabilities:…

同一个 source 会出现在 /adminWhat I expose 树里;你为其授权过的 agent,在它自己的 list 里能看到 obsidian.vault.read

obsidian-rest——经由 Local REST API plugin 的读 + 写

Capability id类别授权暴露面
obsidian-rest.vault.listcapabilityread列出 vault 条目
obsidian-rest.vault.readcapabilityread读一条笔记
obsidian-rest.vault.searchcapabilityread全文搜索 vault(POST /search/simple/
obsidian-rest.vault.writecapabilitywrite创建/覆盖一条笔记——替换整条笔记 → 挂起
obsidian-rest.vault.appendcapabilitywrite追加到笔记末尾(不存在则创建) → 挂起
obsidian-rest.vault.how-to-useskill使用指引

**前置条件:**在同一台 Mac 的 Obsidian 应用里安装并运行 Obsidian Local REST API plugin。该 plugin 在回环上提供 HTTPS(默认 https://127.0.0.1:27124),用其设置里的 Bearer API key 认证。Plexus 接受它的自签名证书,仅仅因为主机解析到回环;transport 每次调用前都会重新核验回环。

启用(API key 只从 STDIN 读取——绝不走 argv,那会经 ps 泄漏——按名字存进 ~/.plexus/secrets/,绝不回显):

sh
printf %s "$OBSIDIAN_KEY" | bun run packages/cli/src/bin/plexus source add obsidian-rest \
    --base-url https://127.0.0.1:27124 --secret-name obsidian-local-rest-api-key --api-key-stdin

一条值得当真的写入警告:obsidian-rest.vault.write替换整条笔记PUT /vault/{path},请求体是完整的 markdown 全文)——先读出笔记,再把想保留的内容全部重发。做增量编辑——日志、跟进、随手记——优先用 obsidian-rest.vault.append:它追加到笔记末尾,保留已有内容(笔记不存在时会创建)。

两项 write(vault.write / vault.append)都带 write 授权,授予时会挂起等人——agent 收到 grant_pending_user,你在 Approvals 标签页批准。三项 read 你在连接时勾选即为常驻授权——调用直接过。(重新配置 source 的 --base-url 或密钥会清除它的授权——先前的批准带不到新端点上。)完整的 source 管理见 docs/sources/MANAGING-SOURCES.md


Apple Calendar——只读

Capability id类别授权暴露面
apple-calendar.calendars.listcapabilityread列出日历
apple-calendar.events.listcapabilityread列出某时间窗口内的事件
apple-calendar.how-to-useskill使用指引

构造上只读——provider 只暴露 listCalendars() / listEvents(),没有写入路径。自动注册(编译进来的第一方 source),没有添加步骤。

**前置条件(真实 macOS):**Calendar 应用,加一次性的 macOS TCC 授权。第一次实时调用会 shell 出 osascript -l JavaScript(JXA),触发 macOS 授权对话框——系统设置 ▸ 隐私与安全性 ▸ 自动化(以及日历)。拒绝之后,调用会失败并给出准确的"到系统设置里启用"提示;Plexus 无法替你再次弹窗——你要自己去系统设置重新授予。

封闭模式(无 macOS、无 TCC):PLEXUS_FAKE_APPLE=1,source 会解析到假 provider,带确定性的内存夹具(示例日历 Home / Work / Birthdays 和示例事件)。验收剧本和测试关卡就是这样跑的。

sh
PLEXUS_FAKE_APPLE=1 bun run start     # fake providers — no TCC, deterministic fixtures

Apple Reminders——读 + 写

Capability id类别授权暴露面
apple-reminders.lists.listcapabilityread列出提醒列表
apple-reminders.reminders.listcapabilityread列出提醒
apple-reminders.reminders.createcapabilitywrite创建一条提醒 → 挂起
apple-reminders.reminders.completecapabilitywrite把提醒标为完成 → 挂起
apple-reminders.skill.how-to-useskill使用指引

两项 write capability 会实实在在改动用户的 Reminders——它们的 describe 也是这么写的——都带 write 授权,因此都挂起等待批准。两项 read 你在连接时勾选即为常驻授权——调用直接过。自动注册(编译进来的第一方 source)。

**前置条件(真实 macOS):**Reminders 应用,加一次性 TCC 授权(系统设置 ▸ 隐私与安全性 ▸ 自动化 + 提醒事项)。真实 provider 用 osascript 执行 tell application "Reminders"(AppleScript);首次实时使用会弹授权。封闭模式:PLEXUS_FAKE_APPLE=1(种子列表 Reminders / Groceries;create/complete 改动内存存储)。


Apple Notes——读 + 仅限创建的写

Capability id类别授权暴露面
apple-notes.folders.listcapabilityread列出文件夹(按账户)
apple-notes.notes.searchcapabilityread有界的标题/正文搜索(默认 20 条命中,硬上限 50)
apple-notes.notes.readcapabilityread按 id 或精确标题读一条笔记(text + 原始 html
apple-notes.notes.createcapabilitywrite创建一条新笔记 → 挂起
apple-notes.skill.how-to-useskill使用指引

构造上仅限创建的写入面:唯一的写入就是创建一条笔记——没有 update、没有 delete、没有 move、没有 rename 条目,整个 source 里也根本不存在(provider seam 没有这类方法,bridge 没有这类 handler)。已有笔记无法经 Plexus 修改或删除。apple-notes.notes.create 仍带 write 授权,挂起等待批准;三项 read 你在连接时勾选即为常驻授权——调用直接过。搜索返回命中摘要(id、标题、文件夹、修改日期、短摘录——绝不返回全文);把命中的 id 传给 notes.read 拿实际内容。自动注册(编译进来的第一方 source)。

**前置条件(真实 macOS):**Notes 应用,加一次性 TCC 授权(系统设置 ▸ 隐私与安全性 ▸ 自动化)——provider 驱动 osascript/JXA。封闭模式:PLEXUS_FAKE_APPLE=1(确定性内存夹具;create 改动内存存储)。


Apple Mail——严格只读

Capability id类别授权暴露面
apple-mail.mailboxes.listcapabilityread账户 + 各邮箱及未读数
apple-mail.messages.searchcapabilityread在单个邮箱内的有界搜索(默认 20,硬上限 50)
apple-mail.message.readcapabilityread按 id 读一封邮件的纯文本(正文上限 20,000 字符)
apple-mail.how-to-useskill使用指引

构造上严格只读——每项 capability 都带 read,provider seam 没有起草/发送/移动/删除方法:起草或发送 capability 在这个 source 里根本不存在,而不是仅仅被拒绝。搜索一次只在一个邮箱内进行(默认 INBOX,即统一收件箱),按发件人/主题子串和/或收件日期范围过滤,结果最新在前,带约 200 字符的摘录和 truncated 标志;大邮箱上优先用日期范围或发件人过滤。自动注册(编译进来的第一方 source)。

**前置条件(真实 macOS):**Mail 应用,加一次性 TCC 授权(系统设置 ▸ 隐私与安全性 ▸ 自动化)。封闭模式:PLEXUS_FAKE_APPLE=1(确定性内存夹具)。


Apple Contacts——只读

Capability id类别授权暴露面
apple-contacts.contacts.searchcapabilityread有界的姓名/邮箱/电话子串搜索(默认 20,硬上限 50)
apple-contacts.contacts.readcapabilityread按联系人 id 读完整名片
apple-contacts.how-to-useskill使用指引

构造上只读——provider seam 没有 create/update/delete 方法;这个 source 里不存在任何写入 capability。搜索匹配姓名、邮箱地址或电话号码的大小写不敏感子串(电话匹配按数字比较——查询需要 ≥ 3 位数字才会匹配电话);contacts.read 返回完整名片(姓名、组织、生日,以及带标签的邮箱/电话/邮政地址)。自动注册(编译进来的第一方 source)。

**前置条件(真实 macOS):**Contacts 应用,加一次性 TCC 授权(系统设置 ▸ 隐私与安全性 ▸ 自动化)。封闭模式:PLEXUS_FAKE_APPLE=1(确定性内存夹具)。


Apple Photos——read 姿态、牢笼化导出

Capability id类别授权暴露面
apple-photos.albums.listcapabilityread相册 + 文件夹及条目数(每层最多 200)
apple-photos.searchcapabilityread仅元数据的媒体搜索(默认 20,最多 100)
apple-photos.exportcapabilityread把一个条目导出到 ~/.plexus/exports/photos/ 牢笼
apple-photos.how-to-useskill使用指引

三项都带 read——provider seam 没有任何改动照片库的方法apple-photos.search 仅搜元数据(相册、拍摄日期范围、文件名/关键词子串——没有内容/ML 搜索,找不到"狗的照片");对超过 5000 个条目的无范围搜索会被拒绝——用 album 限定。apple-photos.export 有一个如实声明的磁盘副作用:它恰好写出一个文件,且写进网关所有的牢笼目录 ~/.plexus/exports/photos/(缺失则创建;每次导出一个全新子目录)。它永远写不到磁盘上任何别处,也绝不改动照片库本身——所以它如实地保持 read 授权,副作用在其 describe 文本里逐字写明。自动注册(编译进来的第一方 source)。

**前置条件(真实 macOS):**Photos 应用,加一次性 TCC 授权(系统设置 ▸ 隐私与安全性 ▸ 自动化 ▸ 照片)。封闭模式:PLEXUS_FAKE_APPLE=1(确定性内存夹具)。

可注入 provider / TCC 的来龙去脉(全部 Apple source 都适用)

每个 source 通过一次 env 检查选择 provider——process.env.PLEXUS_FAKE_APPLE === "1" → 带夹具的 provider;否则是真实 macOS provider(驱动 osascript/JXA,首次使用受 macOS TCC 管控)。这个选择在单元测试里也可注入。所以 PLEXUS_FAKE_APPLE=1 就是封闭、免 TCC 运行的单一开关——bash run-tests.shtests/harnesses/acceptance-apple 剧本和 CI 用的都是它。(ShortcutsBrowser 以各自的开关沿用同一模式:PLEXUS_FAKE_SHORTCUTS=1PLEXUS_FAKE_BROWSER=1。)

osascript 的性能,实话实说

Apple provider 靠 osascript 驱动各自的应用,在超大存储上很慢——列出或搜索成百上千条要花好几秒。把查询限定到时间窗口、具体列表/邮箱或相册,别一次索要全部。


Shortcuts——read + execute(默认记录模式)

Capability id类别授权暴露面
shortcuts.listcapabilityread列出 shortcut 名称 + 文件夹名
shortcuts.runcapabilityexecute按名字运行一个 shortcut → 挂起;默认记录模式
shortcuts.how-to-useskill使用指引

shortcut 是用户自定义的自动化——拥有者把它造成什么样,它就能干什么(发消息、移文件、控制应用)——所以 shortcuts.run拥有者双重把关:它带 execute 授权,挂起等拥有者;即便调用获批,默认也处于记录模式——返回 launched: false,外加本来会执行的那条 shortcuts run 命令原文,已记录、已审计,但没有执行——直到拥有者在 Plexus 控制台为这个 source 启用真实启动What I expose ▸ Shortcuts ▸ Real launch)。shortcuts.list 是只读发现(绝不运行任何东西)——连接时勾选即为常驻授权,调用直接过;先 list 再 run——run原文接收 shortcut 名字。

**前置条件(真实 macOS):**macOS 的 shortcuts CLI(现代 macOS 自带)。自动注册(编译进来的第一方 source);CLI 是否在场经 health 如实上报,不靠隐藏条目。封闭模式:PLEXUS_FAKE_SHORTCUTS=1


Browser——只读(Safari + Chrome)

Capability id类别授权暴露面
browser.tabs.listcapabilityreadSafari + Chrome 当前打开的标签页
browser.bookmarks.searchcapabilityread按标题/URL 子串搜书签,有界(默认 20,硬上限 200)
browser.history.searchcapabilityread按子串 + 可选日期范围搜历史,最新在前,有界
browser.how-to-useskill使用指引

构造上只读——provider seam 任何地方都没有导航/打开/关闭/写入/删除方法;书签/历史的 sqlite 文件只会被拷贝到临时路径再读取(所以运行中的 Chrome 也不会挡住读取)。结果合并 Safari + Chrome,并按浏览器优雅降级:每个结果都带 browsers.safari / browsers.chrome 状态段;未安装、未运行或不可读的浏览器只贡献空列表加一条说明——绝不影响另一个浏览器的行。自动注册(编译进来的第一方 source)。

前置条件(真实 macOS):列出标签页需要对每个浏览器各一次的自动化 TCC 授权;Safari 历史(和书签)需要完全磁盘访问权限——没有它,Safari 这一半降级为 unavailable,Chrome 的结果照常返回。封闭模式:PLEXUS_FAKE_BROWSER=1(确定性内存夹具)。


Browser control——驱动一个真实的 Chrome(读 + execute

browser-control 与上面那个只读的 browser两个 source,这是刻意的:那一个是构造上只读——它的 provider seam 里根本不存在变更方法——把页面控制折进去,会让那条保证悄悄变成假话。

它直接说 Chrome DevTools Protocol。不需要 Puppeteer,不需要 Playwright,也不下载浏览器:CDP 就是 WebSocket 上的 JSON,运行时本来就两样都有。

真正定分量的那个决定:给哪个浏览器

三种模式的 capability 暴露面完全一样。不同的只是调试端点从哪来——而这决定了爆炸半径

模式agent 拿到的浏览器它能触达什么
launch(默认)Plexus 自己拉起的 Chrome,用自己的 profile一个干净的浏览器——没有 cookie,没有已登录会话
attach(所有者 opt-in)你正在用的 Chrome,经 chrome://inspect/#remote-debugging那个浏览器登录过的每一个会话
extension(所有者 opt-in)同样是你正在用的 Chrome,经 Plexus 扩展同上——但同意只在安装时给一次

launch 覆盖日常的「去把这页读了」,是安全默认值。另外两个够到的是你已登录的 web,因此是一个明确的所有者决定——和 exec source 上的 Real launch 一样。

Chrome 自己的同意是全有或全无的——它的权限对话框授权的是那个浏览器,不是一组站点。所以你真正想要的那条边界(「这个 agent 可以碰 GitHub,别的不行」)不可能来自 Chrome。它来自 Plexus。

Capability

Capability id类别授权暴露面
browser-control.tabs.listcapabilityread哪些标签页可被驱动——只列已授权域名的
browser-control.page.readcapabilityread页面的标题、url 与渲染后的文本
browser-control.page.elementscapabilityread可交互元素及可用的选择器;密码框只报长度
browser-control.page.screenshotcapabilityread视口截图,或用 fullPage 截整页
browser-control.page.scrollcapabilityread移动视口;回报 atBottom
browser-control.page.waitcapabilityread等一个选择器、一段字符串,或等加载结束
browser-control.frames.listcapabilityread内嵌 frame,按它自己的域名判定
browser-control.page.navigatecapabilityexecute跳转到某个 URL → 挂起——allowlist 的首要对象
browser-control.page.clickcapabilityexecute在选择器上走一遍真实指针序列 → 挂起
browser-control.page.typecapabilityexecute填一个字段或一个编辑器 → 挂起
browser-control.page.presscapabilityexecute一个真实按键事件 → 挂起(Enter 可以提交)
browser-control.page.uploadcapabilityexecute附加一个文件 → 挂起,只能来自你指定的上传目录
browser-control.page.evaluatecapabilityexecute以该页面的身份执行 JavaScript → 挂起
browser-control.page.cdpcapabilityexecute任意页面级 CDP 命令,原样透传 → 挂起
browser-control.how-to-useskill使用指引

页面暴露面是刻意开放的。在一个 agent 本来就被允许触碰的页面里,click + type 已经等同于完整的用户能动性——下单、发送、删除、改设置都做得到。在这之上再扣住 evaluate,挡不住任何真实伤害,只会让这项能力比所有者转而会去用的替代品更差。扣住的是 CDP 里属于浏览器全局的那一半——不属于任何页面的那部分——正是它让域名 allowlist 是真边界,而不是装饰。

scroll 和 wait 算 read,因为两者都不代表站点做事:它们改变的是可见范围、或我们看多久,提交不了、跟不进、也激活不了任何东西。

边界——域名 allowlist

每次调用都会解析出一个目标 URL,source 用设定的名单去校验这个 URL 的 origin——从真实目标在服务端解析出来,绝不采信 agent 自报的字段。三条规则让它成立:

  1. 空名单 = 拒绝,对那个有东西可失去的浏览器而言。面对你自己的浏览器(attach / extension),没设就是惰性的,不是开放的。面对 Plexus 在空 profile 上拉起的浏览器,没有会话可隔离,所以没设就意味着开放 web——给一个「谁也不是」的浏览器砌墙,什么都保护不了。http/https 的 scheme 规则两种情况都适用,所以「整个 web」永远不包括本地磁盘或 Chrome 自己的设置页。
  2. 一条条目授权它那个域名,含子域。deepseek.com 覆盖 www.deepseek.com。匹配发生在解析出的 host 上、且按点边界,所以 deepseek.com.evil.comevildeepseek.com 都在界外;IP 条目精确匹配;scheme 必须相同,所以授权一个站点绝不隐含授权它的明文形式。
  3. **每次动作之前,重新校验该标签页的当前 origin。**一个在 github.com 上时被放行的标签页,导航到 mail.google.com 之后就不再被放行——复用已持有调试 socket 的调用同样如此。复用是传输层的优化,它从不把判定结果带到下一次。

跨站 <iframe> 跑在自己的渲染进程里,判定方式与标签页完全一致:按它自己的域名。一个被授权的页面并不授权它内嵌的东西——正是这条,挡住了一个你放行的页面把已登录的 accounts.google.com frame 一起带进射程。

它与按 agent 的 scope 机制是叠加而非替代:source 级 allowlist 是地板,授权约束只能从中做减法。

上传是一条外泄通道

page.upload 把你机器上的一个文件递给一个网站。那个牢笼不是围着这项功能的便利设施,它就是这项功能本身:路径相对于你指定的一个目录,用与文件类 source 相同的「词法 + realpath」双重校验封住,且没设就拒绝一切上传——与空 allowlist 同样的 fail-closed 默认。审计记录完整路径与大小;线上只给文件名。

怎么配

在控制台的 What I expose → Browser control 下,三项设置:

  • 模式——launch / attach / extension
  • 已授权域名——一行一个。对一个你已登录的浏览器,空名单拒绝一切。
  • 上传目录——没设就拒绝一切上传。

改动即时生效,不必重启。启动时的兜底是 PLEXUS_BROWSER_CONTROL_MODEPLEXUS_BROWSER_CONTROL_ORIGINS(逗号分隔)与 PLEXUS_BROWSER_CONTROL_UPLOAD_DIR;控制台里保存过的设置优先于环境变量。

attachchrome://inspect/#remote-debugging 处一次性打开远程调试(Chrome 144+)。这不是图方便——自 Chrome 136 起,二进制在默认 profile 上拒绝 --remote-debugging-port,所以那个开关是进入你真正登录着的那个浏览器的唯一路径。之后 Chrome 会逐连接询问权限,并挂出它那条「正受自动化测试软件控制」的横幅。

**用 extension:**先注册一次本地消息宿主,再加载扩展:

sh
bun run packages/runtime/src/sources/browser-control/install-native-host.ts

然后 chrome://extensions开发者模式加载已解压的扩展程序 → 选 extension/plexus-browser。有网关连上时,徽标是绿色。

这个扩展只是一条传输通道——它不持有 allowlist,也没有任何批准逻辑。本地消息宿主由 Chrome 自己拉起,而且它只会拉起「清单里写明了这个扩展 id」的那一个,所以绑定由 Chrome 强制,你不需要在两个窗口之间复制任何配对 token。它相对开关那条路的好处是:同意只在安装时给一次,而不是每次连接都给。

前置条件:Google Chrome。自动注册(编译进来的第一方 source),且在你授权一个域名之前是惰性的;Chrome 是否在场经 health 如实上报,不靠隐藏条目。Plexus 拿走什么就放回什么——它持有的调试 socket 和它开的标签页会在关停时关掉,所以 agent 的浏览不会在你的 Chrome 里越堆越多窗口。


Workspace——沙箱化工作目录(读 + 写

workspace 把磁盘上一个已授权的工作目录暴露为路径受限的文件系统——也就是演示流程里 agent 的草稿 / 产出文件夹。它是下面两个沙箱化 runner 的配套读写面:agent 在这里 list/read 文件,让 Claude Code 或 Codex 在同一个牢笼里构建,再把产物读回来。

Capability id类别授权暴露面
workspace.listcapabilityread列出目录(只读)
workspace.readcapabilityread读文件(只读)
workspace.writecapabilitywrite创建/覆盖文件 → 挂起
workspace.how-to-useskill使用指引

和 Obsidian 的 vault 读取器一样路径受限:所有路径都在 workspace 根之下解析,逃逸(..、绝对路径、向外的符号链接)一律拒绝。两项 read(list/read)你在连接时勾选即为常驻授权——调用直接过;workspace.write 在第一方 source 上带 write 授权,因此挂起等拥有者自动注册(编译进来的第一方 source);可用性(已授权目录是否存在)经 health 报告,绝不靠隐藏条目。


Claude Code——无头、受沙箱约束execute

claudecode 把 Claude Code CLI 暴露为一项敏感 capability:启动无头 Claude Code 做真实编码工作,由 macOS sandbox-exec 约束在已授权目录内。agent 看不到 shell,也看不到启动命令——只有 { prompt }。牢笼之外的读写在内核处失败

Capability id类别授权暴露面
claudecode.runcapabilityexecute在牢笼里启动无头 Claude Code → 挂起
claudecode.how-to-useskill使用指引

claudecode.run 是第一方 source 上的 execute,属于敏感度升级,挂起等拥有者——发出调用后等待批准。两次调用之间用 workspace.read 验证产物。自动注册(编译进来的第一方 source);claude + sandbox-exec 是否在场经 health 如实上报,不靠隐藏条目。


Codex——无头、受沙箱约束execute

codexclaudecode 的镜像:无头运行本地 Codex CLI(codex exec)做真实编码工作,由 macOS sandbox-exec 约束在已授权目录内。姿态相同——只有 { prompt }(外加可选的、牢笼内的 cwd);牢笼之外的读写在内核处失败

Capability id类别授权暴露面
codex.runcapabilityexecute在牢笼里启动无头 codex exec → 挂起
codex.how-to-useskill使用指引

codex.run 是第一方 source 上的 execute,因此挂起等拥有者——发出调用后等待。本地 codex CLI 缺席时,调用返回 source_unavailable,不会让会话失败。自动注册(编译进来的第一方 source);codex + sandbox-exec 是否在场经 health 如实上报。


接下来去哪