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.
- package/README.md +43 -207
- package/dist/adapters/zcode.d.ts +21 -0
- package/dist/adapters/zcode.js +234 -0
- package/dist/cli.js +25 -9
- package/dist/commands/doctor.js +2 -0
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +4 -1
- package/dist/commands/mcp.d.ts +56 -14
- package/dist/commands/mcp.js +105 -28
- package/dist/commands/mcpGateway.js +2 -1
- package/dist/commands/mcpImport.d.ts +21 -2
- package/dist/commands/mcpImport.js +30 -7
- package/dist/commands/memory.d.ts +13 -1
- package/dist/commands/memory.js +15 -0
- package/dist/commands/migrate.js +4 -1
- package/dist/commands/onboard.js +15 -4
- package/dist/commands/rollback.js +24 -1
- package/dist/commands/secretsAudit.js +4 -1
- package/dist/commands/skill.d.ts +35 -6
- package/dist/commands/skill.js +67 -13
- package/dist/commands/sync.js +3 -1
- package/dist/core/adapter.d.ts +11 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.js +1 -0
- package/dist/lib/agentBridge.d.ts +169 -0
- package/dist/lib/agentBridge.js +367 -0
- package/dist/lib/agentBridgeProvider.d.ts +14 -0
- package/dist/lib/agentBridgeProvider.js +95 -0
- package/dist/lib/backup.d.ts +30 -0
- package/dist/lib/backup.js +16 -1
- package/dist/lib/chatAgents.d.ts +42 -0
- package/dist/lib/chatAgents.js +59 -0
- package/dist/lib/envVarNames.d.ts +3 -0
- package/dist/lib/envVarNames.js +19 -0
- package/dist/lib/installAgent.d.ts +1 -1
- package/dist/lib/installAgent.js +1 -1
- package/dist/lib/mcpMigrateRead.d.ts +1 -0
- package/dist/lib/mcpMigrateRead.js +19 -1
- package/dist/lib/realHomeSnapshot.js +5 -0
- package/dist/lib/runtimeControlProvider.js +2 -0
- package/dist/lib/taskStore.js +1 -1
- package/dist/lib/terminalPicker.js +33 -6
- package/dist/lib/zcodeOwnership.d.ts +17 -0
- package/dist/lib/zcodeOwnership.js +37 -0
- package/dist/pi-bridge/bundle.js +2 -1
- package/dist/probes/codex.d.ts +7 -0
- package/dist/probes/codex.js +37 -5
- package/dist/probes/zcode.d.ts +32 -0
- package/dist/probes/zcode.js +140 -0
- package/docs/architecture.md +9 -5
- package/docs/assets/brand-v3/trellis-mark-v3-a.png +0 -0
- package/docs/assets/brand-v3/trellis-mark-v3-a.svg +10 -0
- package/docs/assets/poster-series-v3/README.md +60 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-en.svg +51 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-zh.svg +51 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-en.svg +48 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-zh.svg +48 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-en.svg +56 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-zh.svg +56 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-en.svg +47 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-zh.svg +47 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-en.svg +51 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-zh.svg +51 -0
- package/docs/getting-started.md +173 -12
- package/docs/overview.md +6 -3
- package/docs/overview.zh-CN.md +5 -3
- package/docs/roadmap.md +2 -1
- package/docs/video/README.md +76 -0
- package/docs/video/build/audio/01-opening.aiff +0 -0
- package/docs/video/build/audio/01-opening.mp3 +0 -0
- package/docs/video/build/audio/02-pain.aiff +0 -0
- package/docs/video/build/audio/02-pain.mp3 +0 -0
- package/docs/video/build/audio/03-solution.aiff +0 -0
- package/docs/video/build/audio/03-solution.mp3 +0 -0
- package/docs/video/build/audio/04-install.aiff +0 -0
- package/docs/video/build/audio/04-install.mp3 +0 -0
- package/docs/video/build/audio/04-setup.mp3 +0 -0
- package/docs/video/build/audio/05-dryrun.mp3 +0 -0
- package/docs/video/build/audio/05-init.aiff +0 -0
- package/docs/video/build/audio/05-init.mp3 +0 -0
- package/docs/video/build/audio/05-interactive.mp3 +0 -0
- package/docs/video/build/audio/06-dryrun.aiff +0 -0
- package/docs/video/build/audio/06-dryrun.mp3 +0 -0
- package/docs/video/build/audio/06-onboard.mp3 +0 -0
- package/docs/video/build/audio/06-run.mp3 +0 -0
- package/docs/video/build/audio/07-onboard.aiff +0 -0
- package/docs/video/build/audio/07-onboard.mp3 +0 -0
- package/docs/video/build/audio/07-verify.mp3 +0 -0
- package/docs/video/build/audio/08-closing.mp3 +0 -0
- package/docs/video/build/audio/08-doctor.aiff +0 -0
- package/docs/video/build/audio/08-doctor.mp3 +0 -0
- package/docs/video/build/audio/09-rollback.aiff +0 -0
- package/docs/video/build/audio/09-rollback.mp3 +0 -0
- package/docs/video/build/audio/10-principles.aiff +0 -0
- package/docs/video/build/audio/10-principles.mp3 +0 -0
- package/docs/video/build/audio/11-closing.aiff +0 -0
- package/docs/video/build/audio/11-closing.mp3 +0 -0
- package/docs/video/build/frames/01-opening-0.png +0 -0
- package/docs/video/build/frames/02-pain-1.png +0 -0
- package/docs/video/build/frames/02-pain-2.png +0 -0
- package/docs/video/build/frames/03-solution-3.png +0 -0
- package/docs/video/build/frames/04-install-4.png +0 -0
- package/docs/video/build/frames/04-setup-4.png +0 -0
- package/docs/video/build/frames/04-setup-5.png +0 -0
- package/docs/video/build/frames/05-dryrun-6.png +0 -0
- package/docs/video/build/frames/05-init-5.png +0 -0
- package/docs/video/build/frames/05-interactive-5.png +0 -0
- package/docs/video/build/frames/05-interactive-6.png +0 -0
- package/docs/video/build/frames/06-dryrun-6.png +0 -0
- package/docs/video/build/frames/06-dryrun-7.png +0 -0
- package/docs/video/build/frames/06-onboard-7.png +0 -0
- package/docs/video/build/frames/06-onboard-8.png +0 -0
- package/docs/video/build/frames/06-run-7.png +0 -0
- package/docs/video/build/frames/06-run-8.png +0 -0
- package/docs/video/build/frames/07-onboard-10.png +0 -0
- package/docs/video/build/frames/07-onboard-7.png +0 -0
- package/docs/video/build/frames/07-onboard-8.png +0 -0
- package/docs/video/build/frames/07-onboard-9.png +0 -0
- package/docs/video/build/frames/07-verify-10.png +0 -0
- package/docs/video/build/frames/07-verify-8.png +0 -0
- package/docs/video/build/frames/07-verify-9.png +0 -0
- package/docs/video/build/frames/08-closing-10.png +0 -0
- package/docs/video/build/frames/08-closing-11.png +0 -0
- package/docs/video/build/frames/08-doctor-11.png +0 -0
- package/docs/video/build/frames/08-doctor-9.png +0 -0
- package/docs/video/build/frames/09-rollback-10.png +0 -0
- package/docs/video/build/frames/09-rollback-12.png +0 -0
- package/docs/video/build/frames/10-principles-11.png +0 -0
- package/docs/video/build/frames/10-principles-13.png +0 -0
- package/docs/video/build/frames/11-closing-12.png +0 -0
- package/docs/video/build/frames/11-closing-14.png +0 -0
- package/docs/video/build/segments/01-opening.mp4 +0 -0
- package/docs/video/build/segments/01-opening.txt +3 -0
- package/docs/video/build/segments/02-pain.mp4 +0 -0
- package/docs/video/build/segments/02-pain.txt +5 -0
- package/docs/video/build/segments/03-solution.mp4 +0 -0
- package/docs/video/build/segments/03-solution.txt +3 -0
- package/docs/video/build/segments/04-install.mp4 +0 -0
- package/docs/video/build/segments/04-install.txt +3 -0
- package/docs/video/build/segments/04-setup.mp4 +0 -0
- package/docs/video/build/segments/04-setup.txt +3 -0
- package/docs/video/build/segments/05-dryrun.mp4 +0 -0
- package/docs/video/build/segments/05-dryrun.txt +3 -0
- package/docs/video/build/segments/05-init.mp4 +0 -0
- package/docs/video/build/segments/05-init.txt +3 -0
- package/docs/video/build/segments/05-interactive.mp4 +0 -0
- package/docs/video/build/segments/05-interactive.txt +5 -0
- package/docs/video/build/segments/06-dryrun.mp4 +0 -0
- package/docs/video/build/segments/06-dryrun.txt +3 -0
- package/docs/video/build/segments/06-onboard.mp4 +0 -0
- package/docs/video/build/segments/06-onboard.txt +5 -0
- package/docs/video/build/segments/06-run.mp4 +0 -0
- package/docs/video/build/segments/06-run.txt +3 -0
- package/docs/video/build/segments/07-onboard.mp4 +0 -0
- package/docs/video/build/segments/07-onboard.txt +5 -0
- package/docs/video/build/segments/07-verify.mp4 +0 -0
- package/docs/video/build/segments/07-verify.txt +5 -0
- package/docs/video/build/segments/08-closing.mp4 +0 -0
- package/docs/video/build/segments/08-closing.txt +3 -0
- package/docs/video/build/segments/08-doctor.mp4 +0 -0
- package/docs/video/build/segments/08-doctor.txt +3 -0
- package/docs/video/build/segments/09-rollback.mp4 +0 -0
- package/docs/video/build/segments/09-rollback.txt +3 -0
- package/docs/video/build/segments/10-principles.mp4 +0 -0
- package/docs/video/build/segments/10-principles.txt +3 -0
- package/docs/video/build/segments/11-closing.mp4 +0 -0
- package/docs/video/build/segments/11-closing.txt +3 -0
- package/docs/video/build/segments/final.txt +8 -0
- package/docs/video/build-ai/audio/01-hook.mp3 +0 -0
- package/docs/video/build-ai/audio/02-pain.mp3 +0 -0
- package/docs/video/build-ai/audio/03-solution.mp3 +0 -0
- package/docs/video/build-ai/audio/04-how.mp3 +0 -0
- package/docs/video/build-ai/audio/05-safe.mp3 +0 -0
- package/docs/video/build-ai/audio/06-closing.mp3 +0 -0
- package/docs/video/build-ai/clips/01-hook.mp4 +0 -0
- package/docs/video/build-ai/clips/02-pain.mp4 +0 -0
- package/docs/video/build-ai/clips/03-solution.mp4 +0 -0
- package/docs/video/build-ai/clips/04-how.mp4 +0 -0
- package/docs/video/build-ai/clips/05-safe.mp4 +0 -0
- package/docs/video/build-ai/clips/06-closing.mp4 +0 -0
- package/docs/video/build-ai/first-frame-02-pain.png +0 -0
- package/docs/video/build-ai/first-frame-03-solution.png +0 -0
- package/docs/video/build-ai/first-frame-04-how.png +0 -0
- package/docs/video/build-ai/first-frame-05-safe.png +0 -0
- package/docs/video/build-ai/segments/01-hook.caption.txt +2 -0
- package/docs/video/build-ai/segments/01-hook.mp4 +0 -0
- package/docs/video/build-ai/segments/02-pain.mp4 +0 -0
- package/docs/video/build-ai/segments/03-solution.mp4 +0 -0
- package/docs/video/build-ai/segments/04-how.mp4 +0 -0
- package/docs/video/build-ai/segments/05-safe.mp4 +0 -0
- package/docs/video/build-ai/segments/06-closing.mp4 +0 -0
- package/docs/video/build-ai/segments/cap-01-hook.png +0 -0
- package/docs/video/build-ai/segments/cap-02-pain.png +0 -0
- package/docs/video/build-ai/segments/cap-03-solution.png +0 -0
- package/docs/video/build-ai/segments/cap-04-how.png +0 -0
- package/docs/video/build-ai/segments/cap-05-safe.png +0 -0
- package/docs/video/build-ai/segments/cap-06-closing.png +0 -0
- package/docs/video/build-ai/segments/final.txt +6 -0
- package/docs/video/build-posters/audio/01-hook.mp3 +0 -0
- package/docs/video/build-posters/audio/02-pain.mp3 +0 -0
- package/docs/video/build-posters/audio/03-solution.mp3 +0 -0
- package/docs/video/build-posters/audio/04-how.mp3 +0 -0
- package/docs/video/build-posters/audio/05-safe.mp3 +0 -0
- package/docs/video/build-posters/audio/06-closing.mp3 +0 -0
- package/docs/video/build-posters/cap-01-hook.png +0 -0
- package/docs/video/build-posters/cap-02-pain.png +0 -0
- package/docs/video/build-posters/cap-03-solution.png +0 -0
- package/docs/video/build-posters/cap-04-how.png +0 -0
- package/docs/video/build-posters/cap-05-safe.png +0 -0
- package/docs/video/build-posters/cap-06-closing.png +0 -0
- package/docs/video/build-posters/card-01-hook.png +0 -0
- package/docs/video/build-posters/card-06-closing.png +0 -0
- package/docs/video/build-posters/segments/01-hook.mp4 +0 -0
- package/docs/video/build-posters/segments/02-pain.mp4 +0 -0
- package/docs/video/build-posters/segments/03-solution.mp4 +0 -0
- package/docs/video/build-posters/segments/04-how.mp4 +0 -0
- package/docs/video/build-posters/segments/05-safe.mp4 +0 -0
- package/docs/video/build-posters/segments/06-closing.mp4 +0 -0
- package/docs/video/build-posters/segments/final.txt +6 -0
- package/docs/video/generate-video-ai.mjs +334 -0
- package/docs/video/generate-video-posters.mjs +204 -0
- package/docs/video/generate-video.mjs +426 -0
- package/docs/video/outline.zh-CN.md +102 -0
- package/docs/video/trellis-demo-video-ai.mp4 +0 -0
- package/docs/video/trellis-demo-video.mp4 +0 -0
- package/docs/video/voiceover.zh-CN.md +49 -0
- package/package.json +5 -2
- package/schema/servers.example.yaml +1 -1
- package/docs/assets/agent-trellis-architecture-horizontal.svg +0 -80
- package/docs/assets/agent-trellis-architecture-vertical.svg +0 -82
- 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
|
-
|
|
10
|
-
|
|
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
|
-
>
|
|
13
|
-
>
|
|
12
|
+
> 中文:一个 canonical source 统一管理多个 Code Agent 的 Skill、MCP、Memory
|
|
13
|
+
> 与共享指令,支持预览、备份与回滚。
|
|
14
14
|
|
|
15
|
-
Trellis
|
|
16
|
-
source and generates verified native or Runtime projections from it.
|
|
15
|
+

|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-

|
|
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
|
-
|
|
31
|
-
trellis onboard
|
|
32
|
-
trellis
|
|
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
|
-
|
|
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
|
-
|
|
57
|
-
walkthrough — example output for each command, what each `migrate`/`sync`
|
|
58
|
-
conflict action means, and troubleshooting.
|
|
29
|
+
## How it compares
|
|
59
30
|
|
|
60
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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.**
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
|
134
|
-
|
|
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
|
}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -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()));
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -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,
|
|
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
|