@msdavid/pi-distro 0.3.0 → 0.4.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/CHANGELOG.md +40 -0
- package/README.md +64 -4
- package/docs/authoring.md +87 -13
- package/extensions/catalogue.ts +58 -22
- package/extensions/deploy.ts +33 -6
- package/extensions/github.ts +40 -3
- package/extensions/index.ts +4 -1
- package/extensions/info.ts +25 -16
- package/extensions/pick.ts +25 -10
- package/extensions/resolve.ts +17 -3
- package/extensions/save.ts +78 -8
- package/extensions/show.ts +9 -3
- package/extensions/undeploy.ts +78 -41
- package/extensions/util.ts +81 -11
- package/package.json +1 -1
- package/skills/pi-distro/SKILL.md +135 -44
|
@@ -28,7 +28,59 @@ Never silently skip, silently overwrite, silently substitute, or silently choose
|
|
|
28
28
|
If a decision is ambiguous or the user is unsure, explain the tradeoffs and let
|
|
29
29
|
them choose. **The agent proposes; the user disposes.** Every other rule in this
|
|
30
30
|
skill (merge-don't-clobber, package-redundancy, version-aware deploy, the GitHub
|
|
31
|
-
trust gate) is a specific instance of this principle.
|
|
31
|
+
trust gate, the scope rule) is a specific instance of this principle.
|
|
32
|
+
|
|
33
|
+
## Scope model: local vs global
|
|
34
|
+
|
|
35
|
+
pi supports two install scopes, and pi-distro lets the user choose per component:
|
|
36
|
+
|
|
37
|
+
- **Project-local** (default) — writes to `./.pi/` (packages via `pi install -l` →
|
|
38
|
+
`./.pi/settings.json`; extensions/skills/prompts/themes into `./.pi/<type>/`; settings into
|
|
39
|
+
`./.pi/settings.json`; AGENTS.md at `./AGENTS.md`). Scoped to this project only. This is the
|
|
40
|
+
default philosophy — different projects get different harnesses.
|
|
41
|
+
- **Global** — writes to `~/.pi/agent/` (packages via `pi install` →
|
|
42
|
+
`~/.pi/agent/settings.json`; extensions/skills/prompts/themes into `~/.pi/agent/<type>/`;
|
|
43
|
+
settings into `~/.pi/agent/settings.json`; AGENTS.md at `~/.pi/agent/AGENTS.md`). Shared
|
|
44
|
+
across **every project and session on this machine**. Opt-in, never the default.
|
|
45
|
+
|
|
46
|
+
pi merges global and project-local (project-local shadows global on conflict).
|
|
47
|
+
|
|
48
|
+
### Per-type default scopes
|
|
49
|
+
|
|
50
|
+
| Component type | Default scope | Global allowed? |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| Packages | local | ✅ |
|
|
53
|
+
| Extensions | local | ✅ |
|
|
54
|
+
| Skills | local | ✅ |
|
|
55
|
+
| Prompts | local | ✅ |
|
|
56
|
+
| Themes | **global** | ✅ |
|
|
57
|
+
| settings.json merge | local | ⚠️ guarded (explicit confirm) |
|
|
58
|
+
| SYSTEM.md / APPEND_SYSTEM.md | local | ⚠️ double-confirm |
|
|
59
|
+
| AGENTS.md | local | ⚠️ guarded (explicit confirm) |
|
|
60
|
+
|
|
61
|
+
### Deployment-plan procedure
|
|
62
|
+
|
|
63
|
+
At the start of a `deploy` (and for the selected items in a `pick`), the kickoff includes a
|
|
64
|
+
**scope rule** with this procedure. Follow it exactly:
|
|
65
|
+
|
|
66
|
+
1. **Build a deployment plan** grouping every installable component by type, each with its
|
|
67
|
+
default scope (per the table above, or the author's `(global)` hint if the directives
|
|
68
|
+
mark one). Render it as markdown so the user sees the whole picture.
|
|
69
|
+
2. **Offer three presets** via `ctx.ui.select`:
|
|
70
|
+
- **(a) Accept defaults** — keep every component at its default scope. Recommended.
|
|
71
|
+
- **(b) All-global (where safe)** — flip every global-allowed component to global;
|
|
72
|
+
dangerous types (settings, SYSTEM.md, AGENTS.md) stay local with a surfaced warning.
|
|
73
|
+
- **(c) Customize** — walk items one at a time, offering `local` / `global` / `skip`
|
|
74
|
+
each (`ctx.ui.select` is single-select). Cancel on an item = skip that item.
|
|
75
|
+
3. **Scope-safety guard** — when a dangerous type's final scope is global, surface the blast
|
|
76
|
+
radius ("affects every project/session on this machine") and require explicit confirm.
|
|
77
|
+
For SYSTEM.md/APPEND_SYSTEM.md global, require a second confirm.
|
|
78
|
+
4. **Install/place at the chosen scope** — `pi install -l` (local) or `pi install` (global)
|
|
79
|
+
for packages; write files to `./.pi/...` (local) or `~/.pi/agent/...` (global).
|
|
80
|
+
5. **Provenance does not record scope.** At `undeploy`/`status` time, the extension detects
|
|
81
|
+
placement by checking both locations (`./.pi/...` and `~/.pi/agent/...`, plus `pi list`).
|
|
82
|
+
So note in your final report which components went global, so the user knows where to find
|
|
83
|
+
and remove them.
|
|
32
84
|
|
|
33
85
|
## `/pi-distro deploy` — Distro Deployment
|
|
34
86
|
|
|
@@ -47,7 +99,8 @@ cloned the repo, displayed a security warning + preview, and obtained the user's
|
|
|
47
99
|
explicit confirmation before sending the kickoff — so you can proceed normally.
|
|
48
100
|
The provenance `sourceCatalogue` will be `github:owner/repo[/subpath]`.
|
|
49
101
|
Bundled files for GitHub distros are located in a temp directory (`/tmp/`) — copy
|
|
50
|
-
them from there as usual
|
|
102
|
+
them from there as usual, then **remove the temporary clone** (the kickoff names the
|
|
103
|
+
exact `rm -rf` target) so repeated GitHub deploys don't accumulate clones in `/tmp`.
|
|
51
104
|
|
|
52
105
|
### Deployment steps
|
|
53
106
|
|
|
@@ -79,17 +132,20 @@ them from there as usual.
|
|
|
79
132
|
|
|
80
133
|
If the section already exists (re-deploy), replace only that delimited section.
|
|
81
134
|
|
|
82
|
-
3. **Install pi packages —
|
|
83
|
-
|
|
84
|
-
|
|
135
|
+
3. **Install pi packages — scope + redundancy/conflict detection.** If the directives
|
|
136
|
+
list pi packages to install, first run the **scope** flow (deployment-plan + preset from
|
|
137
|
+
the Scope model above) to decide local vs global per package, then run the
|
|
138
|
+
**redundancy/conflict** check, then install at the chosen scope — `pi install -l <package>`
|
|
139
|
+
for **project-local** or `pi install <package>` for **global** — but **only after
|
|
85
140
|
confirming with the user** AND after evaluating tool redundancy/conflicts:
|
|
86
141
|
|
|
87
|
-
**Do NOT pre-add packages to
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
settings
|
|
91
|
-
|
|
92
|
-
|
|
142
|
+
**Do NOT pre-add packages to `settings.json` by hand.** `pi install -l` (local) and
|
|
143
|
+
`pi install` (global) are the single mechanisms that register a package: each installs the
|
|
144
|
+
package AND appends the source to the corresponding settings file (`./.pi/settings.json` or
|
|
145
|
+
`~/.pi/agent/settings.json`) on success. If an install fails, nothing is added to settings
|
|
146
|
+
— so settings never contains a package that isn't actually installed. (This is why the
|
|
147
|
+
bundled `settings.json` does not list packages — they are registered by `pi install`, not
|
|
148
|
+
by merging a `packages` array.)
|
|
93
149
|
|
|
94
150
|
**Redundancy/conflict evaluation (do this BEFORE installing each package):** Some packages
|
|
95
151
|
may provide tools that overlap with already-active tools. This can be:
|
|
@@ -101,8 +157,9 @@ them from there as usual.
|
|
|
101
157
|
leaving the user with duplicate capability and a confusing tool set.
|
|
102
158
|
You (the agent) must **evaluate** this — it requires judgment, not just string matching.
|
|
103
159
|
Before installing each package:
|
|
104
|
-
1. Read the **already-active tools** and **
|
|
105
|
-
"Current project state" section, and run `pi list`
|
|
160
|
+
1. Read the **already-active tools**, **project packages**, and **global packages** from
|
|
161
|
+
the kickoff's "Current project state" section, and run `pi list` for a fresh view of
|
|
162
|
+
both local and global packages.
|
|
106
163
|
2. For each to-be-installed package, compare its stated purpose (from the directives)
|
|
107
164
|
against the already-active tools. Ask: *does this package do something an existing tool
|
|
108
165
|
already does?* Consider both exact name matches and semantic overlap.
|
|
@@ -110,17 +167,20 @@ them from there as usual.
|
|
|
110
167
|
a choice and explain the overlap:
|
|
111
168
|
- **(a) Skip** — the capability already exists; don't install the package. Note this
|
|
112
169
|
in the provenance/deployment report.
|
|
113
|
-
- **(b) Replace** —
|
|
114
|
-
`pi remove <
|
|
170
|
+
- **(b) Replace** — remove the overlapping package from wherever it lives
|
|
171
|
+
(`pi remove -l <overlapping-package>` if project-local, `pi remove <pkg>` if global),
|
|
172
|
+
then install the new one at the chosen scope (`pi install -l <new-package>` for local
|
|
173
|
+
or `pi install <new-package>` for global).
|
|
115
174
|
- **(c) Keep both** — install it anyway. Use this when the user prefers the new tool,
|
|
116
175
|
or when the two tools serve subtly different purposes despite surface similarity.
|
|
117
176
|
- **(d) Cancel** — don't install anything.
|
|
118
177
|
4. Only proceed with the user's chosen option.
|
|
119
178
|
|
|
120
|
-
4. **Create hooks / extensions / prompts / skills.** If the directives instruct creating
|
|
121
|
-
|
|
122
|
-
using the bundled source files or the
|
|
123
|
-
merge-don't-clobber rule
|
|
179
|
+
4. **Create hooks / extensions / prompts / skills / themes.** If the directives instruct creating
|
|
180
|
+
these, place them at the **chosen scope**: `./.pi/<type>/` (local) or `~/.pi/agent/<type>/`
|
|
181
|
+
(global) — themes default to global. Create them using the bundled source files or the
|
|
182
|
+
directives' instructions. Apply the same merge-don't-clobber rule (at whichever target
|
|
183
|
+
path) for any that already exist.
|
|
124
184
|
|
|
125
185
|
5. **Write/update provenance.** When the deployment is complete, write (or update)
|
|
126
186
|
`./.pi/harness.md` in the project directory. The provenance file is itself a valid
|
|
@@ -201,21 +261,27 @@ your reference. Follow the selection procedure in the kickoff exactly:
|
|
|
201
261
|
|
|
202
262
|
1. **Walk the user through each category, one at a time.** Use `ctx.ui.select`/`ctx.ui.confirm`
|
|
203
263
|
to let them pick which items to apply. Present each item with its one-line purpose (from
|
|
204
|
-
the directives)
|
|
264
|
+
the directives) and its author scope hint (`[local]`/`[global]`). Let them select any
|
|
265
|
+
subset — including none (skip the category).
|
|
205
266
|
2. **Surface dependencies.** As the user selects, evaluate cross-component dependencies and
|
|
206
267
|
warn about them before applying. Example: if they pick an extension that references a
|
|
207
268
|
theme provided by a package they skipped, point that out and ask whether to also install
|
|
208
269
|
the package or skip the extension. Reason about the dependencies from the directives
|
|
209
270
|
prose — this is a judgment task. Never silently install a dependency the user didn't pick.
|
|
210
|
-
3. **
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
271
|
+
3. **Choose scope (local vs global).** For the selected components, run the deployment-plan
|
|
272
|
+
+ preset flow from the Scope model above (accept-defaults / all-global-where-safe /
|
|
273
|
+
customize). The plan is built from only the selected components. Apply the scope-safety
|
|
274
|
+
guard for dangerous types.
|
|
275
|
+
4. **Apply only the selected components** at the chosen scope with the same rules as a full
|
|
276
|
+
deploy: merge-don't-clobber (at whichever target path), package-redundancy check,
|
|
277
|
+
`pi install -l` (local) or `pi install` (global) for packages (after confirming),
|
|
278
|
+
copy/merge for files (overwrite / keep theirs / merge).
|
|
279
|
+
5. **Do NOT write standard provenance.** A partial deploy is a custom config, not "this
|
|
214
280
|
distro was applied." Do not write `appliedHarness`/`appliedVersion` provenance. Instead,
|
|
215
281
|
after applying, suggest the next step: "This is a custom configuration. Run
|
|
216
282
|
`/pi-distro save` to snapshot it as your own reusable distro" (which writes clean
|
|
217
283
|
provenance for the saved distro).
|
|
218
|
-
|
|
284
|
+
6. **Recommend a restart** if any packages or extensions were installed.
|
|
219
285
|
|
|
220
286
|
The natural loop is: `/pi-distro pick <distro-A>` → `/pi-distro pick <distro-B>` →
|
|
221
287
|
`/pi-distro save` (snapshot the combined result as a new distro). This is how users build
|
|
@@ -236,19 +302,29 @@ directives against the *current* project state and let the user decide what to r
|
|
|
236
302
|
|
|
237
303
|
Follow the removal procedure in the kickoff exactly:
|
|
238
304
|
|
|
239
|
-
1. **Walk the user through each removal category, one at a time
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
- **(
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
305
|
+
1. **Walk the user through each removal category, one at a time.** A distro may have
|
|
306
|
+
placed components at EITHER scope — the kickoff reports each package's placement
|
|
307
|
+
(`[local]`, `[global]`, `[both]`) by checking both `./.pi/...` and `~/.pi/agent/...`, plus
|
|
308
|
+
`pi list`. Remove from wherever it actually lives:
|
|
309
|
+
- **(a) Packages** — for each distro package still installed, remove it from where it
|
|
310
|
+
lives: `pi remove -l <pkg>` for `[local]`, `pi remove <pkg>` for `[global]` (warn: global
|
|
311
|
+
removal affects EVERY project on this machine — get explicit confirm), and BOTH
|
|
312
|
+
commands for `[both]`. Ask per package — the user may want to keep some. Warn if
|
|
313
|
+
removing a package that other components depend on.
|
|
314
|
+
- **(b) Bundled files** — for each file the distro placed, check for it at BOTH
|
|
315
|
+
`./<path>` (local) and `~/.pi/agent/<equivalent>` (global). If it exists, **show the
|
|
316
|
+
user the file (or a summary) before removing** — they may have customized it. Offer:
|
|
317
|
+
remove / keep, per location. Never silently delete. For `settings.json` (local at
|
|
318
|
+
`./.pi/settings.json`, global at `~/.pi/agent/settings.json`), offer to remove specific
|
|
319
|
+
keys the distro merged, not the whole file. Warn that global settings removal affects
|
|
320
|
+
every project.
|
|
321
|
+
- **(c) AGENTS.md delimited section** — the `<!-- pi-distro: <name> -->` ...
|
|
322
|
+
`<!-- /pi-distro: <name> -->` block may exist at `./AGENTS.md` (local) and/or
|
|
323
|
+
`~/.pi/agent/AGENTS.md` (global). Offer to remove it from each location it was found.
|
|
324
|
+
Warn that removing the global one affects every session. Leave any non-distro content.
|
|
325
|
+
- **(d) Extensions / skills / prompts / themes** — if described in the directives, check
|
|
326
|
+
for them in BOTH `./.pi/<type>/` (local) and `~/.pi/agent/<type>/` (global). Offer to
|
|
327
|
+
remove each (show before delete), per location.
|
|
252
328
|
2. **Remove provenance last** — only after the user confirms the component removals, remove
|
|
253
329
|
`./.pi/harness.md`. Confirm before deleting.
|
|
254
330
|
3. **Report and recommend a restart** — summarise what was removed vs. kept. Tell the user to
|
|
@@ -264,16 +340,18 @@ skip, delete, or strip. The user decides; you execute their choices.
|
|
|
264
340
|
|
|
265
341
|
When you receive a draft request from the `save` command, it contains a live-config
|
|
266
342
|
snapshot of the current project: the system prompt options (tools, skills, context
|
|
267
|
-
files, guidelines),
|
|
343
|
+
files, guidelines), the raw contents of **every project-local config file** found
|
|
268
344
|
under `./` (root `AGENTS.md`/`CLAUDE.md` variants), `./.pi/` (recursively — `settings.json`,
|
|
269
345
|
`SYSTEM.md`, `APPEND_SYSTEM.md`, `extensions/`, `skills/`, `prompts/`, `themes/`, and any
|
|
270
346
|
per-extension/skill config files like `.pi/<name>.json`), `./.crew/{agents,teams,workflows}/`
|
|
271
347
|
(pi-crew project-local authored definitions — NOT the runtime state subdirs), and
|
|
272
|
-
`./.agents/skills/` (project root only).
|
|
273
|
-
`
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
348
|
+
`./.agents/skills/` (project root only). **It also captures global (user-level) config**
|
|
349
|
+
from `~/.pi/agent/` (`settings.json`, `AGENTS.md`, `extensions/`, `themes/`, `skills/`,
|
|
350
|
+
`prompts/`) and globally-installed packages — these are marked `(global)` in the snapshot so
|
|
351
|
+
you can reproduce them at the global scope in the saved distro. Data/runtime dirs and the
|
|
352
|
+
provenance file `./.pi/harness.md` are excluded. Ancestor (parent-dir) `AGENTS.md` /
|
|
353
|
+
`.agents/skills/` appear only in the context-files list as informational — they are out of
|
|
354
|
+
scope and must NOT be bundled.
|
|
277
355
|
|
|
278
356
|
### Authoring steps
|
|
279
357
|
|
|
@@ -288,6 +366,19 @@ be bundled.
|
|
|
288
366
|
`version` (semver). Optionally `author` and `tags`.
|
|
289
367
|
- **Directives body**: include sections for bundled files, pi packages to install,
|
|
290
368
|
hooks/extensions, context, and skills/prompts — mirroring the live config.
|
|
369
|
+
- **Scope (local vs global)**: the snapshot separates **project-local** from **global**
|
|
370
|
+
(marked `(global)`, captured from `~/.pi/agent/`). Reproduce each component at the scope
|
|
371
|
+
it was captured at:
|
|
372
|
+
- A **global package** → list it in `## pi packages to install` with the `(global)`
|
|
373
|
+
marker suffix. A **project-local package** → no marker (default local).
|
|
374
|
+
- A **global bundled file** → copy into `files/` as usual, AND add a `## Global
|
|
375
|
+
deployment notes` section listing which file targets should be placed globally
|
|
376
|
+
(e.g. `.pi/extensions/foo.ts` → deploy globally to `~/.pi/agent/extensions/foo.ts`).
|
|
377
|
+
- Global `settings.json` / `SYSTEM.md` / `AGENTS.md` → note in `## Global deployment
|
|
378
|
+
notes` that they target `~/.pi/agent/...`, so the deploy-time scope-safety guard
|
|
379
|
+
surfaces the blast radius.
|
|
380
|
+
The user's deploy-time preset still governs the final scope — these markers/notes are
|
|
381
|
+
the author-suggested defaults.
|
|
291
382
|
|
|
292
383
|
3. **Propose & confirm.** Present the proposed `name`, `title`, `description`, and the full
|
|
293
384
|
draft to the user. Ask for confirmation or edits. Do not proceed until the user
|