agent-trellis 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/README.md +43 -207
  2. package/dist/adapters/zcode.d.ts +21 -0
  3. package/dist/adapters/zcode.js +234 -0
  4. package/dist/cli.js +25 -9
  5. package/dist/commands/doctor.js +2 -0
  6. package/dist/commands/init.d.ts +1 -1
  7. package/dist/commands/init.js +4 -1
  8. package/dist/commands/mcp.d.ts +56 -14
  9. package/dist/commands/mcp.js +105 -28
  10. package/dist/commands/mcpGateway.js +2 -1
  11. package/dist/commands/mcpImport.d.ts +21 -2
  12. package/dist/commands/mcpImport.js +30 -7
  13. package/dist/commands/memory.d.ts +13 -1
  14. package/dist/commands/memory.js +15 -0
  15. package/dist/commands/migrate.js +4 -1
  16. package/dist/commands/onboard.js +15 -4
  17. package/dist/commands/rollback.js +24 -1
  18. package/dist/commands/secretsAudit.js +4 -1
  19. package/dist/commands/skill.d.ts +35 -6
  20. package/dist/commands/skill.js +67 -13
  21. package/dist/commands/sync.js +3 -1
  22. package/dist/core/adapter.d.ts +11 -1
  23. package/dist/core/types.d.ts +1 -1
  24. package/dist/core/types.js +1 -0
  25. package/dist/lib/agentBridge.d.ts +169 -0
  26. package/dist/lib/agentBridge.js +367 -0
  27. package/dist/lib/agentBridgeProvider.d.ts +14 -0
  28. package/dist/lib/agentBridgeProvider.js +95 -0
  29. package/dist/lib/backup.d.ts +30 -0
  30. package/dist/lib/backup.js +16 -1
  31. package/dist/lib/chatAgents.d.ts +42 -0
  32. package/dist/lib/chatAgents.js +59 -0
  33. package/dist/lib/envVarNames.d.ts +3 -0
  34. package/dist/lib/envVarNames.js +19 -0
  35. package/dist/lib/installAgent.d.ts +1 -1
  36. package/dist/lib/installAgent.js +1 -1
  37. package/dist/lib/mcpMigrateRead.d.ts +1 -0
  38. package/dist/lib/mcpMigrateRead.js +19 -1
  39. package/dist/lib/realHomeSnapshot.js +5 -0
  40. package/dist/lib/runtimeControlProvider.js +2 -0
  41. package/dist/lib/taskStore.js +1 -1
  42. package/dist/lib/terminalPicker.js +33 -6
  43. package/dist/lib/zcodeOwnership.d.ts +17 -0
  44. package/dist/lib/zcodeOwnership.js +37 -0
  45. package/dist/pi-bridge/bundle.js +2 -1
  46. package/dist/probes/codex.d.ts +7 -0
  47. package/dist/probes/codex.js +37 -5
  48. package/dist/probes/zcode.d.ts +32 -0
  49. package/dist/probes/zcode.js +140 -0
  50. package/docs/architecture.md +9 -5
  51. package/docs/assets/brand-v3/trellis-mark-v3-a.png +0 -0
  52. package/docs/assets/brand-v3/trellis-mark-v3-a.svg +10 -0
  53. package/docs/assets/poster-series-v3/README.md +60 -0
  54. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-en.png +0 -0
  55. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-en.svg +51 -0
  56. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-zh.png +0 -0
  57. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-zh.svg +51 -0
  58. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-en.png +0 -0
  59. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-en.svg +48 -0
  60. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-zh.png +0 -0
  61. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-zh.svg +48 -0
  62. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-en.png +0 -0
  63. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-en.svg +56 -0
  64. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-zh.png +0 -0
  65. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-zh.svg +56 -0
  66. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-en.png +0 -0
  67. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-en.svg +47 -0
  68. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-zh.png +0 -0
  69. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-zh.svg +47 -0
  70. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-en.png +0 -0
  71. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-en.svg +51 -0
  72. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-zh.png +0 -0
  73. package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-zh.svg +51 -0
  74. package/docs/getting-started.md +173 -12
  75. package/docs/overview.md +6 -3
  76. package/docs/overview.zh-CN.md +5 -3
  77. package/docs/roadmap.md +2 -1
  78. package/docs/video/README.md +76 -0
  79. package/docs/video/build/audio/01-opening.aiff +0 -0
  80. package/docs/video/build/audio/01-opening.mp3 +0 -0
  81. package/docs/video/build/audio/02-pain.aiff +0 -0
  82. package/docs/video/build/audio/02-pain.mp3 +0 -0
  83. package/docs/video/build/audio/03-solution.aiff +0 -0
  84. package/docs/video/build/audio/03-solution.mp3 +0 -0
  85. package/docs/video/build/audio/04-install.aiff +0 -0
  86. package/docs/video/build/audio/04-install.mp3 +0 -0
  87. package/docs/video/build/audio/04-setup.mp3 +0 -0
  88. package/docs/video/build/audio/05-dryrun.mp3 +0 -0
  89. package/docs/video/build/audio/05-init.aiff +0 -0
  90. package/docs/video/build/audio/05-init.mp3 +0 -0
  91. package/docs/video/build/audio/05-interactive.mp3 +0 -0
  92. package/docs/video/build/audio/06-dryrun.aiff +0 -0
  93. package/docs/video/build/audio/06-dryrun.mp3 +0 -0
  94. package/docs/video/build/audio/06-onboard.mp3 +0 -0
  95. package/docs/video/build/audio/06-run.mp3 +0 -0
  96. package/docs/video/build/audio/07-onboard.aiff +0 -0
  97. package/docs/video/build/audio/07-onboard.mp3 +0 -0
  98. package/docs/video/build/audio/07-verify.mp3 +0 -0
  99. package/docs/video/build/audio/08-closing.mp3 +0 -0
  100. package/docs/video/build/audio/08-doctor.aiff +0 -0
  101. package/docs/video/build/audio/08-doctor.mp3 +0 -0
  102. package/docs/video/build/audio/09-rollback.aiff +0 -0
  103. package/docs/video/build/audio/09-rollback.mp3 +0 -0
  104. package/docs/video/build/audio/10-principles.aiff +0 -0
  105. package/docs/video/build/audio/10-principles.mp3 +0 -0
  106. package/docs/video/build/audio/11-closing.aiff +0 -0
  107. package/docs/video/build/audio/11-closing.mp3 +0 -0
  108. package/docs/video/build/frames/01-opening-0.png +0 -0
  109. package/docs/video/build/frames/02-pain-1.png +0 -0
  110. package/docs/video/build/frames/02-pain-2.png +0 -0
  111. package/docs/video/build/frames/03-solution-3.png +0 -0
  112. package/docs/video/build/frames/04-install-4.png +0 -0
  113. package/docs/video/build/frames/04-setup-4.png +0 -0
  114. package/docs/video/build/frames/04-setup-5.png +0 -0
  115. package/docs/video/build/frames/05-dryrun-6.png +0 -0
  116. package/docs/video/build/frames/05-init-5.png +0 -0
  117. package/docs/video/build/frames/05-interactive-5.png +0 -0
  118. package/docs/video/build/frames/05-interactive-6.png +0 -0
  119. package/docs/video/build/frames/06-dryrun-6.png +0 -0
  120. package/docs/video/build/frames/06-dryrun-7.png +0 -0
  121. package/docs/video/build/frames/06-onboard-7.png +0 -0
  122. package/docs/video/build/frames/06-onboard-8.png +0 -0
  123. package/docs/video/build/frames/06-run-7.png +0 -0
  124. package/docs/video/build/frames/06-run-8.png +0 -0
  125. package/docs/video/build/frames/07-onboard-10.png +0 -0
  126. package/docs/video/build/frames/07-onboard-7.png +0 -0
  127. package/docs/video/build/frames/07-onboard-8.png +0 -0
  128. package/docs/video/build/frames/07-onboard-9.png +0 -0
  129. package/docs/video/build/frames/07-verify-10.png +0 -0
  130. package/docs/video/build/frames/07-verify-8.png +0 -0
  131. package/docs/video/build/frames/07-verify-9.png +0 -0
  132. package/docs/video/build/frames/08-closing-10.png +0 -0
  133. package/docs/video/build/frames/08-closing-11.png +0 -0
  134. package/docs/video/build/frames/08-doctor-11.png +0 -0
  135. package/docs/video/build/frames/08-doctor-9.png +0 -0
  136. package/docs/video/build/frames/09-rollback-10.png +0 -0
  137. package/docs/video/build/frames/09-rollback-12.png +0 -0
  138. package/docs/video/build/frames/10-principles-11.png +0 -0
  139. package/docs/video/build/frames/10-principles-13.png +0 -0
  140. package/docs/video/build/frames/11-closing-12.png +0 -0
  141. package/docs/video/build/frames/11-closing-14.png +0 -0
  142. package/docs/video/build/segments/01-opening.mp4 +0 -0
  143. package/docs/video/build/segments/01-opening.txt +3 -0
  144. package/docs/video/build/segments/02-pain.mp4 +0 -0
  145. package/docs/video/build/segments/02-pain.txt +5 -0
  146. package/docs/video/build/segments/03-solution.mp4 +0 -0
  147. package/docs/video/build/segments/03-solution.txt +3 -0
  148. package/docs/video/build/segments/04-install.mp4 +0 -0
  149. package/docs/video/build/segments/04-install.txt +3 -0
  150. package/docs/video/build/segments/04-setup.mp4 +0 -0
  151. package/docs/video/build/segments/04-setup.txt +3 -0
  152. package/docs/video/build/segments/05-dryrun.mp4 +0 -0
  153. package/docs/video/build/segments/05-dryrun.txt +3 -0
  154. package/docs/video/build/segments/05-init.mp4 +0 -0
  155. package/docs/video/build/segments/05-init.txt +3 -0
  156. package/docs/video/build/segments/05-interactive.mp4 +0 -0
  157. package/docs/video/build/segments/05-interactive.txt +5 -0
  158. package/docs/video/build/segments/06-dryrun.mp4 +0 -0
  159. package/docs/video/build/segments/06-dryrun.txt +3 -0
  160. package/docs/video/build/segments/06-onboard.mp4 +0 -0
  161. package/docs/video/build/segments/06-onboard.txt +5 -0
  162. package/docs/video/build/segments/06-run.mp4 +0 -0
  163. package/docs/video/build/segments/06-run.txt +3 -0
  164. package/docs/video/build/segments/07-onboard.mp4 +0 -0
  165. package/docs/video/build/segments/07-onboard.txt +5 -0
  166. package/docs/video/build/segments/07-verify.mp4 +0 -0
  167. package/docs/video/build/segments/07-verify.txt +5 -0
  168. package/docs/video/build/segments/08-closing.mp4 +0 -0
  169. package/docs/video/build/segments/08-closing.txt +3 -0
  170. package/docs/video/build/segments/08-doctor.mp4 +0 -0
  171. package/docs/video/build/segments/08-doctor.txt +3 -0
  172. package/docs/video/build/segments/09-rollback.mp4 +0 -0
  173. package/docs/video/build/segments/09-rollback.txt +3 -0
  174. package/docs/video/build/segments/10-principles.mp4 +0 -0
  175. package/docs/video/build/segments/10-principles.txt +3 -0
  176. package/docs/video/build/segments/11-closing.mp4 +0 -0
  177. package/docs/video/build/segments/11-closing.txt +3 -0
  178. package/docs/video/build/segments/final.txt +8 -0
  179. package/docs/video/build-ai/audio/01-hook.mp3 +0 -0
  180. package/docs/video/build-ai/audio/02-pain.mp3 +0 -0
  181. package/docs/video/build-ai/audio/03-solution.mp3 +0 -0
  182. package/docs/video/build-ai/audio/04-how.mp3 +0 -0
  183. package/docs/video/build-ai/audio/05-safe.mp3 +0 -0
  184. package/docs/video/build-ai/audio/06-closing.mp3 +0 -0
  185. package/docs/video/build-ai/clips/01-hook.mp4 +0 -0
  186. package/docs/video/build-ai/clips/02-pain.mp4 +0 -0
  187. package/docs/video/build-ai/clips/03-solution.mp4 +0 -0
  188. package/docs/video/build-ai/clips/04-how.mp4 +0 -0
  189. package/docs/video/build-ai/clips/05-safe.mp4 +0 -0
  190. package/docs/video/build-ai/clips/06-closing.mp4 +0 -0
  191. package/docs/video/build-ai/first-frame-02-pain.png +0 -0
  192. package/docs/video/build-ai/first-frame-03-solution.png +0 -0
  193. package/docs/video/build-ai/first-frame-04-how.png +0 -0
  194. package/docs/video/build-ai/first-frame-05-safe.png +0 -0
  195. package/docs/video/build-ai/segments/01-hook.caption.txt +2 -0
  196. package/docs/video/build-ai/segments/01-hook.mp4 +0 -0
  197. package/docs/video/build-ai/segments/02-pain.mp4 +0 -0
  198. package/docs/video/build-ai/segments/03-solution.mp4 +0 -0
  199. package/docs/video/build-ai/segments/04-how.mp4 +0 -0
  200. package/docs/video/build-ai/segments/05-safe.mp4 +0 -0
  201. package/docs/video/build-ai/segments/06-closing.mp4 +0 -0
  202. package/docs/video/build-ai/segments/cap-01-hook.png +0 -0
  203. package/docs/video/build-ai/segments/cap-02-pain.png +0 -0
  204. package/docs/video/build-ai/segments/cap-03-solution.png +0 -0
  205. package/docs/video/build-ai/segments/cap-04-how.png +0 -0
  206. package/docs/video/build-ai/segments/cap-05-safe.png +0 -0
  207. package/docs/video/build-ai/segments/cap-06-closing.png +0 -0
  208. package/docs/video/build-ai/segments/final.txt +6 -0
  209. package/docs/video/build-posters/audio/01-hook.mp3 +0 -0
  210. package/docs/video/build-posters/audio/02-pain.mp3 +0 -0
  211. package/docs/video/build-posters/audio/03-solution.mp3 +0 -0
  212. package/docs/video/build-posters/audio/04-how.mp3 +0 -0
  213. package/docs/video/build-posters/audio/05-safe.mp3 +0 -0
  214. package/docs/video/build-posters/audio/06-closing.mp3 +0 -0
  215. package/docs/video/build-posters/cap-01-hook.png +0 -0
  216. package/docs/video/build-posters/cap-02-pain.png +0 -0
  217. package/docs/video/build-posters/cap-03-solution.png +0 -0
  218. package/docs/video/build-posters/cap-04-how.png +0 -0
  219. package/docs/video/build-posters/cap-05-safe.png +0 -0
  220. package/docs/video/build-posters/cap-06-closing.png +0 -0
  221. package/docs/video/build-posters/card-01-hook.png +0 -0
  222. package/docs/video/build-posters/card-06-closing.png +0 -0
  223. package/docs/video/build-posters/segments/01-hook.mp4 +0 -0
  224. package/docs/video/build-posters/segments/02-pain.mp4 +0 -0
  225. package/docs/video/build-posters/segments/03-solution.mp4 +0 -0
  226. package/docs/video/build-posters/segments/04-how.mp4 +0 -0
  227. package/docs/video/build-posters/segments/05-safe.mp4 +0 -0
  228. package/docs/video/build-posters/segments/06-closing.mp4 +0 -0
  229. package/docs/video/build-posters/segments/final.txt +6 -0
  230. package/docs/video/generate-video-ai.mjs +334 -0
  231. package/docs/video/generate-video-posters.mjs +204 -0
  232. package/docs/video/generate-video.mjs +426 -0
  233. package/docs/video/outline.zh-CN.md +102 -0
  234. package/docs/video/trellis-demo-video-ai.mp4 +0 -0
  235. package/docs/video/trellis-demo-video.mp4 +0 -0
  236. package/docs/video/voiceover.zh-CN.md +49 -0
  237. package/package.json +5 -2
  238. package/schema/servers.example.yaml +1 -1
  239. package/docs/assets/agent-trellis-architecture-horizontal.svg +0 -80
  240. package/docs/assets/agent-trellis-architecture-vertical.svg +0 -82
  241. package/docs/assets/trellis-mark.svg +0 -12
package/README.md CHANGED
@@ -1,237 +1,73 @@
1
1
  # Trellis
2
2
 
3
3
  <p align="center">
4
- <img src="docs/assets/trellis-mark.svg" width="88" alt="Trellis logo" />
4
+ <img src="docs/assets/brand-v3/trellis-mark-v3-a.svg" width="88" alt="Trellis logo" />
5
5
  </p>
6
6
 
7
7
  <p align="center"><strong>Unified Code Agent Runtime</strong></p>
8
8
 
9
- Trellis gives Claude Code, Codex, Kiro, pi, and Kimi Code one Runtime for
10
- Skills, MCP, Memory, and shared instructions.
9
+ One canonical source for Skills, MCP, Memory, and shared instructions —
10
+ projected safely into Claude Code, Codex, Kiro, pi, Kimi Code, and ZCode.
11
11
 
12
- > 中文:Trellis 是统一的 Code Agent Runtime,为多个 Code Agent 提供一致的
13
- > Skill、MCP、Memory 与共享指令能力。
12
+ > 中文:一个 canonical source 统一管理多个 Code Agent 的 Skill、MCP、Memory
13
+ > 与共享指令,支持预览、备份与回滚。
14
14
 
15
- Trellis does not replace an Agent's native runtime. It manages one canonical
16
- source and generates verified native or Runtime projections from it.
15
+ ![Agent Trellis — One Runtime. Every Code Agent.](docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-en.png)
17
16
 
18
- [Read the product overview →](docs/overview.md)
19
-
20
- ![Agent Trellis architecture](docs/assets/agent-trellis-architecture-horizontal.svg)
21
-
22
- ## Install
17
+ ## Quick start
23
18
 
24
19
  ```bash
25
20
  npm install -g agent-trellis
26
- ```
27
-
28
- ## Quick start
29
21
 
30
- ```bash
31
- trellis onboard --dry-run
32
- trellis onboard
33
- trellis doctor
22
+ trellis onboard --dry-run # preview: migration source, managed agents, MCP, memory
23
+ trellis onboard # apply — every write is backed up automatically
24
+ trellis doctor # verify state, any time
34
25
  ```
35
26
 
36
- Use the dry-run to review migration source, managed Agents, MCP mode, and
37
- Memory before applying. See [`docs/overview.md`](docs/overview.md) for the
38
- short product explanation and [`docs/getting-started.md`](docs/getting-started.md)
39
- for the complete workflow.
40
-
41
- ## Why
42
-
43
- By late 2026 the "sync my AI agent rules across tools" space is crowded — at
44
- least seven open source projects do it (`block/ai-rules`, `ai-rules-sync`,
45
- `skillshare`, `skills-hub`, `skills-link`, `agent_sync`, and others). None of
46
- them cover **Kiro** or **pi**, and none of them go past rules/skills into MCP
47
- servers, shared memory, and secret hygiene as one coherent system. That's the
48
- gap Trellis fills — see [`docs/research.md`](docs/research.md) for the full
49
- landscape survey and [`docs/architecture.md`](docs/architecture.md) for what we
50
- build versus what we deliberately reuse.
51
-
52
- Trellis aligns with the emerging [`.agents Protocol`](https://dotagentsprotocol.com)
53
- draft rather than inventing a sixth competing standard, and is likely its first
54
- working implementation.
27
+ Something went wrong? `trellis rollback` inverts the last run.
55
28
 
56
- See [`docs/getting-started.md`](docs/getting-started.md) for the detailed
57
- walkthrough — example output for each command, what each `migrate`/`sync`
58
- conflict action means, and troubleshooting.
29
+ ## How it compares
59
30
 
60
- **One command:**
31
+ | | Skills / Rules | MCP | Memory | Secret hygiene | Agents covered |
32
+ |---|---|---|---|---|---|
33
+ | [ai-rules](https://github.com/block/ai-rules), [skills-link](https://github.com/shanliuling/skills-link), [agent_sync](https://github.com/yelmuratoff/agent_sync) | ✅ | ❌ | ❌ | ❌ | Many — but not Kiro or pi |
34
+ | [skillshare](https://github.com/runkids/skillshare), [skills-hub](https://github.com/qufei1993/skills-hub) | ✅ skills only | ❌ | ❌ | ❌ | Codex, Claude, … |
35
+ | [mcp-router](https://github.com/mcp-router/mcp-router) | ❌ | ✅ desktop router | ❌ | config in its own dashboard | — |
36
+ | [MetaMCP](https://github.com/metatool-ai/metamcp), [mcp-hub](https://github.com/ravitemer/mcp-hub) | ❌ | ✅ aggregator | ❌ | ❌ | — |
37
+ | [cli-agent-orchestrator](https://github.com/awslabs/cli-agent-orchestrator) | ❌ | ❌ | ❌ | ❌ | Runs agent fleets, doesn't unify config |
38
+ | **Trellis** | ✅ | ✅ native config, Runtime, or hub mode | ✅ shared memory + handoffs | ✅ references only, `secrets audit` | Claude Code, Codex, Kiro, pi, Kimi Code, ZCode |
61
39
 
62
- ```
63
- trellis onboard
64
- ```
40
+ Sync tools stop at rules and skills. MCP routers manage servers but hold their
41
+ own config — a second source of truth (we hit real token drift with exactly
42
+ that setup). Trellis is the only one treating Skills + MCP + Memory +
43
+ instructions as **one** canonical system, and the only one covering Kiro and
44
+ pi. Full landscape survey: [`docs/research.md`](docs/research.md).
65
45
 
66
- Creates canonical source, detects which of Claude Code/Codex/Kiro/pi/Kimi Code are on
67
- this machine, then resolves two independent choices: a **migration source**
68
- (read from — auto-selected if only one present agent has real content,
69
- prompted with a numbered choice if more than one, skippable if starting
70
- fresh; pass `--agent <id>` to skip the prompt) and a **managed set** (written
71
- to — zero or more agents, chosen explicitly; pass `--manage <ids>` or
72
- `--manage none` to skip the prompt). The source is **not** managed by
73
- default — importing from Claude Code doesn't mean Trellis starts writing to
74
- Claude Code too, unless you explicitly include it. Selecting an agent that
75
- isn't installed yet (e.g. pi) is itself the authorization to install it —
76
- one confirmation, then a real `npm install -g <package>`; Kiro has no CLI
77
- package and is refused with its download URL instead. Once resolved, it
78
- runs `migrate`, `sync`, `mcp sync`, and `secrets audit` against the managed
79
- set — the whole onboarding path in one command, no follow-up commands to
80
- type by hand. If no agent is detected, it prints each supported agent's
81
- real install command/URL and stops — it never installs anything on its own
82
- initiative. Add `--dry-run` to preview the whole thing with zero writes.
83
-
84
- Onboarding only adds to the existing managed set. To deliberately narrow or
85
- replace Trellis's future write boundary without touching an agent's current
86
- native state, use `trellis manage list|set|add|remove`; these mutations are
87
- dry-runnable and backed by `trellis rollback`.
46
+ ## Design principles
88
47
 
89
- ```
90
- trellis onboard --agent claude-code --manage pi
91
- ```
48
+ 1. **One canonical source, many adapters** — agent-native configs are
49
+ generated artifacts, never hand-edited.
50
+ 2. **No plaintext secrets, ever** — outputs hold variable references;
51
+ `trellis secrets audit` rejects raw values.
52
+ 3. **Verify, don't assume** — every adapter claim is backed by an executed
53
+ probe in isolated Docker sandboxes, never a developer's own dotfiles.
92
54
 
93
- ## Trellis itself as a Skill
94
-
95
- Trellis ships one package-owned Skill, `trellis-runtime`, with two layers:
96
-
97
- | Layer | Who uses it | What it covers |
98
- | --- | --- | --- |
99
- | Takeover and migration | the operator, with Agent assistance | inspect, dry-run, choose a migration source, choose the managed boundary, select Skills/MCP/Memory, authorize OAuth, sync, audit, verify, and rollback |
100
- | Runtime consumption | every managed Agent | discover and read canonical Skills, inspect shared Memory and global instructions, diagnose MCP, see managed Agents, and inspect or explicitly confirm task handoffs |
101
-
102
- `trellis init` bootstraps this Skill into
103
- `~/.trellis/skills/trellis-runtime/SKILL.md`. After an Agent is managed,
104
- `trellis sync` delivers it in the Agent's native Skill location for native or
105
- `both` delivery. For Runtime-only delivery, `SkillProvider` exposes the same
106
- canonical Skill through the `trellis` MCP Runtime; Kimi Code uses
107
- `trellis kimi` to prevent a second native Skill discovery path. This is one
108
- canonical Skill, not a copied per-Agent variant.
109
-
110
- Before takeover, the Skill cannot be consumed from an Agent that has not been
111
- connected to Trellis yet; use the CLI and
112
- [`docs/getting-started.md`](docs/getting-started.md#trellis-runtime-skill)
113
- for the first-run path. After takeover, the Skill is the Agent's operating
114
- guide for Trellis-managed capabilities. The MCP client may display names such
115
- as `mcp__trellis__skills_search`; `mcp__` is client-generated, while Trellis's
116
- portable names are `skills_search`, `memory_search`, `runtime_status`, and so
117
- on.
118
-
119
- **Or step by step** (what `onboard` is actually doing under the hood, if you
120
- want to run any one stage on its own):
121
-
122
- For standard MCP Router/client exports, use `trellis mcp import <json-file>`.
123
- It reads `mcpServers` without changing the source, de-duplicates existing
124
- servers, extracts credential-like environment values into the ignored local
125
- secret file, converts supported `mcp-remote` Basic Auth entries to native HTTP,
126
- and reports unsupported inline credentials or unavailable paths.
127
- Always run it with `--dry-run` first; see the detailed importer rules in
128
- [`docs/getting-started.md`](docs/getting-started.md).
129
-
130
- After upgrading Trellis, refresh the package-owned Runtime Skill with
131
- `trellis skill update-builtin --dry-run` followed by
132
- `trellis skill update-builtin`; the operation is backed up and does not require
133
- editing Agent-native files.
134
-
135
- **Already using Claude Code, Codex, Kiro, or pi and want to migrate what you
136
- already have?**
137
-
138
- 1. `trellis init` — creates `~/.trellis/` with a minimal skeleton (only what's
139
- missing; never overwrites a file you already have) and tells you which of
140
- the five supported agents it found on this machine.
141
- 2. `trellis migrate --from <agent>` — once per agent you already use. Copies
142
- that agent's real skills and instructions into canonical source. Never
143
- overwrites: an already-identical skill is reported and skipped, a genuine
144
- conflict is reported and left for you to resolve by hand. Add `--dry-run`
145
- to preview first.
146
- 3. `trellis sync` — distributes canonical skills/instructions to every
147
- **managed** agent (`~/.trellis/managed.yaml` — empty by default; edit it
148
- by hand or let `trellis onboard` write it). An agent that's merely present
149
- but not managed is never touched. Add `--dry-run` to preview first.
150
- 4. `trellis mcp sync` — distributes `~/.trellis/mcp/servers.yaml` (see
151
- [`schema/servers.example.yaml`](schema/servers.example.yaml)) to every
152
- managed agent's native MCP config, including ownership-safe removal.
153
- 5. `trellis secrets audit` — fails non-zero if any managed agent's real
154
- config holds a literal credential or an unexpected env var name.
155
- 6. `trellis doctor` — read-only scan of every present agent's current state
156
- (managed or not); run any time to check for drift.
157
-
158
- **Starting from nothing?** Skip step 2 — `trellis init`'s placeholder
159
- `agents.md` and empty `skills/` are a fine starting point; edit them by hand.
160
-
161
- **Every real write `sync`/`mcp sync`/`onboard` perform is backed up
162
- first, automatically — no flag to opt in.** Before creating, repairing,
163
- or removing anything, each is recorded to a structured, timestamped run
164
- under `~/.trellis/backups/`, with enough information to invert it exactly.
165
- `trellis rollback` undoes one recorded run — omit a run id for the most
166
- recent one:
55
+ Trellis aligns with the emerging [`.agents Protocol`](https://dotagentsprotocol.com)
56
+ draft rather than inventing another standard.
167
57
 
168
- ```
169
- $ trellis rollback
170
- rollback 2026-09-13T04-52-18-727Z-mcp-sync
171
- ✅ 3 restored, 0 conflict(s), 0 already reverted
172
- - [restore] restore /Users/you/.claude.json to its content before this run (...)
173
- ```
58
+ ## Docs
174
59
 
175
- If something else touched a path since the backed-up run, that one path
176
- is a `conflict` — reported, left untouched, never force-restored over —
177
- while every other path in the same rollback still restores. `--list`
178
- shows available runs without touching anything; `--dry-run` previews a
179
- restore with zero writes.
60
+ - [Overview](docs/overview.md) ([中文](docs/overview.zh-CN.md)) — what it is and why
61
+ - [Getting started](docs/getting-started.md) — every command, with example output
62
+ - [Architecture](docs/architecture.md) — what we build vs. deliberately reuse
63
+ - [Research](docs/research.md) — the full competitive landscape
180
64
 
181
65
  ## Status
182
66
 
183
- **Early, pre-1.0.** The CLI commands above are implemented, unit-tested, and
184
- verified against isolated Linux Docker scenarios (never a developer's own
185
- dotfiles during development — see
186
- [`docs/architecture.md`](docs/architecture.md)'s testing philosophy). The
187
- sandbox matrix covers migration, steady-state management, runtime routing,
188
- failure isolation, and expected conflicts. A separate agent image installs
189
- real Codex, Claude Code, Kiro CLI, and pi binaries to verify their isolated
190
- configuration behavior. `onboard` picks one agent as the migration base when
191
- more than one is present; merging differing content across multiple agents
192
- into one result is named future work, not built yet.
193
-
194
- **Known limitations, honestly stated rather than discovered the hard way:**
195
- - MCP servers are never spawned/handshake-tested by `trellis mcp sync` or
196
- `trellis sync` — only that the *config* is written correctly.
197
- `trellis doctor --probe-mcp` is the one command that actually connects,
198
- and it's opt-in.
199
- - The pi bridge extension (`trellis-pi-mcp-bridge`) has been verified to
200
- load and register tools without erroring, never against a real LLM tool
201
- call in production.
202
- - Verification has run against real Docker containers and real isolated
203
- Codex, Claude Code, Kiro CLI, and pi installs — not against a developer's
204
- actual daily-use agent directories. If you hit something a clean-room
205
- sandbox wouldn't have caught, please open an issue.
206
- - `~/.trellis/backups/` has no automatic pruning yet — every `sync`/
207
- `mcp sync`/`onboard`/`mcp import` run that performs a real write adds one more run
208
- directory, with no cap. Delete old ones by hand for now.
209
-
210
- A canonical MCP server can also declare `enabled: false` (kept defined,
211
- never written to any agent) and `static_env` (a value that was never a
212
- secret — an email, an environment tag — written verbatim instead of
213
- resolved by name; still scanned against `reject_patterns` like every
214
- other literal field). Before ever writing a name-only `env` entry,
215
- `mcp sync` now checks it actually resolves through the same source
216
- `secrets audit` and the pi bridge use — an unresolvable name is refused
217
- as a conflict, not silently written and left to break that server's
218
- connection once the agent starts it. Both found via real-machine
219
- dogfooding, not a synthetic fixture — see
220
- [`schema/servers.example.yaml`](schema/servers.example.yaml).
221
-
222
- ## Design principles
223
-
224
- 1. **One canonical source, many adapters.** Each agent's native config file is
225
- a generated or symlinked artifact, never hand-edited.
226
- 2. **Reuse before building.** MCP aggregation, memory, and secret-reference
227
- patterns already have mature open source answers — Trellis wires to them
228
- instead of reimplementing them. See [`docs/architecture.md`](docs/architecture.md).
229
- 3. **No plaintext secrets, ever.** Every adapter output holds variable
230
- references only; `trellis secrets audit` scans for and rejects raw values.
231
- 4. **Verify, don't assume.** Every claim this project makes about an agent's
232
- behavior (file format, discovery path, MCP support) is backed by an
233
- executed probe, not documentation-reading. Adapters that can't be verified
234
- this way don't ship.
67
+ **Early, pre-1.0.** All CLI commands are implemented, unit-tested, and verified
68
+ against real agents in isolated containers. Known limitations are listed in
69
+ [Getting started](docs/getting-started.md); please open an issue for anything
70
+ a clean-room sandbox wouldn't catch.
235
71
 
236
72
  ## License
237
73
 
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Runtime-first ZCode adapter.
3
+ *
4
+ * ZCode's native `~/.agents/skills` scan prevents scope-safe native delivery,
5
+ * so Runtime-only delivery uses one MCP Runtime edge and turns off the two
6
+ * native Skill switches through a ledger-backed, reversible config change.
7
+ */
8
+ import type { AdapterPlanItem, AdapterProbeResult, AdapterVerifyResult, TrellisAdapter } from "../core/adapter.js";
9
+ import type { CanonicalSource } from "../core/types.js";
10
+ import type { BackupSession } from "../lib/backup.js";
11
+ export declare class ZcodeAdapter implements TrellisAdapter {
12
+ private readonly homeDir;
13
+ private readonly env;
14
+ readonly name = "ZCode";
15
+ readonly id: "zcode";
16
+ constructor(homeDir?: string, env?: NodeJS.ProcessEnv);
17
+ probe(): Promise<AdapterProbeResult>;
18
+ plan(canonical: CanonicalSource): Promise<AdapterPlanItem[]>;
19
+ apply(plan: AdapterPlanItem[], backup: BackupSession): Promise<void>;
20
+ verify(canonical: CanonicalSource): Promise<AdapterVerifyResult>;
21
+ }
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Runtime-first ZCode adapter.
3
+ *
4
+ * ZCode's native `~/.agents/skills` scan prevents scope-safe native delivery,
5
+ * so Runtime-only delivery uses one MCP Runtime edge and turns off the two
6
+ * native Skill switches through a ledger-backed, reversible config change.
7
+ */
8
+ import { existsSync, readFileSync } from "node:fs";
9
+ import { homedir } from "node:os";
10
+ import { dirname, join } from "node:path";
11
+ import { isInScope } from "../core/adapter.js";
12
+ import { capabilityDeliveryForAgent, usesNativeCapabilityDelivery } from "../core/types.js";
13
+ import { applySymlinkPlan, planSymlinks } from "./symlinkPlan.js";
14
+ import { renderJsonServerEntry } from "./jsonMcp.js";
15
+ import { LEGACY_GATEWAY_ENTRY_NAME, LEGACY_RUNTIME_ENTRY_NAME, resolveMcpPlan } from "./mcpPlan.js";
16
+ import { deepEqual } from "../lib/deepEqual.js";
17
+ import { forgetOwned, loadMcpOwnership, ownedByAgent, recordOwned, saveMcpOwnership } from "../lib/mcpOwnership.js";
18
+ import { forgetZcodeSettingsOwnership, loadZcodeSettingsOwnership, saveZcodeSettingsOwnership } from "../lib/zcodeOwnership.js";
19
+ import * as zcodeProbe from "../probes/zcode.js";
20
+ function readConfig(path) {
21
+ if (!existsSync(path))
22
+ return undefined;
23
+ return JSON.parse(readFileSync(path, "utf8"));
24
+ }
25
+ function record(value) {
26
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
27
+ }
28
+ function zcodeServers(parsed) {
29
+ return record(record(parsed?.mcp).servers);
30
+ }
31
+ function planZcodeMcp(opts) {
32
+ const { desired, conflicts } = resolveMcpPlan("zcode", opts.mcp, opts.managedAgents, opts.policy);
33
+ const existing = zcodeServers(opts.parsed);
34
+ const items = [];
35
+ for (const { name, def } of desired) {
36
+ const rendered = renderJsonServerEntry(def);
37
+ if (deepEqual(existing[name], rendered))
38
+ continue;
39
+ items.push({
40
+ action: "create",
41
+ kind: "mcp",
42
+ target: opts.configPath,
43
+ mcpWrite: { name, def },
44
+ description: `MCP server "${name}" ${existing[name] === undefined ? "created" : "updated"} in ${opts.configPath}`,
45
+ });
46
+ }
47
+ for (const conflict of conflicts) {
48
+ items.push({ action: "conflict", kind: "mcp", target: opts.configPath, description: conflict.message, ...(conflict.remediation ? { remediation: conflict.remediation } : {}) });
49
+ }
50
+ const desiredNames = new Set(desired.map((entry) => entry.name));
51
+ for (const [name, expected] of Object.entries(opts.ownership)) {
52
+ if (desiredNames.has(name))
53
+ continue;
54
+ if ((name === LEGACY_GATEWAY_ENTRY_NAME || name === LEGACY_RUNTIME_ENTRY_NAME) && desiredNames.has("trellis"))
55
+ continue;
56
+ if (existing[name] === undefined || !deepEqual(existing[name], expected))
57
+ continue;
58
+ items.push({
59
+ action: "remove",
60
+ kind: "mcp",
61
+ target: opts.configPath,
62
+ mcpRemove: { name },
63
+ description: `MCP server "${name}" removed from ${opts.configPath} — no longer in canonical`,
64
+ });
65
+ }
66
+ return items;
67
+ }
68
+ function applyZcodeMcp(parsed, items) {
69
+ const base = parsed ?? {};
70
+ const mcp = record(base.mcp);
71
+ const servers = { ...record(mcp.servers) };
72
+ for (const item of items) {
73
+ if (item.kind !== "mcp")
74
+ continue;
75
+ if (item.action === "create" && item.mcpWrite)
76
+ servers[item.mcpWrite.name] = renderJsonServerEntry(item.mcpWrite.def);
77
+ if (item.action === "remove" && item.mcpRemove)
78
+ delete servers[item.mcpRemove.name];
79
+ }
80
+ return { ...base, mcp: { ...mcp, servers } };
81
+ }
82
+ function currentSkillControls(parsed) {
83
+ const features = record(parsed?.features);
84
+ const skills = record(parsed?.skills);
85
+ return {
86
+ featuresSkill: typeof features.skill === "boolean" ? features.skill : null,
87
+ skillsEnabled: typeof skills.enabled === "boolean" ? skills.enabled : null,
88
+ };
89
+ }
90
+ function applySkillControls(parsed, controls) {
91
+ const features = { ...record(parsed.features) };
92
+ const skills = { ...record(parsed.skills) };
93
+ if (controls.featuresSkill === null)
94
+ delete features.skill;
95
+ else
96
+ features.skill = controls.featuresSkill;
97
+ if (controls.skillsEnabled === null)
98
+ delete skills.enabled;
99
+ else
100
+ skills.enabled = controls.skillsEnabled;
101
+ return { ...parsed, features, skills };
102
+ }
103
+ export class ZcodeAdapter {
104
+ homeDir;
105
+ env;
106
+ name = "ZCode";
107
+ id = "zcode";
108
+ constructor(homeDir = homedir(), env = process.env) {
109
+ this.homeDir = homeDir;
110
+ this.env = env;
111
+ }
112
+ async probe() {
113
+ const snapshot = await zcodeProbe.probe(this.homeDir, { env: this.env });
114
+ return { present: snapshot.present, version: snapshot.version, ...(snapshot.diagnostics.length ? { detail: snapshot.diagnostics.join("; ") } : {}) };
115
+ }
116
+ async plan(canonical) {
117
+ const profile = zcodeProbe.resolveZcodeProfile(this.homeDir, this.env);
118
+ if (!profile)
119
+ return [];
120
+ const parsed = readConfig(profile.configPath);
121
+ const canonicalRoot = dirname(canonical.instructionsFile);
122
+ const runtimeOnly = capabilityDeliveryForAgent(this.id, canonical.mcp) === "mcp";
123
+ const items = [];
124
+ items.push(...planSymlinks({
125
+ rootDir: join(this.homeDir, ".zcode", "skills"),
126
+ desired: usesNativeCapabilityDelivery(this.id, canonical.mcp)
127
+ ? canonical.skills.filter((skill) => isInScope(this.id, skill.scope, canonical.managedAgents)).map((skill) => ({ name: skill.name, target: skill.dir }))
128
+ : [],
129
+ canonicalRoot: join(canonicalRoot, "skills"),
130
+ kind: "skill",
131
+ }));
132
+ items.push(...planSymlinks({
133
+ rootDir: join(this.homeDir, ".zcode"),
134
+ desired: [{ name: "AGENTS.md", target: canonical.instructionsFile }],
135
+ canonicalRoot,
136
+ kind: "instructions",
137
+ }));
138
+ items.push(...planZcodeMcp({
139
+ configPath: profile.configPath,
140
+ parsed,
141
+ mcp: canonical.mcp,
142
+ managedAgents: canonical.managedAgents,
143
+ policy: canonical.secretsPolicy,
144
+ ownership: ownedByAgent(loadMcpOwnership(this.homeDir), this.id),
145
+ }));
146
+ const current = currentSkillControls(parsed);
147
+ const ownership = loadZcodeSettingsOwnership(this.homeDir);
148
+ if (runtimeOnly && (current.featuresSkill !== false || current.skillsEnabled !== false)) {
149
+ items.push({
150
+ action: "create",
151
+ kind: "zcode-skill-control",
152
+ target: profile.configPath,
153
+ zcodeSkillControls: { featuresSkill: false, skillsEnabled: false, previous: current },
154
+ description: `native ZCode Skill discovery disabled in ${profile.configPath} for Runtime-only delivery`,
155
+ });
156
+ }
157
+ else if (!runtimeOnly && ownership?.configPath === profile.configPath && current.featuresSkill === false && current.skillsEnabled === false) {
158
+ items.push({
159
+ action: "remove",
160
+ kind: "zcode-skill-control",
161
+ target: profile.configPath,
162
+ zcodeSkillControls: { ...ownership.previous },
163
+ description: `previous native ZCode Skill settings restored in ${profile.configPath}`,
164
+ });
165
+ }
166
+ return items;
167
+ }
168
+ async apply(plan, backup) {
169
+ await applySymlinkPlan(plan.filter((item) => item.kind === "skill" || item.kind === "instructions"), backup);
170
+ const configItems = plan.filter((item) => (item.kind === "mcp" || item.kind === "zcode-skill-control") && (item.action === "create" || item.action === "remove"));
171
+ if (configItems.length === 0)
172
+ return;
173
+ const configPath = configItems[0].target;
174
+ let merged = applyZcodeMcp(readConfig(configPath), configItems);
175
+ const control = configItems.find((item) => item.kind === "zcode-skill-control")?.zcodeSkillControls;
176
+ if (control)
177
+ merged = applySkillControls(merged, control);
178
+ backup.writeFile(configPath, `${JSON.stringify(merged, null, 2)}\n`);
179
+ let ownership = loadMcpOwnership(this.homeDir);
180
+ for (const item of configItems) {
181
+ if (item.kind !== "mcp")
182
+ continue;
183
+ if (item.action === "create" && item.mcpWrite)
184
+ ownership = recordOwned(ownership, this.id, item.mcpWrite.name, renderJsonServerEntry(item.mcpWrite.def));
185
+ if (item.action === "remove" && item.mcpRemove)
186
+ ownership = forgetOwned(ownership, this.id, item.mcpRemove.name);
187
+ }
188
+ saveMcpOwnership(this.homeDir, ownership);
189
+ const controlItem = configItems.find((item) => item.kind === "zcode-skill-control");
190
+ if (controlItem?.action === "create" && controlItem.zcodeSkillControls?.previous) {
191
+ saveZcodeSettingsOwnership(this.homeDir, {
192
+ configPath,
193
+ managed: { featuresSkill: false, skillsEnabled: false },
194
+ previous: controlItem.zcodeSkillControls.previous,
195
+ });
196
+ }
197
+ else if (controlItem?.action === "remove") {
198
+ forgetZcodeSettingsOwnership(this.homeDir);
199
+ }
200
+ }
201
+ async verify(canonical) {
202
+ const snapshot = await zcodeProbe.probe(this.homeDir, { env: this.env });
203
+ if (!snapshot.present)
204
+ return { ok: false, mismatches: ["zcode is not present on this machine"] };
205
+ const profile = zcodeProbe.resolveZcodeProfile(this.homeDir, this.env);
206
+ if (!profile)
207
+ return { ok: false, mismatches: ["zcode profile cannot be selected"] };
208
+ const mismatches = [];
209
+ const desiredNativeSkills = canonical.skills
210
+ .filter((skill) => usesNativeCapabilityDelivery(this.id, canonical.mcp) && isInScope(this.id, skill.scope, canonical.managedAgents))
211
+ .map((skill) => skill.name);
212
+ const actualNativeSkills = new Set(snapshot.skillRoots.filter((root) => root.path === join(this.homeDir, ".zcode", "skills")).flatMap((root) => root.skills.map((skill) => skill.name)));
213
+ for (const name of desiredNativeSkills)
214
+ if (!actualNativeSkills.has(name))
215
+ mismatches.push(`skill "${name}" is missing on ZCode`);
216
+ const expectedMcp = planZcodeMcp({
217
+ configPath: profile.configPath,
218
+ parsed: readConfig(profile.configPath),
219
+ mcp: canonical.mcp,
220
+ managedAgents: canonical.managedAgents,
221
+ policy: canonical.secretsPolicy,
222
+ ownership: ownedByAgent(loadMcpOwnership(this.homeDir), this.id),
223
+ }).filter((item) => item.action === "create" || item.action === "conflict");
224
+ mismatches.push(...expectedMcp.map((item) => item.description));
225
+ if (!snapshot.instructionsFile?.isSymlink || snapshot.instructionsFile.target !== canonical.instructionsFile)
226
+ mismatches.push("shared instructions are not linked into ~/.zcode/AGENTS.md");
227
+ if (capabilityDeliveryForAgent(this.id, canonical.mcp) === "mcp") {
228
+ const controls = currentSkillControls(readConfig(profile.configPath));
229
+ if (controls.featuresSkill !== false || controls.skillsEnabled !== false)
230
+ mismatches.push("native ZCode Skill discovery is still enabled during Runtime-only delivery");
231
+ }
232
+ return mismatches.length === 0 ? { ok: true } : { ok: false, mismatches };
233
+ }
234
+ }
package/dist/cli.js CHANGED
@@ -16,7 +16,7 @@ import { runMcpAuth } from "./commands/mcpAuth.js";
16
16
  import { runSecretsAudit } from "./commands/secretsAudit.js";
17
17
  import { runRollback } from "./commands/rollback.js";
18
18
  import { runSkillList, runSkillAdd, runSkillRemove, runSkillUpdateBuiltin } from "./commands/skill.js";
19
- import { runMemoryExtraction, runMemorySync } from "./commands/memory.js";
19
+ import { collectMemoryList, runMemoryExtraction, runMemorySync } from "./commands/memory.js";
20
20
  import { parseManageArgs, runManage } from "./commands/manage.js";
21
21
  import { runKimi } from "./commands/kimi.js";
22
22
  import { TRELLIS_VERSION } from "./lib/cliMetadata.js";
@@ -130,8 +130,9 @@ Commands:
130
130
  upstream capabilities; existing mcp-gateway configs remain valid
131
131
  as a compatibility alias
132
132
  mcp remove <name>
133
- Remove a canonical MCP server (canonical-side only — does
134
- not touch any agent's already-synced native config)
133
+ Remove a canonical MCP server, then run the same sync as
134
+ mcp sync so every managed agent's Trellis-owned entry for
135
+ it is removed too
135
136
  --dry-run preview the plan, write nothing
136
137
  --json machine-readable output, no report text
137
138
  skill list
@@ -325,12 +326,12 @@ async function main(argv) {
325
326
  }
326
327
  if (subcommand === "add") {
327
328
  const [name] = mcpRest;
328
- process.exitCode = runMcpAdd(name, parseMcpAddArgs(mcpRest), { json, dryRun }).exitCode;
329
+ process.exitCode = (await runMcpAdd(name, parseMcpAddArgs(mcpRest), { json, dryRun })).exitCode;
329
330
  return;
330
331
  }
331
332
  if (subcommand === "import") {
332
333
  const [file] = mcpRest;
333
- process.exitCode = runMcpImport(file, { json, dryRun }).exitCode;
334
+ process.exitCode = (await runMcpImport(file, { json, dryRun })).exitCode;
334
335
  return;
335
336
  }
336
337
  if (subcommand === "set") {
@@ -347,7 +348,7 @@ async function main(argv) {
347
348
  process.exitCode = 1;
348
349
  return;
349
350
  }
350
- process.exitCode = runMcpRemove(name, { json, dryRun }).exitCode;
351
+ process.exitCode = (await runMcpRemove(name, { json, dryRun })).exitCode;
351
352
  return;
352
353
  }
353
354
  if (subcommand === "auth") {
@@ -382,7 +383,7 @@ async function main(argv) {
382
383
  process.exitCode = 1;
383
384
  return;
384
385
  }
385
- process.exitCode = runSkillAdd(name, from, { json, dryRun }).exitCode;
386
+ process.exitCode = (await runSkillAdd(name, from, { json, dryRun })).exitCode;
386
387
  return;
387
388
  }
388
389
  if (subcommand === "remove") {
@@ -392,7 +393,7 @@ async function main(argv) {
392
393
  process.exitCode = 1;
393
394
  return;
394
395
  }
395
- process.exitCode = runSkillRemove(name, { json, dryRun }).exitCode;
396
+ process.exitCode = (await runSkillRemove(name, { json, dryRun })).exitCode;
396
397
  return;
397
398
  }
398
399
  if (subcommand === "update-builtin") {
@@ -407,6 +408,21 @@ async function main(argv) {
407
408
  const [subcommand, ...memoryRest] = rest;
408
409
  const json = memoryRest.includes("--json");
409
410
  const dryRun = memoryRest.includes("--dry-run");
411
+ if (subcommand === "list") {
412
+ const entries = collectMemoryList();
413
+ if (json) {
414
+ console.log(JSON.stringify(entries, null, 2));
415
+ }
416
+ else if (entries.length === 0) {
417
+ console.log("No memories in canonical source yet.");
418
+ }
419
+ else {
420
+ for (const { name, scope } of entries) {
421
+ console.log(`${name} — ${scope.length > 0 ? scope.join(", ") : "(no managed agent reaches it)"}`);
422
+ }
423
+ }
424
+ return;
425
+ }
410
426
  if (subcommand === "sync") {
411
427
  process.exitCode = runMemorySync({ json, dryRun }).exitCode;
412
428
  return;
@@ -415,7 +431,7 @@ async function main(argv) {
415
431
  process.exitCode = runMemoryExtraction({ json, dryRun }).exitCode;
416
432
  return;
417
433
  }
418
- console.error(`Unknown memory subcommand: ${subcommand ?? "(none)"}\nUsage: trellis memory sync|extract\n`);
434
+ console.error(`Unknown memory subcommand: ${subcommand ?? "(none)"}\nUsage: trellis memory list|sync|extract\n`);
419
435
  process.exitCode = 1;
420
436
  return;
421
437
  }
@@ -10,6 +10,7 @@ import * as codexProbe from "../probes/codex.js";
10
10
  import * as kiroProbe from "../probes/kiro.js";
11
11
  import * as piProbe from "../probes/pi.js";
12
12
  import * as kimiCodeProbe from "../probes/kimi-code.js";
13
+ import * as zcodeProbe from "../probes/zcode.js";
13
14
  import { loadCanonicalSource } from "../core/canonical.js";
14
15
  import { GATEWAY_ENTRY_NAME, RUNTIME_ENTRY_NAME, resolveMcpPlan } from "../adapters/mcpPlan.js";
15
16
  import { ALL_AGENTS } from "../core/types.js";
@@ -76,6 +77,7 @@ export async function collectDoctorReport(homeDir = homedir(), knownHostInjected
76
77
  { agent: "kiro", run: () => kiroProbe.probe(homeDir, { probeMcp }) },
77
78
  { agent: "pi", run: () => piProbe.probe(homeDir) },
78
79
  { agent: "kimi-code", run: () => kimiCodeProbe.probe(homeDir, { probeMcp }) },
80
+ { agent: "zcode", run: () => zcodeProbe.probe(homeDir, { probeMcp }) },
79
81
  ];
80
82
  // One agent erroring must not blank the other three's results.
81
83
  const settled = await Promise.allSettled(probeList.map((p) => p.run()));
@@ -29,7 +29,7 @@ export interface InitReport {
29
29
  /** Exported so `migrate` can byte-compare canonical `agents.md` against
30
30
  * this exact string (design.md D3, trellis-cli-migrate) rather than
31
31
  * retyping an equivalent one that could silently drift from this. */
32
- export declare const AGENTS_MD_TEMPLATE = "# Shared instructions\n\nWrite what every agent should know here \u2014 communication preferences,\nproject conventions, anything you'd otherwise repeat per agent.\n\nAlready using Claude Code, Codex, Kiro, pi, or Kimi Code? `trellis migrate --from\n<agent>` imports its real instructions and skills instead of starting\nfrom this placeholder.\n";
32
+ export declare const AGENTS_MD_TEMPLATE = "# Shared instructions\n\nWrite what every agent should know here \u2014 communication preferences,\nproject conventions, anything you'd otherwise repeat per agent.\n\nAlready using Claude Code, Codex, Kiro, pi, Kimi Code, or ZCode? `trellis migrate --from\n<agent>` imports its real instructions and skills instead of starting\nfrom this placeholder.\n";
33
33
  /**
34
34
  * Trellis never spawns an installer itself (global package installs are
35
35
  * exactly the kind of irreversible, system-wide action that needs the