agent-trellis 0.14.1 → 0.15.0
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/dist/adapters/claude-code.js +4 -3
- package/dist/adapters/codex.js +4 -3
- package/dist/adapters/kimi-code.js +4 -3
- package/dist/adapters/kiro.js +5 -4
- package/dist/adapters/pi.js +4 -3
- package/dist/adapters/zcode.d.ts +12 -1
- package/dist/adapters/zcode.js +7 -6
- package/dist/cli.js +38 -5
- package/dist/commands/doctor.d.ts +9 -1
- package/dist/commands/doctor.js +43 -6
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.js +24 -0
- package/dist/commands/mcp.d.ts +44 -1
- package/dist/commands/mcp.js +145 -33
- package/dist/commands/migrate.d.ts +12 -0
- package/dist/commands/migrate.js +8 -4
- package/dist/commands/migrateWorkspace.d.ts +40 -0
- package/dist/commands/migrateWorkspace.js +197 -0
- package/dist/commands/rollback.js +65 -35
- package/dist/commands/skill.d.ts +14 -0
- package/dist/commands/skill.js +71 -0
- package/dist/commands/sync.d.ts +16 -1
- package/dist/commands/sync.js +48 -15
- package/dist/core/adapter.d.ts +14 -0
- package/dist/core/canonical.d.ts +20 -34
- package/dist/core/canonical.js +18 -92
- package/dist/core/mcpServerDef.d.ts +39 -0
- package/dist/core/mcpServerDef.js +93 -0
- package/dist/core/types.d.ts +39 -4
- package/dist/lib/mcpMigrateRead.d.ts +25 -0
- package/dist/lib/mcpMigrateRead.js +9 -2
- package/dist/lib/skillProvider.js +18 -5
- package/dist/lib/workspace.d.ts +39 -0
- package/dist/lib/workspace.js +158 -0
- package/dist/lib/workspaceConfig.d.ts +45 -0
- package/dist/lib/workspaceConfig.js +98 -0
- package/dist/lib/workspaceDoctor.d.ts +44 -0
- package/dist/lib/workspaceDoctor.js +94 -0
- package/dist/lib/workspaceFiles.d.ts +38 -0
- package/dist/lib/workspaceFiles.js +264 -0
- package/dist/lib/workspaceMcp.d.ts +57 -0
- package/dist/lib/workspaceMcp.js +277 -0
- package/dist/lib/workspaceMerge.d.ts +37 -0
- package/dist/lib/workspaceMerge.js +98 -0
- package/dist/lib/workspaceMigrate.d.ts +118 -0
- package/dist/lib/workspaceMigrate.js +423 -0
- package/dist/pi-bridge/bundle.js +258 -96
- package/docs/architecture.md +111 -49
- package/docs/getting-started.md +86 -14
- package/docs/mcp-oauth-matrix.md +12 -1
- package/docs/overview.zh-CN.md +17 -0
- package/docs/research.md +28 -6
- package/docs/roadmap.md +17 -5
- package/package.json +1 -1
- package/docs/implementation-plan.md +0 -341
package/docs/architecture.md
CHANGED
|
@@ -10,8 +10,8 @@ required reading for that.
|
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
┌─────────────────────────────────────────────────────────┐
|
|
13
|
-
│ Trellis canonical source (~/.trellis
|
|
14
|
-
│ "Global vs. workspace scope" below)
|
|
13
|
+
│ Trellis canonical source (~/.trellis global + <repo>/.agents, │
|
|
14
|
+
│ see "Global vs. workspace scope" below) │
|
|
15
15
|
│ instructions · skills · agents · mcp/servers.yaml · │
|
|
16
16
|
│ memories · secrets policy │
|
|
17
17
|
└───────────────┬─────────────────────────────────────────┘
|
|
@@ -19,8 +19,8 @@ required reading for that.
|
|
|
19
19
|
┌───────┼────────┬─────────────┬──────────────┐
|
|
20
20
|
▼ ▼ ▼ ▼
|
|
21
21
|
Claude Code Codex Kiro pi Kimi Code ZCode
|
|
22
|
-
(symlink adapter) (incremental (symlink adapter) (
|
|
23
|
-
TOML writer)
|
|
22
|
+
(symlink adapter) (incremental (symlink adapter) (native
|
|
23
|
+
TOML writer) mcp.json)
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
Trellis owns exactly one thing: **the canonical source, and the generators
|
|
@@ -56,19 +56,77 @@ Aligned to the `.agents Protocol` draft, extended where the draft is silent:
|
|
|
56
56
|
|
|
57
57
|
## Global vs. workspace scope
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
Two layers, both canonical: `~/.trellis` per machine (global) and
|
|
60
|
+
`<repo>/.agents/` per project (workspace). A repo opts in by containing
|
|
61
|
+
`.agents/`; `trellis sync` discovers the nearest ancestor `.agents/`
|
|
62
|
+
walking up from the cwd (`findWorkspaceRoot` in `src/lib/workspace.ts` —
|
|
63
|
+
`~/` itself is never picked up as a workspace root) and merges the two
|
|
64
|
+
layers. Outside any workspace the plan is byte-identical to the old
|
|
65
|
+
global-only behavior; `--global-only` opts out explicitly.
|
|
62
66
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
```
|
|
68
|
+
.agents/
|
|
69
|
+
├── config.json # { "version": 1, mcp.servers } — the same
|
|
70
|
+
│ # snake_case schema and validator as
|
|
71
|
+
│ # mcp/servers.yaml; one schema, one validator
|
|
72
|
+
├── AGENTS.md # workspace instructions
|
|
73
|
+
├── skills/<name>/SKILL.md
|
|
74
|
+
└── .trellis-rendered.json # Trellis's ownership manifest — committable;
|
|
75
|
+
# what a fresh clone re-attaches through
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Merge semantics (`src/lib/workspaceMerge.ts`): workspace wins by ID for
|
|
79
|
+
MCP servers and skills; `enabled: false` tombstones a global entry for
|
|
80
|
+
this project only; instructions are not content-merged (a workspace
|
|
81
|
+
`AGENTS.md` stands on its own layer). Provenance and the
|
|
82
|
+
shadowed/tombstoned lists ride on the canonical source so `trellis
|
|
83
|
+
doctor` can attribute every entry to its layer.
|
|
84
|
+
|
|
85
|
+
Delivery is layer-preserving — Trellis never re-renders global content
|
|
86
|
+
into project files. Global entries go to the agents' user-level paths as
|
|
87
|
+
before; workspace entries go to project-level native paths (`.mcp.json`,
|
|
88
|
+
`.codex/config.toml`, `.kiro/settings/mcp.json`, `.pi/mcp.json`,
|
|
89
|
+
`.kimi-code/mcp.json`, `zcode.json`/`.zcode/config.json`). The agents
|
|
90
|
+
then layer natively: five of six resolve project-over-user; zcode
|
|
91
|
+
resolves same-name MCP conflicts user-first, so a shadowing workspace
|
|
92
|
+
server gets an explicit sync warning instead of a silent no-op. Skills
|
|
93
|
+
are *copied* (not symlinked — rendered artifacts must be committable and
|
|
94
|
+
work without symlink support) into `.claude/skills/` and `.kiro/skills/`
|
|
95
|
+
with digest-based drift detection, while Codex/pi/Kimi read
|
|
96
|
+
`.agents/skills/` natively. Instructions render as marker-headed copies:
|
|
97
|
+
root `AGENTS.md` for Codex/pi/Kimi and `.kiro/steering/
|
|
98
|
+
trellis-workspace.md` for Kiro; Claude's `CLAUDE.md` is never written
|
|
99
|
+
(v1 limitation — `migrate --workspace` is the path for absorbing a
|
|
100
|
+
hand-written one).
|
|
101
|
+
|
|
102
|
+
Two invariants make the workspace layer safe to commit:
|
|
103
|
+
|
|
104
|
+
- **No secrets in the repo.** Workspace `config.json` rejects
|
|
105
|
+
credential-shaped literals at load (the same `reject_patterns` as the
|
|
106
|
+
global secrets policy) and accepts only `${VAR}` references; rendered
|
|
107
|
+
artifacts likewise carry references, never resolved values. Secret
|
|
108
|
+
values live in the machine-local store (`secrets.policy.yaml`'s
|
|
109
|
+
`env_file`) and are re-established per machine —
|
|
110
|
+
`migrate --workspace` extracts any literal it finds in a hand-written
|
|
111
|
+
project file into that store (and flags git-tracked plaintext with a
|
|
112
|
+
rotation advisory).
|
|
113
|
+
- **Ownership travels with the repo.** `.agents/.trellis-rendered.json`
|
|
114
|
+
records what Trellis rendered per agent per server; an entry present
|
|
115
|
+
in an agent's file but absent from the manifest is user-authored and
|
|
116
|
+
never overwritten. Because the manifest is committed, a fresh clone —
|
|
117
|
+
or a copied directory — re-attaches cleanly instead of
|
|
118
|
+
conflict-guarding on its own committed artifacts.
|
|
119
|
+
|
|
120
|
+
`trellis sync --check` computes the identical plan with zero writes and
|
|
121
|
+
exits non-zero on drift — the CI freshness gate for committed artifacts.
|
|
122
|
+
Existing hand-written project config is adopted with
|
|
123
|
+
`trellis migrate --workspace`: it scans all six agents' project-level
|
|
124
|
+
paths plus the root `AGENTS.md`, classifies every find (create /
|
|
125
|
+
already-managed / identical-to-global / skip-local / skip-unsupported /
|
|
126
|
+
conflict / extract-secret), refuses the whole run on unresolved
|
|
127
|
+
conflicts, then imports and re-renders inside a single backup session so
|
|
128
|
+
one `trellis rollback` restores originals and removes generated
|
|
129
|
+
`.agents/` content.
|
|
72
130
|
|
|
73
131
|
## Private / agent-specific capabilities
|
|
74
132
|
|
|
@@ -163,17 +221,19 @@ populates `~/.pi/agent/skills` on its own. (This corrects an earlier,
|
|
|
163
221
|
pre-P0 assumption that pi needed "no adapter" for skills/instructions;
|
|
164
222
|
that was written before pi's actual global discovery directory was
|
|
165
223
|
confirmed, when it wasn't yet known whether canonical skills would ever
|
|
166
|
-
reach it without one.) MCP
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
224
|
+
reach it without one.) MCP on pi ≥ 1.1.0 is native: the adapter merges
|
|
225
|
+
entries into `~/.pi/agent/mcp.json` — a `trellis mcp-gateway --agent pi`
|
|
226
|
+
stdio entry under gateway mode (or `mcp-runtime` under runtime delivery),
|
|
227
|
+
a single hub-URL entry under hub mode, direct entries otherwise — with
|
|
228
|
+
agent-owned OAuth servers written as bare `{url}` entries that
|
|
229
|
+
`pi mcp login` authorizes (an optional canonical `auth.client_name`
|
|
230
|
+
renders as `oauth.clientName` for providers that gate dynamic client
|
|
231
|
+
registration by name, e.g. Figma). On pi < 1.1.0 the legacy bridge
|
|
232
|
+
extension (`src/pi-bridge/`, symlinked into `~/.pi/agent/extensions/`) is
|
|
233
|
+
still planned instead; it is deprecated and scheduled for removal.
|
|
234
|
+
|
|
235
|
+
The legacy bridge symlink follows the currently executing Trellis
|
|
236
|
+
installation.
|
|
177
237
|
When switching from a checkout to a global package (or between installation
|
|
178
238
|
roots), sync can repair an outside-root link only if its target ends in
|
|
179
239
|
`dist/pi-bridge/bundle.js` and its bytes match the current bridge bundle.
|
|
@@ -211,12 +271,14 @@ to the code writing one entry that points at it.
|
|
|
211
271
|
- Every adapter writes ONE entry instead of N. This is most of the value:
|
|
212
272
|
adding a new backend server means editing wherever the hub's own config
|
|
213
273
|
lives (this project doesn't prescribe that either) and never touching
|
|
214
|
-
any of the
|
|
274
|
+
any of the six agents' configs or restarting them, if the hub supports
|
|
215
275
|
live reload (mcp-hub does, via SSE).
|
|
216
276
|
- The collision check against `known_host_injected` (docs/research.md
|
|
217
277
|
§"Codex — three hard constraints") shrinks to checking one name instead
|
|
218
278
|
of N, since there's nothing else locally defined to collide with.
|
|
219
|
-
- pi
|
|
279
|
+
- pi gets one hub-URL entry in its native mcp.json instead of N direct
|
|
280
|
+
entries (pre-1.1.0: the legacy bridge opens one HTTP client instead of N
|
|
281
|
+
stdio clients).
|
|
220
282
|
|
|
221
283
|
**What doesn't change:** the boundary with mirasim (docs/research.md §3)
|
|
222
284
|
is unaffected — `mcp.hub`, self-hosted or not, only ever carries the
|
|
@@ -253,11 +315,11 @@ there (not silently dropped) while still reaching every other agent.
|
|
|
253
315
|
|
|
254
316
|
**Real OAuth** (browser redirect, short-lived access token, refresh
|
|
255
317
|
token) was, for most of this project's life, deliberately not built:
|
|
256
|
-
all
|
|
318
|
+
all the native-config agents already have their own working flow —
|
|
257
319
|
Claude Code's `claude mcp add --client-id/--client-secret/--callback-port`,
|
|
258
320
|
Codex's `codex mcp login`/`logout` pair, Kiro's `oauth`/`oauthScopes`
|
|
259
|
-
fields
|
|
260
|
-
reach such a server at all.
|
|
321
|
+
fields, pi's `pi mcp login` (native since pi 1.1.0; the legacy bridge
|
|
322
|
+
could not reach such a server at all).
|
|
261
323
|
|
|
262
324
|
Gateway mode does not automatically take ownership of OAuth servers. Mark a
|
|
263
325
|
server explicitly with `auth: oauth` (or `trellis mcp set <name> --auth oauth`)
|
|
@@ -400,7 +462,7 @@ Trellis MCP Runtime
|
|
|
400
462
|
│ ├─ SkillProvider (read/search canonical skills)
|
|
401
463
|
│ ├─ RuntimeMemoryProvider
|
|
402
464
|
│ │ └─ CanonicalMemoryProvider (read-only canonical Markdown)
|
|
403
|
-
│ └─ StatusProvider (
|
|
465
|
+
│ └─ StatusProvider (read-only diagnostics)
|
|
404
466
|
└─ UpstreamProvider
|
|
405
467
|
└─ existing GatewayBackend / future RemoteBackend
|
|
406
468
|
```
|
|
@@ -542,26 +604,26 @@ development, not in CI, not for a "quick manual check." A bug in an adapter
|
|
|
542
604
|
that patches TOML in place is exactly the kind of thing that corrupts a
|
|
543
605
|
real config file if it's tested against one.
|
|
544
606
|
|
|
545
|
-
**Exception: pi.** This rule protects real
|
|
546
|
-
other
|
|
547
|
-
directories, in-place TOML/JSON edits).
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
607
|
+
**Exception: pi (bridge era, kept as history).** This rule protects real
|
|
608
|
+
state a person depends on — the other agents' adapters patch that state in
|
|
609
|
+
place (symlinks over real directories, in-place TOML/JSON edits). In the
|
|
610
|
+
bridge era pi's adapter never did: skills/instructions were the same
|
|
611
|
+
symlink-or-noop regardless of machine, and the MCP bridge (P4) was a
|
|
612
|
+
single already-symlinked extension file that read a separate,
|
|
613
|
+
Trellis-owned `servers.yaml` rather than writing into anything pi itself
|
|
614
|
+
depended on, so a temporary, narrowly-scoped `~/.trellis/mcp/servers.yaml`
|
|
615
|
+
plus a real `pi -p` run carried none of the corruption risk this section
|
|
616
|
+
exists to prevent. Since pi 1.1.0 the adapter merges
|
|
617
|
+
`~/.pi/agent/mcp.json` in place like every other adapter, so **this
|
|
618
|
+
exception no longer applies to MCP config** — real-machine pi verification
|
|
619
|
+
(the v0.14.0 managed migration, for example) follows the standard
|
|
620
|
+
discipline: backup, dry-run, then a scoped apply. The paragraph is kept
|
|
621
|
+
because the bridge extension still exists as the pre-1.1.0 fallback.
|
|
560
622
|
|
|
561
623
|
Verification happens against an isolated environment instead: a scratch
|
|
562
624
|
`$HOME` (or a container with one mounted) populated with synthetic
|
|
563
625
|
per-agent config that looks like the real thing but is expendable — created
|
|
564
|
-
fresh, asserted against, thrown away. `docs/implementation-plan.md`'s P1
|
|
626
|
+
fresh, asserted against, thrown away. `docs/archive/implementation-plan.md`'s P1
|
|
565
627
|
acceptance criteria already describes this shape ("point at a scratch
|
|
566
628
|
`$HOME`... run `trellis sync skills`... confirm zero findings"); this
|
|
567
629
|
section exists to make it a project-wide rule that every later phase's
|
package/docs/getting-started.md
CHANGED
|
@@ -496,8 +496,8 @@ Trellis resolves `CODEX_HOME` when set, otherwise `~/.codex`, and reads only
|
|
|
496
496
|
the Memory directory. `AGENTS.md`, `session_index.jsonl`, sessions,
|
|
497
497
|
credentials, and plugin state are never treated as memory.
|
|
498
498
|
|
|
499
|
-
**MCP servers** (claude-code, kiro, codex — not pi,
|
|
500
|
-
|
|
499
|
+
**MCP servers** (claude-code, kiro, codex, kimi-code, zcode — not pi, whose
|
|
500
|
+
mcp.json migrate-in is not implemented) migrate the same way, into
|
|
501
501
|
`~/.trellis/mcp/servers.yaml`:
|
|
502
502
|
|
|
503
503
|
```
|
|
@@ -821,6 +821,69 @@ automatically, so `trellis rollback` can undo the whole run later — see
|
|
|
821
821
|
[`trellis rollback`](#trellis-rollback--undoing-a-syncmcp-synconboard-run)
|
|
822
822
|
below.
|
|
823
823
|
|
|
824
|
+
## Workspace scope — per-project config in the repo
|
|
825
|
+
|
|
826
|
+
Everything above manages `~/.trellis`, one canonical source per machine.
|
|
827
|
+
A project can carry its own layer in the repo itself, under `.agents/` —
|
|
828
|
+
committable by design, shared with every teammate and agent that checks
|
|
829
|
+
it out:
|
|
830
|
+
|
|
831
|
+
```
|
|
832
|
+
$ cd your-repo
|
|
833
|
+
$ trellis init --workspace # scaffold .agents/ (fill-missing-only)
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
```
|
|
837
|
+
.agents/
|
|
838
|
+
├── config.json # { "version": 1, mcp.servers } — same schema
|
|
839
|
+
│ # as ~/.trellis/mcp/servers.yaml
|
|
840
|
+
├── AGENTS.md # workspace instructions
|
|
841
|
+
├── skills/<name>/SKILL.md
|
|
842
|
+
└── .trellis-rendered.json # Trellis's ownership manifest — commit it too
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
Edit those files directly, or use the CLI with `--workspace`
|
|
846
|
+
(`trellis mcp add <name> --workspace`, `trellis skill add <name> --from ... --workspace`).
|
|
847
|
+
Then, from anywhere inside the repo:
|
|
848
|
+
|
|
849
|
+
```
|
|
850
|
+
$ trellis sync # global layer + workspace layer together
|
|
851
|
+
$ trellis sync --global-only # global only, even inside a workspace
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
The workspace layer wins on ID conflicts with the global one (and
|
|
855
|
+
`enabled: false` in `config.json` tombstones a global server for this
|
|
856
|
+
project). Rendered artifacts — `.mcp.json`, `.codex/config.toml`,
|
|
857
|
+
`.pi/mcp.json`, skill copies under `.claude/skills/`, the marker-headed
|
|
858
|
+
root `AGENTS.md`, … — are meant to be **committed** alongside `.agents/`.
|
|
859
|
+
They contain only `${VAR}` references, never secret values, and
|
|
860
|
+
`.agents/config.json` itself refuses credential-shaped literals at load;
|
|
861
|
+
actual values live in each machine's local secret store and are
|
|
862
|
+
re-established per machine. CI keeps the committed artifacts honest:
|
|
863
|
+
|
|
864
|
+
```
|
|
865
|
+
$ trellis sync --check # zero writes; exit 1 naming any stale file
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
Already have hand-written project config (a `.mcp.json`, a
|
|
869
|
+
`.codex/config.toml`, a root `AGENTS.md`)? Absorb it instead of
|
|
870
|
+
rewriting by hand:
|
|
871
|
+
|
|
872
|
+
```
|
|
873
|
+
$ trellis migrate --workspace --dry-run # preview the classified plan
|
|
874
|
+
$ trellis migrate --workspace # import + re-render, one
|
|
875
|
+
# backup session — `trellis
|
|
876
|
+
# rollback` undoes the whole thing
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
The scanner inventories all six agents' project-level paths, skips
|
|
880
|
+
`*.local.*` files unread, extracts plaintext secrets into the global
|
|
881
|
+
secret store as `${VAR}` references (with a rotation advisory when the
|
|
882
|
+
literal was git-tracked), and refuses the run on unresolved conflicts —
|
|
883
|
+
pick a side with `--choose name=agentId`, or import an
|
|
884
|
+
identical-to-global entry as an intentional shadow with
|
|
885
|
+
`--dedup override`.
|
|
886
|
+
|
|
824
887
|
## `trellis mcp sync`
|
|
825
888
|
|
|
826
889
|
Distributes `~/.trellis/mcp/servers.yaml` to every **managed** agent's
|
|
@@ -915,9 +978,13 @@ stay direct while ordinary remote servers remain shared through the gateway.
|
|
|
915
978
|
|
|
916
979
|
### `trellis mcp auth <server-name>`
|
|
917
980
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
981
|
+
Authorization ownership is explicit per server (the full model is
|
|
982
|
+
[`mcp-authorization-ownership.md`](mcp-authorization-ownership.md)):
|
|
983
|
+
**agent-owned** OAuth servers (plain `auth: oauth`) are authorized by the
|
|
984
|
+
Agent's own login command — `claude mcp` / `codex mcp login` /
|
|
985
|
+
`pi mcp login <name>` — and Trellis never touches their tokens. **Trellis-owned**
|
|
986
|
+
servers (`auth: { kind: oauth, owner: trellis }`) connect through the
|
|
987
|
+
gateway/runtime on a credential Trellis holds, authorized once through:
|
|
921
988
|
|
|
922
989
|
```
|
|
923
990
|
$ trellis mcp auth notion-remote
|
|
@@ -929,17 +996,19 @@ This opens your browser, completes the flow, and stores the result 0600
|
|
|
929
996
|
under `~/.trellis/mcp/oauth/` — never in `servers.yaml`, so canonical
|
|
930
997
|
stays safe to read, diff, and commit.
|
|
931
998
|
|
|
932
|
-
Run it once per server
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
999
|
+
Run it once per Trellis-owned server. After that the gateway refreshes the
|
|
1000
|
+
token silently whenever it expires; it never opens a browser and never
|
|
1001
|
+
prompts, because it is spawned by an agent with no terminal attached.
|
|
1002
|
+
Re-running
|
|
936
1003
|
this command when the stored token is still valid does nothing (`--force`
|
|
937
1004
|
overrides); when it has expired but is renewable, it refreshes without a
|
|
938
|
-
browser.
|
|
1005
|
+
browser. `trellis mcp renew` does the same non-interactively for every
|
|
1006
|
+
Trellis-owned server that can be renewed without a browser.
|
|
939
1007
|
|
|
940
|
-
If a
|
|
941
|
-
one server and keeps serving every other — it does not fail to start.
|
|
942
|
-
|
|
1008
|
+
If a Trellis-owned OAuth server has no stored credential, the gateway skips
|
|
1009
|
+
that one server and keeps serving every other — it does not fail to start.
|
|
1010
|
+
Agent-owned servers in the same route are unaffected: the Agent's own client
|
|
1011
|
+
reports them as requiring its own authorization.
|
|
943
1012
|
|
|
944
1013
|
An Agent can call the read-only `trellis.mcp.status` Runtime tool to explain
|
|
945
1014
|
this partial state to the user. It reports unavailable or authorization-
|
|
@@ -1083,7 +1152,10 @@ $ trellis doctor
|
|
|
1083
1152
|
```
|
|
1084
1153
|
|
|
1085
1154
|
Read-only. Scans all six agents' current state and reports drift —
|
|
1086
|
-
mismatched skill content across agents, wrong-case skill files,
|
|
1155
|
+
mismatched skill content across agents, wrong-case skill files, OAuth
|
|
1156
|
+
credential health for Trellis-owned servers (the same read-only
|
|
1157
|
+
classification as `trellis mcp renew` and the `trellis.mcp.status` Runtime
|
|
1158
|
+
tool, so the three never disagree), and (with
|
|
1087
1159
|
`--probe-mcp`) whether each configured MCP server actually handshakes.
|
|
1088
1160
|
Safe to run any time; nothing here writes anything.
|
|
1089
1161
|
|
package/docs/mcp-oauth-matrix.md
CHANGED
|
@@ -41,7 +41,18 @@ per-provider list, is what Trellis commits to.
|
|
|
41
41
|
| Notion | DCR-open | `client_id` from DCR | Same | Medium |
|
|
42
42
|
| Linear | DCR-open | `client_id` from DCR | Same | Medium |
|
|
43
43
|
| Cloudflare | DCR-open | `client_id` from DCR | Same | Medium |
|
|
44
|
-
| Figma |
|
|
44
|
+
| Figma | DCR gated by client_name | `client_id` from DCR, issued only when the self-asserted `client_name` is on Figma's beta allowlist | Registration with an unknown name (e.g. `pi`, `Trellis`) refused with a bare 403; `Claude Code` succeeds — observed directly 2026-10-11 (oauth-client-name) | High |
|
|
45
|
+
|
|
46
|
+
**Figma, updated.** The row above supersedes an earlier classification of
|
|
47
|
+
Figma as plain Allowlist ("no self-service path"). What Figma actually gates
|
|
48
|
+
is the `client_name` a client asserts at registration, not possession of a
|
|
49
|
+
pre-issued `client_id`: the same registration endpoint answers 403 for
|
|
50
|
+
`pi`/`Trellis` and 200 for an allowlisted name, independent of User-Agent.
|
|
51
|
+
The working path is therefore agent-owned auth plus a declared canonical
|
|
52
|
+
`auth.client_name` (rendered into the agent's own registration, e.g. pi's
|
|
53
|
+
`oauth.clientName`). Trellis-hosted DCR hardcodes `client_name: "Trellis"`
|
|
54
|
+
(`src/lib/oauth/flow.ts`) and would be refused for Figma until Trellis's own
|
|
55
|
+
name is allowlisted or the field is wired through there too.
|
|
45
56
|
|
|
46
57
|
**On confidence.** "High" means the behavior was observed directly against the
|
|
47
58
|
live provider and the failure (or success) is reproducible from this
|
package/docs/overview.zh-CN.md
CHANGED
|
@@ -71,6 +71,22 @@ Trellis Runtime / Gateway
|
|
|
71
71
|
└── MCP Runtime ────── Kimi Code / ZCode / 其他 Runtime-first Agent
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
+
### 所有权边界(Ownership boundary)
|
|
75
|
+
|
|
76
|
+
- `~/.trellis/` 是 canonical source 和策略边界。
|
|
77
|
+
- 各 Agent 的原生目录是投影,不是独立的事实源。
|
|
78
|
+
- Gateway/Runtime 负责连接路由和 Provider 暴露,不接管 Agent 的私有会话。
|
|
79
|
+
- 凭证不进入 canonical YAML,在运行时解析。
|
|
80
|
+
- Runtime Provider 将 Memory、MCP 输出和任务记录视为不可信上下文。
|
|
81
|
+
|
|
82
|
+
## 投递模式(Delivery modes)
|
|
83
|
+
|
|
84
|
+
| 模式 | 含义 | 典型场景 |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| `native` | 将能力投影到 Agent 的原生配置 | 最大化原生兼容性 |
|
|
87
|
+
| `mcp` | 通过 Runtime MCP 边界消费 Trellis 能力 | Kimi Code 等 Runtime-first Agent |
|
|
88
|
+
| `both` | 过渡期同时保留 native 和 Runtime 投递 | 兼容性迁移 |
|
|
89
|
+
|
|
74
90
|
## 与相似产品的关系
|
|
75
91
|
|
|
76
92
|
| 产品/类别 | 主要解决的问题 | Trellis 的区别 |
|
|
@@ -79,6 +95,7 @@ Trellis Runtime / Gateway
|
|
|
79
95
|
| [MCP Router](https://github.com/mcp-router/mcp-router) | 桌面 MCP 管理、Workspace、Provider 和日志 | 可作为 Trellis 的导入源或上游;Trellis 自己维护 canonical MCP 状态 |
|
|
80
96
|
| [MetaMCP](https://github.com/metatool-ai/metamcp) / [mcp-hub](https://github.com/ravitemer/mcp-hub) | MCP 聚合和统一入口 | Trellis 额外负责不同 Agent 的 native 适配、生命周期和安全同步 |
|
|
81
97
|
| [OpenViking](https://github.com/volcengine/OpenViking) | Memory、资源和 Skill 的上下文数据库 | Trellis 可将其接入 Memory/Context Provider,作为底层上下文服务 |
|
|
98
|
+
| Agent 编排平台 | 启动 worker、调度任务、协调执行 | Trellis 目前只提供持久化任务交接记录和租约,不隐式远程执行 Agent;执行层是明确的未来方向 |
|
|
82
99
|
|
|
83
100
|
## 术语约定
|
|
84
101
|
|
package/docs/research.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
Surveyed 2026-09-11. This is why Trellis is a thin orchestration layer, not a
|
|
4
4
|
from-scratch rebuild of anything below.
|
|
5
5
|
|
|
6
|
+
> **Currency note (2026-10-11, doc governance):** this is a research/history
|
|
7
|
+
> document — sections are dated snapshots of what was true when surveyed, and
|
|
8
|
+
> some "decided not to build" / "future direction" passages have since been
|
|
9
|
+
> implemented (gateway/runtime, skills-over-MCP, pi native MCP). Where a
|
|
10
|
+
> section conflicts with [`architecture.md`](architecture.md), architecture.md
|
|
11
|
+
> is current. Inline markers flag the known-superseded spots.
|
|
12
|
+
|
|
6
13
|
## Rules / skills sync (crowded — don't rebuild)
|
|
7
14
|
|
|
8
15
|
| Project | Covers | Kiro | pi | MCP | Memory | Secrets |
|
|
@@ -50,7 +57,11 @@ specifies).
|
|
|
50
57
|
| [mcp-router](https://github.com/mcp-router/mcp-router) | — | Desktop app + CLI, Sustainable Use License | Already deployed in this environment; token-based, has a GUI. **First-hand incident**: its `MCPR_TOKEN` existed in three different values across `secrets.env`/`config.toml`/`kiro/mcp.json` simultaneously, one silently invalid — see below |
|
|
51
58
|
|
|
52
59
|
Decision: Trellis still does not implement aggregation/routing logic
|
|
53
|
-
itself.
|
|
60
|
+
itself. *(Superseded 2026-10: gateway mode and the Trellis MCP Runtime now
|
|
61
|
+
do exactly this in-process — see architecture.md "Gateway mode" and the
|
|
62
|
+
BuiltinRegistry/UpstreamProvider diagram; the hub-mode support described
|
|
63
|
+
below remains as the external-endpoint option.)* It generates native MCP
|
|
64
|
+
config for each agent directly — that's
|
|
54
65
|
what actually needed solving, since none of the above touch Kiro/pi/Codex's
|
|
55
66
|
TOML format. But it now natively *supports* routing every agent through a
|
|
56
67
|
single external endpoint instead of N direct definitions ("hub mode," see
|
|
@@ -68,6 +79,10 @@ before hub mode existed as a documented option.
|
|
|
68
79
|
|
|
69
80
|
### MCP Runtime / built-in capability direction — confirmed architecture
|
|
70
81
|
|
|
82
|
+
*(Implemented: SkillProvider, RuntimeMemoryProvider and StatusProvider ship
|
|
83
|
+
in v0.12–v0.14 exactly in this shape — this section is the pre-implementation
|
|
84
|
+
confirmation, kept as the design's origin.)*
|
|
85
|
+
|
|
71
86
|
The next abstraction is broader than a skill-only MCP server. MCP defines
|
|
72
87
|
tools, resources, and prompts with different control models, so a Trellis
|
|
73
88
|
runtime should host a registry of providers rather than make every new
|
|
@@ -93,6 +108,11 @@ scripts by default.
|
|
|
93
108
|
|
|
94
109
|
### Local Claude Code / pi dogfood — 2026-09-18
|
|
95
110
|
|
|
111
|
+
*(Bridge-era snapshot: "the packaged MCP bridge" below refers to the pi
|
|
112
|
+
bridge extension, retired as the default delivery by pi 1.1.0 native MCP in
|
|
113
|
+
v0.14.0. The findings about tool-surface size and route granularity are
|
|
114
|
+
still valid.)*
|
|
115
|
+
|
|
96
116
|
After an external, credential-minimized host snapshot, the managed set was
|
|
97
117
|
narrowed from all four agents to Claude Code and pi through `trellis manage
|
|
98
118
|
set`. Hashes of Codex and Kiro's relevant native state were identical before
|
|
@@ -245,12 +265,14 @@ Reverse-engineered directly from the installed binary
|
|
|
245
265
|
not supported"` — that era is why the bridge extension below exists.
|
|
246
266
|
- pi's capability surface is **extensions**: JS modules loaded via
|
|
247
267
|
`--extension`/discovery, with a real API (`createExtension`,
|
|
248
|
-
`registerTool`).
|
|
249
|
-
|
|
268
|
+
`registerTool`). *(Superseded as the default path: since pi 1.1.0, Trellis
|
|
269
|
+
writes pi's native `mcp.json` directly — trellis-pi-native-mcp-migration,
|
|
270
|
+
v0.14.0. The bridge extension remains only as the pre-1.1.0 fallback and
|
|
271
|
+
is scheduled for removal.)* Giving pi access to the same MCP servers
|
|
272
|
+
every other agent uses meant writing a bridge extension that spins up
|
|
250
273
|
`@modelcontextprotocol/sdk` stdio clients from `mcp.json` and registers
|
|
251
|
-
their tools through this API
|
|
252
|
-
|
|
253
|
-
[`src/adapters/pi/`](../src/adapters/pi).
|
|
274
|
+
their tools through this API — the one adapter in Trellis that is genuine
|
|
275
|
+
code, not config templating.
|
|
254
276
|
|
|
255
277
|
## Cross-machine / cloud sharing — surveyed 2026-09-15, future direction confirmed
|
|
256
278
|
|
package/docs/roadmap.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# Roadmap
|
|
2
2
|
|
|
3
|
+
*Current release: v0.14.1 (2026-10-11). This file tracks phase-level scope;
|
|
4
|
+
per-release detail lives in [`releases/`](releases/).*
|
|
5
|
+
|
|
3
6
|
Each phase must ship with a `trellis doctor` check that verifies its own
|
|
4
7
|
claim — no phase is "done" on the strength of a config file existing, only
|
|
5
8
|
on the strength of a passing verification against the real running agent.
|
|
6
9
|
|
|
7
|
-
See [`implementation-plan.md`](implementation-plan.md) for P1–P4 broken down
|
|
10
|
+
See [`archive/implementation-plan.md`](archive/implementation-plan.md) for P1–P4 broken down
|
|
8
11
|
to file/function level.
|
|
9
12
|
|
|
10
13
|
**P0 is done and archived** (`openspec/changes/archive/2026-09-12-trellis-doctor-p0/`;
|
|
@@ -21,7 +24,7 @@ had a much larger blast radius than "read-only" should mean.
|
|
|
21
24
|
|
|
22
25
|
This is the format every later phase uses: one `openspec/changes/<phase>/`
|
|
23
26
|
directory per phase, `openspec new change <name>` → tasks implemented →
|
|
24
|
-
`openspec archive <name>`. `implementation-plan.md`'s P0/P1 sections are
|
|
27
|
+
`openspec archive <name>`. `archive/implementation-plan.md`'s P0/P1 sections are
|
|
25
28
|
kept only as historical notes; don't edit them further.
|
|
26
29
|
|
|
27
30
|
**P1 is done and archived** (`openspec/changes/archive/2026-09-12-trellis-sync-p1/`;
|
|
@@ -933,7 +936,7 @@ tests passing.
|
|
|
933
936
|
| P1 | ✅ `trellis sync skills` / `trellis sync instructions` — symlink-based distribution to Claude Code, Codex, Kiro, and pi | P0 |
|
|
934
937
|
| P2 | ✅ `trellis mcp sync` — incremental, in-place adapters for Claude Code (JSON merge), Codex (TOML section patch), Kiro (JSON merge); collision check against known host-injected server names | P1 |
|
|
935
938
|
| P3 | ✅ `trellis secrets audit` — scans every adapter's output for literal credential patterns and unexpected env var names, fails non-zero on any hit | P2 |
|
|
936
|
-
| P4 | ✅ pi bridge extension — MCP tool registration via `registerTool`, sourced from the same `mcp/servers.yaml` | P2 |
|
|
939
|
+
| P4 | ✅ pi bridge extension — MCP tool registration via `registerTool`, sourced from the same `mcp/servers.yaml`. **Superseded as the default by v0.14.0** (pi ≥ 1.1.0 native MCP, trellis-pi-native-mcp-migration): the bridge is now the pre-1.1.0 fallback only, and `src/pi-bridge/` is scheduled for removal one release later | P2 |
|
|
937
940
|
| P5 | ✅ `@trellis/sdk` — read-only API over the canonical source, for third-party agents to consume without depending on the CLI | P1–P4 stable |
|
|
938
941
|
| P6 | ✅ Memory: document and wire the `server-memory` default; write the mem0/OpenMemory upgrade guide | P2 |
|
|
939
942
|
| P7 | ✅ Secrets/env management: shared `resolveSecretEnv` + `secrets.policy.yaml`'s `env_file`, pi bridge stops reading raw ambient env, `secrets audit` gains a `missing-env-value` check | P3, P4 |
|
|
@@ -957,9 +960,18 @@ tests passing.
|
|
|
957
960
|
|
|
958
961
|
| P25 | ✅ Onboard prompt TUI: replaces Trellis's hand-written raw-mode picker and ANSI redraw logic with `@clack/prompts`, preserving non-TTY fallbacks, `--json`, stream-injected tests, stderr-only interactive chrome, and compact agent summaries that show counts instead of enumerating skills. Full-screen TUI runtimes remain out of scope; onboarding stays visible in terminal scrollback | P22 |
|
|
959
962
|
| P26 | ✅ Fine-grained capability selection: item-level skill/MCP/memory selection from a serializable selection file or searchable TUI, per-agent MCP route overrides with direct/gateway/hub precedence, selected-memory sync without implicit native-memory import, and explicit unsupported-reader diagnostics | P17, P21, P22, P25 |
|
|
960
|
-
| P27 | 🚧 Trellis MCP Runtime phase 1 ✅: one provider registry and agent-facing MCP edge; SkillProvider and the read-only CanonicalMemoryProvider expose scoped progressive-disclosure tools/resources, runtime delivery supports native/mcp/both per agent, selected upstream tools mount through the existing GatewayBackend, and doctor checks runtime drift. Remaining: upstream
|
|
961
|
-
| P28 | 🚧 Kimi Code Runtime-first adapter: Kimi is recognized as a managed Agent, receives one deferred `trellis` Runtime entry in `~/.kimi-code/mcp.json`, and `trellis kimi` isolates native Skill discovery for Runtime-only delivery. The Runtime Skill is available through SkillProvider;
|
|
963
|
+
| P27 | 🚧 Trellis MCP Runtime phase 1 ✅: one provider registry and agent-facing MCP edge; SkillProvider and the read-only CanonicalMemoryProvider expose scoped progressive-disclosure tools/resources, runtime delivery supports native/mcp/both per agent, selected upstream tools mount through the existing GatewayBackend, upstream **resources** ship (v0.12.0), and doctor checks runtime drift. Remaining: upstream **prompts** backend, real pi/Kiro model smoke, and real Claude model smoke (Claude remains intentionally deferred) | P21, P25, P26 |
|
|
964
|
+
| P28 | 🚧 Kimi Code Runtime-first adapter: Kimi is recognized as a managed Agent, receives one deferred `trellis` Runtime entry in `~/.kimi-code/mcp.json`, and `trellis kimi` isolates native Skill discovery for Runtime-only delivery. The Runtime Skill is available through SkillProvider; upstream resources ship (v0.12.0). Remaining: real Kimi model-session smoke and upstream prompt consumption | P27 |
|
|
962
965
|
| P29 | ✅ ZCode Runtime-first adapter: `zcode` is a managed Agent with profile-aware static configuration (`~/.zcode/cli/config.json` for official profiles and `setting.json` for the local community CLI), a single owned Runtime MCP entry, scoped-Skill isolation, safe instruction/MCP migration, doctor/onboarding coverage, and public-CLI chat/delegation parsing for ZCode's `response`/`sessionId` stream envelope. Desktop-private runtime paths are never process-host entry points. | P27, P28 |
|
|
966
|
+
| P30 | ✅ Workspace scope: a second canonical layer in the repo itself, `<repo>/.agents/` (`config.json` reusing `servers.yaml`'s exact snake_case schema + validator, `AGENTS.md`, `skills/`), discovered by walking up from the cwd (`~/` never counts) and merged workspace-wins-by-ID with `enabled: false` tombstones. Delivery is layer-preserving — global content never re-renders into project files; workspace entries go to all six agents' project-level native paths, with skills *copied* (digest-drift-detected) for Claude/Kiro, native `.agents/skills/` reads for Codex/pi/Kimi, marker-headed root `AGENTS.md` for Codex/pi/Kimi + Kiro steering, and a zcode reverse-precedence warning (its MCP resolves user-first). Committable by design: `config.json` refuses credential-shaped literals at load, rendered artifacts carry only `${VAR}` references, and the committed `.agents/.trellis-rendered.json` ownership manifest is what lets a fresh clone or copied directory re-attach instead of conflict-guarding on its own artifacts. CLI: `init --workspace`, `sync` auto-include with `--check` as the CI freshness gate and `--global-only` as the escape hatch, `mcp add`/`skill add --workspace`, and `migrate --workspace` — a six-path scanner + seven-way classifier (create / already-managed / identical-to-global / skip-local / skip-unsupported / conflict / extract-secret) that refuses wholesale on unresolved conflicts, extracts plaintext secrets into the global store (git-tracked literals get a rotation advisory), seeds manifest ownership so the cascade render adopts rather than conflicts, and runs inside one backup session so a single `rollback` restores every original | P2, P24 |
|
|
967
|
+
|
|
968
|
+
**Shipped since P29 without a phase number** (detail in `docs/releases/`):
|
|
969
|
+
v0.13.0 — OAuth credential operability (`trellis mcp renew`, doctor OAuth
|
|
970
|
+
health, honest credential status in `trellis.mcp.status`, browser callback
|
|
971
|
+
page). v0.14.0 — pi native MCP delivery (pi ≥ 1.1.0 `mcp.json` writes,
|
|
972
|
+
bridge retirement in the same sync; supersedes P4's default path).
|
|
973
|
+
v0.14.1 — canonical `auth.client_name` for providers that gate OAuth dynamic
|
|
974
|
+
client registration by client name (Figma).
|
|
963
975
|
|
|
964
976
|
**Cross-machine / cloud sharing — confirmed future direction, not yet
|
|
965
977
|
scoped as a phase.** Surveyed 2026-09-15 (`docs/research.md`'s "Cross-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-trellis",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "A unified Code Agent Runtime for Skills, MCP, Memory, and shared instructions across Claude Code, Codex, Kiro, pi, Kimi Code, and ZCode.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Paul Leo",
|