agent-trellis 0.1.0 → 0.3.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/README.md +69 -17
- package/dist/adapters/claude-code.d.ts +5 -3
- package/dist/adapters/claude-code.js +27 -14
- package/dist/adapters/codex.d.ts +8 -4
- package/dist/adapters/codex.js +47 -16
- package/dist/adapters/jsonMcp.d.ts +16 -5
- package/dist/adapters/jsonMcp.js +38 -29
- package/dist/adapters/kiro.d.ts +5 -3
- package/dist/adapters/kiro.js +29 -16
- package/dist/adapters/mcpPlan.d.ts +11 -6
- package/dist/adapters/mcpPlan.js +40 -7
- package/dist/adapters/pi.d.ts +2 -1
- package/dist/adapters/pi.js +4 -4
- package/dist/adapters/symlinkPlan.d.ts +7 -3
- package/dist/adapters/symlinkPlan.js +42 -16
- package/dist/cli.js +161 -18
- package/dist/commands/init.js +11 -0
- package/dist/commands/mcp.d.ts +114 -7
- package/dist/commands/mcp.js +258 -17
- package/dist/commands/memory.d.ts +39 -0
- package/dist/commands/memory.js +78 -0
- package/dist/commands/migrate.d.ts +30 -4
- package/dist/commands/migrate.js +83 -16
- package/dist/commands/onboard.d.ts +52 -7
- package/dist/commands/onboard.js +318 -35
- package/dist/commands/rollback.d.ts +44 -0
- package/dist/commands/rollback.js +201 -0
- package/dist/commands/secretsAudit.d.ts +7 -0
- package/dist/commands/secretsAudit.js +14 -7
- package/dist/commands/skill.d.ts +51 -0
- package/dist/commands/skill.js +104 -0
- package/dist/commands/sync.d.ts +13 -0
- package/dist/commands/sync.js +31 -5
- package/dist/core/adapter.d.ts +28 -11
- package/dist/core/adapter.js +2 -2
- package/dist/core/canonical.d.ts +26 -1
- package/dist/core/canonical.js +103 -3
- package/dist/core/types.d.ts +29 -1
- package/dist/core/types.js +11 -2
- package/dist/lib/backup.d.ts +56 -0
- package/dist/lib/backup.js +98 -0
- package/dist/lib/deepEqual.d.ts +8 -0
- package/dist/lib/deepEqual.js +26 -0
- package/dist/lib/dirEquals.d.ts +9 -0
- package/dist/lib/dirEquals.js +15 -1
- package/dist/lib/installAgent.d.ts +26 -0
- package/dist/lib/installAgent.js +46 -0
- package/dist/lib/mcpMigrateRead.d.ts +69 -0
- package/dist/lib/mcpMigrateRead.js +188 -0
- package/dist/lib/mcpOwnership.d.ts +25 -0
- package/dist/lib/mcpOwnership.js +50 -0
- package/dist/lib/memoryGraph.d.ts +60 -0
- package/dist/lib/memoryGraph.js +101 -0
- package/dist/lib/realHomeSnapshot.d.ts +26 -0
- package/dist/lib/realHomeSnapshot.js +77 -0
- package/dist/lib/terminalPicker.d.ts +45 -0
- package/dist/lib/terminalPicker.js +193 -0
- package/dist/lib/tomlSection.d.ts +20 -6
- package/dist/lib/tomlSection.js +78 -12
- package/dist/pi-bridge/bundle.js +100 -51
- package/dist/pi-bridge/index.js +14 -2
- package/dist/probes/codex.js +10 -2
- package/docs/architecture.md +7 -4
- package/docs/getting-started.md +267 -33
- package/docs/roadmap.md +444 -0
- package/package.json +1 -1
- package/schema/servers.example.yaml +39 -2
package/docs/getting-started.md
CHANGED
|
@@ -16,39 +16,62 @@ $ trellis onboard
|
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
Runs `init`, detects which of Claude Code/Codex/Kiro/pi are on this machine,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- **
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
then resolves two independent choices before running `migrate`, `sync`,
|
|
20
|
+
`mcp sync`, and `secrets audit` — the whole onboarding path, no follow-up
|
|
21
|
+
commands to type by hand:
|
|
22
|
+
|
|
23
|
+
1. **Migration source** — read from, at most one, never written back to.
|
|
24
|
+
- **No agent has real content**: skipped — canonical starts from `init`'s
|
|
25
|
+
placeholder.
|
|
26
|
+
- **Exactly one agent has real content**: auto-selected, no prompt.
|
|
27
|
+
- **Two or more**: prompts you to choose (Up/Down or j/k, Enter to confirm,
|
|
28
|
+
on a real terminal that supports it — falls back to a numbered
|
|
29
|
+
type-a-digit prompt otherwise), or pass `--agent <id>` to skip the
|
|
30
|
+
prompt entirely.
|
|
31
|
+
2. **Managed set** — zero or more agents to actually write to. Always an
|
|
32
|
+
explicit choice: pass `--manage <ids>` (comma-separated, e.g. `--manage
|
|
33
|
+
pi,codex`) or `--manage none`, or answer the interactive checkbox prompt
|
|
34
|
+
(Space to toggle, Enter to confirm — same numbered fallback as above).
|
|
35
|
+
**The source is not included by default** — migrating from Claude Code
|
|
36
|
+
doesn't mean Trellis starts managing Claude Code too, unless you say so.
|
|
37
|
+
Selecting an agent that isn't installed yet is itself the authorization to
|
|
38
|
+
install it (one confirmation, then a real `npm install -g <package>`);
|
|
39
|
+
Kiro has no CLI package and is refused with its download URL instead.
|
|
27
40
|
|
|
28
41
|
```
|
|
29
|
-
$ trellis onboard --agent claude-code
|
|
30
|
-
Using claude-code as the migration
|
|
42
|
+
$ trellis onboard --agent claude-code --manage pi
|
|
43
|
+
Using claude-code as the migration source (--agent).
|
|
44
|
+
Managed agents: pi
|
|
31
45
|
|
|
32
46
|
migrate --from claude-code
|
|
33
47
|
[create] skill "my-skill" — will copy from /Users/you/.claude/skills/my-skill
|
|
34
48
|
...
|
|
35
49
|
|
|
36
50
|
sync
|
|
37
|
-
✅
|
|
51
|
+
✅ pi — 1 created, 0 removed, 0 conflict(s)
|
|
38
52
|
...
|
|
39
53
|
|
|
40
|
-
|
|
54
|
+
mcp sync
|
|
55
|
+
✅ pi — already in sync
|
|
56
|
+
|
|
57
|
+
secrets audit
|
|
58
|
+
✅ no findings — every present agent's real config and every declared env var passed all checks
|
|
41
59
|
```
|
|
42
60
|
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
No agent named `claude-code` appears in the `sync`/`mcp sync` output above —
|
|
62
|
+
it's present and was the migration source, but it isn't managed, so it's
|
|
63
|
+
never even probed as a sync target, not just left with zero items.
|
|
45
64
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
65
|
+
Add `--dry-run` to preview the entire chain — init/migrate/sync/mcp
|
|
66
|
+
sync, including what would be written to `~/.trellis/managed.yaml` — with
|
|
67
|
+
zero writes anywhere (secrets audit is always read-only, with or without
|
|
68
|
+
the flag).
|
|
69
|
+
|
|
70
|
+
**A managed agent's own real content still isn't overwritten.** If you
|
|
71
|
+
explicitly include the source in `--manage`, sync still never overwrites
|
|
72
|
+
its real files — see the conflict table below. Merging differing content
|
|
73
|
+
across multiple agents into one canonical result isn't built yet — see
|
|
74
|
+
[README's Status](../README.md#status).
|
|
52
75
|
|
|
53
76
|
The rest of this page is the same flow broken into its individual steps —
|
|
54
77
|
useful if you want more control over any one part, or just want to
|
|
@@ -114,32 +137,140 @@ Add `--dry-run` to see the plan without writing anything:
|
|
|
114
137
|
$ trellis migrate --from codex --dry-run
|
|
115
138
|
```
|
|
116
139
|
|
|
140
|
+
Add `--only skills`, `--only instructions`, or `--only mcp` to migrate
|
|
141
|
+
just one category — useful when you only want part of it brought in
|
|
142
|
+
right now. Omit it to migrate all three, exactly as above:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
$ trellis migrate --from codex --only instructions
|
|
146
|
+
```
|
|
147
|
+
|
|
117
148
|
**What each action means:**
|
|
118
149
|
|
|
119
150
|
| Action | Meaning |
|
|
120
151
|
|---|---|
|
|
121
152
|
| `create` | New to canonical source — copied in. |
|
|
122
|
-
| `already-migrated` | Canonical already has byte-identical content (safe re-run, nothing happens). |
|
|
153
|
+
| `already-migrated` | Canonical already has byte-identical (or, for MCP servers, structurally identical) content (safe re-run, nothing happens). |
|
|
123
154
|
| `conflict` | Canonical already has *different* real content — **left untouched**, resolve by hand. |
|
|
124
155
|
| `skip-symlink` | That agent's own copy is itself a symlink (already shared in from elsewhere) — nothing of that agent's own to import. |
|
|
125
156
|
| `skip-case-broken` | Found as `skill.md` instead of `SKILL.md` — fix the case on the source agent first. |
|
|
157
|
+
| `skip-unsupported` | MCP servers only — that agent's real definition can't be safely represented (see below); nothing was written for it. |
|
|
126
158
|
|
|
127
159
|
Migrate never overwrites a genuine conflict, and never scopes a migrated
|
|
128
|
-
skill to just the source agent — once in canonical, it's
|
|
129
|
-
agent by default (see `sync`, below). If migrate reports
|
|
130
|
-
the two files it names and decide by hand
|
|
131
|
-
canonical, then re-run.
|
|
160
|
+
skill (or MCP server) to just the source agent — once in canonical, it's
|
|
161
|
+
visible to every agent by default (see `sync`, below). If migrate reports
|
|
162
|
+
a `conflict`, open the two files/entries it names and decide by hand
|
|
163
|
+
which content should actually be canonical, then re-run.
|
|
164
|
+
|
|
165
|
+
**MCP servers** (claude-code, kiro, codex — not pi, which has no static
|
|
166
|
+
MCP config to read at all) migrate the same way, into
|
|
167
|
+
`~/.trellis/mcp/servers.yaml`:
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
$ trellis migrate --from claude-code --only mcp
|
|
171
|
+
migrate --from claude-code
|
|
172
|
+
[create] mcp server "gitlab" — will add to servers.yaml
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Two known fidelity limits, named rather than silently worked around:
|
|
176
|
+
|
|
177
|
+
- **Codex remote servers migrate when they only use `url` and
|
|
178
|
+
`bearer_token_env_var`** — the one shape this codebase has verified
|
|
179
|
+
against a real `codex` binary, and the only shape Trellis's own writer
|
|
180
|
+
ever produces for Codex. Codex's own config schema has no way to tell
|
|
181
|
+
`http` apart from `sse`, so a migrated remote server always comes back
|
|
182
|
+
as `http` — not a guess, that distinction was never stored in the
|
|
183
|
+
first place. A server using Codex's other header mechanisms
|
|
184
|
+
(`http_headers`/`env_http_headers`/`http_headers_helper` — real fields
|
|
185
|
+
this project has no verified shape for) is reported `skip-unsupported`
|
|
186
|
+
rather than guessed at; use `trellis mcp add` for that one server as a
|
|
187
|
+
workaround.
|
|
188
|
+
- **`headers` recovery depends on that agent's own real on-disk shape.**
|
|
189
|
+
claude-code/kiro read `headers` from the exact same JSON field Trellis
|
|
190
|
+
itself writes (`schema/servers.example.yaml`'s `figma` example) — if a
|
|
191
|
+
server was hand-authored with some other shape, it migrates whatever
|
|
192
|
+
is actually there, same as any other field.
|
|
132
193
|
|
|
133
194
|
## Starting from nothing
|
|
134
195
|
|
|
135
196
|
Skip migrate. Edit `~/.trellis/agents.md` and add skills under
|
|
136
|
-
`~/.trellis/skills/<name>/SKILL.md` directly
|
|
137
|
-
|
|
197
|
+
`~/.trellis/skills/<name>/SKILL.md` directly, or use
|
|
198
|
+
`trellis skill add` (below) instead of hand-editing. There's nothing else
|
|
199
|
+
to set up before moving on to `sync`.
|
|
200
|
+
|
|
201
|
+
The same applies to MCP servers — `~/.trellis/mcp/servers.yaml` can be
|
|
202
|
+
hand-authored the same way (see
|
|
203
|
+
[`schema/servers.example.yaml`](../schema/servers.example.yaml) for the
|
|
204
|
+
full shape), or use `trellis mcp add` (below). Either way, move on to
|
|
205
|
+
[`trellis mcp sync`](#trellis-mcp-sync) once you've added what you want.
|
|
206
|
+
|
|
207
|
+
## `trellis skill` / `trellis mcp` — canonical CRUD via the CLI
|
|
208
|
+
|
|
209
|
+
An alternative to hand-editing canonical files directly — useful for
|
|
210
|
+
scripting, or when you'd rather not open a text editor for a one-line
|
|
211
|
+
change. Both commands are canonical-side only: they never touch any
|
|
212
|
+
agent's native config (that stays `sync`/`mcp sync`'s job).
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
$ trellis skill list
|
|
216
|
+
my-skill — claude-code, codex, pi
|
|
217
|
+
|
|
218
|
+
$ trellis skill add my-other-skill --from ./some/local/dir
|
|
219
|
+
skill add my-other-skill
|
|
220
|
+
[create] will copy from ./some/local/dir
|
|
221
|
+
|
|
222
|
+
$ trellis skill remove my-other-skill
|
|
223
|
+
removed skill "my-other-skill" from canonical source.
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`skill add` refuses (no write) if the name already exists with different
|
|
227
|
+
content — same conflict posture as `migrate`, never silently overwritten.
|
|
228
|
+
`skill remove` deletes the canonical directory; the *next* `trellis sync`
|
|
229
|
+
then auto-removes the now-stale symlink on every agent that had it (skills
|
|
230
|
+
carry their own ownership marker — the symlink itself — so this
|
|
231
|
+
propagates automatically, unlike MCP servers below).
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
$ trellis mcp list
|
|
235
|
+
tanka (http) — codex, pi
|
|
236
|
+
env: TANKA_TOKEN (values never read/printed)
|
|
237
|
+
|
|
238
|
+
$ trellis mcp add local-server --transport stdio --command node --args server.js --env API_KEY
|
|
239
|
+
mcp add local-server
|
|
240
|
+
[create] will add to servers.yaml
|
|
241
|
+
|
|
242
|
+
$ trellis mcp remove local-server
|
|
243
|
+
removed MCP server "local-server" from canonical source.
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
`mcp add` takes `--transport stdio|http|sse`; stdio requires `--command`
|
|
247
|
+
(plus optional `--args a,b`, `--env NAME,...`, `--static-env k=v,...`),
|
|
248
|
+
http/sse require `--url` (plus optional `--headers k=v,...`, values
|
|
249
|
+
expected as `${VAR}` references, never literal secrets). Both accept
|
|
250
|
+
`--agents id,...` (scope) and `--enabled true|false`. Same no-overwrite
|
|
251
|
+
conflict posture as `skill add` — there is no `--force`.
|
|
252
|
+
|
|
253
|
+
`mcp remove` is **canonical-only** — it does not remove the server from
|
|
254
|
+
any agent that already has it from an earlier `mcp sync` (the same
|
|
255
|
+
no-automatic-removal gap `mcp sync` itself has — see
|
|
256
|
+
[README's Known limitations](../README.md#status)); remove it by hand on
|
|
257
|
+
each agent in the meantime.
|
|
258
|
+
|
|
259
|
+
`mcp list` never resolves or prints a secret value: `env` names are shown
|
|
260
|
+
as bare names (the actual value is never read from your shell), and
|
|
261
|
+
`static_env` values are shown in full since those were never secrets in
|
|
262
|
+
the first place (see `mcp sync`'s own explanation of `env` vs.
|
|
263
|
+
`static_env`, further below).
|
|
264
|
+
|
|
265
|
+
All four of `skill add`/`skill remove`/`mcp add`/`mcp remove` support
|
|
266
|
+
`--dry-run` and `--json`, same convention as every other command.
|
|
138
267
|
|
|
139
268
|
## `trellis sync`
|
|
140
269
|
|
|
141
|
-
Distributes canonical skills and instructions to every agent
|
|
142
|
-
|
|
270
|
+
Distributes canonical skills and instructions to every **managed** agent
|
|
271
|
+
(`~/.trellis/managed.yaml` — empty by default; `trellis onboard` writes it,
|
|
272
|
+
or edit it yourself). A present-but-unmanaged agent gets no report line at
|
|
273
|
+
all, not just zero items:
|
|
143
274
|
|
|
144
275
|
```
|
|
145
276
|
$ trellis sync
|
|
@@ -162,12 +293,18 @@ canonical, that's what `migrate` is for.
|
|
|
162
293
|
Run `trellis sync skills` or `trellis sync instructions` to distribute just
|
|
163
294
|
one half. Add `--dry-run` (in any position — `trellis sync --dry-run` and
|
|
164
295
|
`trellis sync skills --dry-run` both work) to preview the plan with zero
|
|
165
|
-
writes
|
|
296
|
+
writes (and, per the same rule, records nothing to back up — see
|
|
297
|
+
`trellis rollback` below).
|
|
298
|
+
|
|
299
|
+
Every create/repair/remove this actually performs is recorded first,
|
|
300
|
+
automatically, so `trellis rollback` can undo the whole run later — see
|
|
301
|
+
[`trellis rollback`](#trellis-rollback--undoing-a-syncmcp-synconboard-run)
|
|
302
|
+
below.
|
|
166
303
|
|
|
167
304
|
## `trellis mcp sync`
|
|
168
305
|
|
|
169
|
-
Distributes `~/.trellis/mcp/servers.yaml` to every
|
|
170
|
-
MCP config. See [`schema/servers.example.yaml`](../schema/servers.example.yaml)
|
|
306
|
+
Distributes `~/.trellis/mcp/servers.yaml` to every **managed** agent's
|
|
307
|
+
native MCP config — same restriction as `sync`, see above. See [`schema/servers.example.yaml`](../schema/servers.example.yaml)
|
|
171
308
|
for the full documented shape — server definitions, per-agent scoping,
|
|
172
309
|
known-host-injected collision avoidance, and hub mode.
|
|
173
310
|
|
|
@@ -180,6 +317,11 @@ does not remove it from any agent's native config yet (see
|
|
|
180
317
|
[README's Known limitations](../README.md#status)). Remove it by hand on
|
|
181
318
|
each agent in the meantime.
|
|
182
319
|
|
|
320
|
+
Every native-config file this rewrites in place is snapshotted first,
|
|
321
|
+
automatically — see
|
|
322
|
+
[`trellis rollback`](#trellis-rollback--undoing-a-syncmcp-synconboard-run)
|
|
323
|
+
below to undo a run that turned out to be wrong.
|
|
324
|
+
|
|
183
325
|
`env:` in `servers.yaml` lists variable **names** only, never literal
|
|
184
326
|
values — the real values come from wherever your shell/secret manager
|
|
185
327
|
already populates them. See
|
|
@@ -187,13 +329,61 @@ already populates them. See
|
|
|
187
329
|
for exactly how that resolution works for each agent, including the one
|
|
188
330
|
narrow exception (pi's bridge has to read a value into its own process).
|
|
189
331
|
|
|
332
|
+
Before writing any name-only `env` entry, `mcp sync` checks it actually
|
|
333
|
+
resolves — a name with no value anywhere `secrets audit` would also
|
|
334
|
+
check is refused as a conflict for that one server, not written and left
|
|
335
|
+
to silently break that server once the agent tries to use it. Every
|
|
336
|
+
other server, and every other agent, still syncs normally.
|
|
337
|
+
|
|
338
|
+
For a value that isn't a secret at all — an email address, an
|
|
339
|
+
environment tag — use `static_env` instead of `env`: written into the
|
|
340
|
+
agent's config verbatim, never treated as a name to resolve (still
|
|
341
|
+
scanned for an accidental real credential, same as every other literal
|
|
342
|
+
field). `enabled: false` keeps a server's definition in canonical
|
|
343
|
+
without writing it to any agent — for something you want configured but
|
|
344
|
+
not currently active anywhere; remove the line (or set it `true`) to
|
|
345
|
+
turn it back on everywhere at once. See
|
|
346
|
+
[`schema/servers.example.yaml`](../schema/servers.example.yaml) for both.
|
|
347
|
+
|
|
348
|
+
## `trellis memory sync`
|
|
349
|
+
|
|
350
|
+
Ingests `~/.trellis/memories/*.md` into the actual on-disk file
|
|
351
|
+
`@modelcontextprotocol/server-memory` reads at its own startup — closing
|
|
352
|
+
the gap between "memory entries exist in canonical" and "the running
|
|
353
|
+
memory server actually knows about them." Requires a `memory` server in
|
|
354
|
+
`servers.yaml` with `static_env.MEMORY_FILE_PATH` set explicitly (see
|
|
355
|
+
[`schema/servers.example.yaml`](../schema/servers.example.yaml)); without
|
|
356
|
+
one, this is a no-op, not an error.
|
|
357
|
+
|
|
358
|
+
```
|
|
359
|
+
$ trellis memory sync
|
|
360
|
+
memory sync — /Users/you/.trellis/memories/graph.jsonl
|
|
361
|
+
[create] "sprint-tasks" — will create a new entity
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Every entry Trellis creates is tagged internally so a later sync can
|
|
365
|
+
safely update or remove it; anything else already in that file — an
|
|
366
|
+
entity or relation an agent added itself while actually using the memory
|
|
367
|
+
server — is never touched. If a name collides with something already in
|
|
368
|
+
the graph that Trellis didn't create, the command refuses that one entry
|
|
369
|
+
(reported as a conflict) rather than overwriting it, same posture as
|
|
370
|
+
every other conflict in this project.
|
|
371
|
+
|
|
372
|
+
**Known limitation, named rather than silently worked around:** this only
|
|
373
|
+
ingests canonical's *own* `memories/*.md` files into the shared store —
|
|
374
|
+
it does not (yet) extract an agent's own already-accumulated memory
|
|
375
|
+
content (e.g. Claude Code's own per-project memory feature) back into
|
|
376
|
+
canonical. That extraction is a real, separate, still-open gap — see
|
|
377
|
+
`docs/roadmap.md`'s P15 entry.
|
|
378
|
+
|
|
190
379
|
## `trellis secrets audit`
|
|
191
380
|
|
|
192
381
|
```
|
|
193
382
|
$ trellis secrets audit
|
|
194
383
|
```
|
|
195
384
|
|
|
196
|
-
Scans every
|
|
385
|
+
Scans every **managed** agent's **real, on-disk** config (never canonical)
|
|
386
|
+
for — same restriction as `sync`, see above:
|
|
197
387
|
|
|
198
388
|
1. A literal value matching one of `secrets.policy.yaml`'s
|
|
199
389
|
`reject_patterns` (a credential-shaped string that should have been a
|
|
@@ -220,6 +410,50 @@ Safe to run any time; nothing here writes anything.
|
|
|
220
410
|
stdio MCP server (some reaching real external services) — not something a
|
|
221
411
|
"just check my config" command should do by default.
|
|
222
412
|
|
|
413
|
+
## `trellis rollback` — undoing a `sync`/`mcp sync`/`onboard` run
|
|
414
|
+
|
|
415
|
+
Every real write those three commands perform is recorded, before it
|
|
416
|
+
happens, to a structured run directory under `~/.trellis/backups/` — no
|
|
417
|
+
flag needed, this is always on for any run that actually writes
|
|
418
|
+
something. `--dry-run` never creates one, since nothing was written.
|
|
419
|
+
|
|
420
|
+
```
|
|
421
|
+
$ trellis rollback
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Omitting a run id targets the most recent run. Pass one explicitly to
|
|
425
|
+
undo an older run — see `trellis rollback --list` for what's available:
|
|
426
|
+
|
|
427
|
+
```
|
|
428
|
+
$ trellis rollback --list
|
|
429
|
+
2026-09-13T04-52-18-727Z-mcp-sync — mcp-sync, 3 operation(s), 2026-09-13T04:52:18.727Z
|
|
430
|
+
2026-09-13T04-44-56-967Z-sync — sync, 1 operation(s), 2026-09-13T04:44:56.967Z
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
For each recorded operation, rollback checks whether that path's
|
|
434
|
+
**current** state still matches what the run itself left behind:
|
|
435
|
+
|
|
436
|
+
| Current state vs. recorded | Result |
|
|
437
|
+
|---|---|
|
|
438
|
+
| Unchanged since the run | `restore` — the file's exact prior bytes, or the symlink's exact prior target, or removed if the run created it |
|
|
439
|
+
| Something else touched it since | `conflict` — reported, left untouched, never force-restored over |
|
|
440
|
+
|
|
441
|
+
One path's `conflict` never blocks any other path in the same rollback
|
|
442
|
+
from restoring. Exit code is non-zero if any `conflict` occurred. Add
|
|
443
|
+
`--dry-run` to preview the restore/conflict plan with zero writes, or
|
|
444
|
+
`--json` for machine-readable output.
|
|
445
|
+
|
|
446
|
+
`onboard` shares one backup run across its whole chained `sync`/`mcp
|
|
447
|
+
sync` stages — one `trellis rollback` undoes an entire `onboard`
|
|
448
|
+
invocation, not just its last stage. `migrate` is not covered: it only
|
|
449
|
+
ever creates a new canonical entry or refuses on conflict, never
|
|
450
|
+
overwrites existing canonical content, so there's nothing a snapshot
|
|
451
|
+
would add — undoing a migrate mistake is just deleting the newly
|
|
452
|
+
created file under `~/.trellis/skills/`.
|
|
453
|
+
|
|
454
|
+
`~/.trellis/backups/` has no automatic pruning — delete old run
|
|
455
|
+
directories by hand once you're done with them.
|
|
456
|
+
|
|
223
457
|
## Troubleshooting
|
|
224
458
|
|
|
225
459
|
- **A `conflict` I don't understand**: `migrate` and `sync` both name the
|