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
Things 3read + write已安装 Things 3
cc-masterexecute / write / readPATH 上有 Claude Code(claude
Workspaceworkspaceread + write磁盘上一个已授权的工作目录
Claude Codeclaudecodeexecute(受沙箱约束)PATH 上有 claude + macOS sandbox-exec
Codexcodexexecute(受沙箱约束)PATH 上有 codex CLI + macOS sandbox-exec

两种启用形态

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

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

默认拒绝:agent 在请求授权之前没有任何调用权限。第一方 source 的 read 自动批准;write 属于敏感度升级,挂起等待人类批准(即 grant_pending_user 那套动作——见连接一个 agent)。agent 永远无法给自己授予变更性调用。信任模型见项目 README快速上手


Obsidian

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

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

Capability id类别授权暴露面
obsidian.vault.readcapabilityread构造上只读
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

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

sh
curl -s -H "Host: 127.0.0.1:7077" http://127.0.0.1:7077/.well-known/plexus | bun -e \
  'const d = await Bun.stdin.json(); console.log(d.capabilities.map(c => c.id).join("\n"))'
# → … obsidian.vault.read …

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

Capability id类别授权暴露面
obsidian-rest.vault.listcapabilityread列出 vault 条目
obsidian-rest.vault.readcapabilityread读一条笔记
obsidian-rest.vault.writecapabilitywrite创建/覆盖一条笔记 → 挂起
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.writewrite 授权,授予时会挂起等人——agent 收到 grant_pending_user,你在 Pending 标签页批准。两项 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 改动内存存储)。


Things 3——读 + 写

Capability id类别授权暴露面
things.todos.listcapabilityread列出待办(AppleScript)
things.projects.listcapabilityread列出项目(AppleScript)
things.todos.addcapabilitywrite追加一条待办 → 挂起
things.how-to-useskill使用指引

值得留意的暴露面差异:read 走 AppleScript 词典(tell application "Things3"),写入(things.todos.add)走 Things URL-schemethings:///add?title=…&notes=…&when=…&list=…)。这让写入成为边界清晰的追加——不是任意变更——但它仍带 write 授权,仍挂起等待批准自动注册(编译进来的第一方 source)。

**前置条件(真实 macOS):**已安装 Things 3(通过一次 osascript 版本探测检测)。写入用 open 二进制打开 things:// URL。封闭模式:PLEXUS_FAKE_APPLE=1(种子待办 + 项目;add 改动内存存储)。

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

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

osascript 的性能,实话实说

Apple provider 靠 osascript 驱动 Calendar / Reminders,在超大存储上很慢——列出成百上千条要花好几秒。把查询限定到时间窗口或具体列表,别一次索要全部。


cc-master——Claude Code 编排

cc-master 是 Claude Code 长时程编排 plugin 的受管 launcher。它无头地 spawn claude --plugin-dir <embedded cc-master> -p …从不改动你的 ~/.claude——plugin 经 --plugin-dir 注入,自动加载进受管会话。

Capability id类别授权备注
cc-master.session.launchcapabilityexecute启动一个无头 Claude Code 会话(始终暴露)
cc-master.orchestration.runworkflowexecute旗舰编排 workflow
cc-master.board.createcapabilitywrite创建编排 board
cc-master.agent.dispatchcapabilityexecute派发受管的子 agent
cc-master.board.statuscapabilityread读 board 状态
cc-master.skill.orchestrating-to-completionskill使用指引
cc-master.skill.authoring-workflowsskill使用指引
cc-master.skill.as-master-orchestratorskill使用指引
cc-master.skill.statusskill使用指引

所有 execute / write capability 都挂起等待批准(每项 capability 都默认拒绝);board.status 是 read。除 session.launch 之外的编排暴露面由一个配置 flag 门控(见下)——flag 关闭时,只暴露 cc-master.session.launch

前置条件:PATH 上有 claude 二进制,且 plugin 装在 ~/.claude/ 之下。两者齐备时,Plexus 会自动检测 cc-master 并浮现这些 capability。

启用 / 配置:

  • cc-master 尚未启用时,用 /admin 里的 Install cc-master 动作。它做一次幂等、有审计的正规安装——只添加启用 plugin + 注册其 marketplace 所需的那两个设置键,绝不重写无关设置。已启用时是安全的空操作。
  • 暴露门控持久化在 ~/.plexus/cc-master.json,形如 { "loadCcMaster": <bool> }(默认 true);/admin 的 cc-master 配置负责切换(GET/POST /admin/api/cc-master/config)。

在 discovery 里确认检测结果:

sh
curl -s -H "Host: 127.0.0.1:7077" http://127.0.0.1:7077/.well-known/plexus | bun -e \
  'const d = await Bun.stdin.json();
   console.log(d.capabilities.filter(c => c.id.startsWith("cc-master")).map(c => c.id).join("\n"))'

出于安全,launch 受门控

裸的 bun run start(以及整个测试关卡)以仅记录模式运行 cc-master——cc-master.agent.dispatch 会在真实的 board 上记录这次派发,返回它本会运行的 argv,但不 spawn claude。随附的桌面应用把门控拨到PLEXUS_CC_HEADLESS_LAUNCH=1),launch 才真实执行;手动设置这个 env var,裸运行也能真实 launch。见 tests/harnesses/acceptance/README.md


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 浮现。


接下来去哪