@msdavid/pi-distro 0.2.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 +54 -0
- package/LICENSE +21 -0
- package/README.md +394 -0
- package/docs/authoring.md +238 -0
- package/docs/preview.png +0 -0
- package/docs/preview.svg +58 -0
- package/extensions/catalogue.ts +221 -0
- package/extensions/deploy.ts +141 -0
- package/extensions/frontmatter.ts +158 -0
- package/extensions/github.ts +110 -0
- package/extensions/index.ts +86 -0
- package/extensions/info.ts +133 -0
- package/extensions/pick.ts +132 -0
- package/extensions/resolve.ts +70 -0
- package/extensions/save.ts +217 -0
- package/extensions/show.ts +96 -0
- package/extensions/undeploy.ts +124 -0
- package/extensions/update.ts +109 -0
- package/extensions/util.ts +44 -0
- package/harnesses/minimal/README.md +21 -0
- package/harnesses/minimal/files/AGENTS.md +20 -0
- package/harnesses/minimal/files/settings.json +4 -0
- package/harnesses/minimal/harness.md +24 -0
- package/harnesses/pi-distro-one/README.md +50 -0
- package/harnesses/pi-distro-one/files/.pi/extensions/claude-statusline.ts +220 -0
- package/harnesses/pi-distro-one/files/AGENTS.md +166 -0
- package/harnesses/pi-distro-one/files/settings.json +9 -0
- package/harnesses/pi-distro-one/harness.md +79 -0
- package/harnesses/web-fullstack/README.md +25 -0
- package/harnesses/web-fullstack/files/.pi/prompts/review.md +12 -0
- package/harnesses/web-fullstack/files/AGENTS.md +37 -0
- package/harnesses/web-fullstack/files/settings.json +11 -0
- package/harnesses/web-fullstack/harness.md +40 -0
- package/package.json +65 -0
- package/skills/pi-distro/SKILL.md +359 -0
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@msdavid/pi-distro",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Reusable, composable configurations for the pi coding agent — seed distros, project snapshots, and GitHub sharing with version-aware updates.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "msdavid",
|
|
8
|
+
"homepage": "https://github.com/msdavid/pi-distro#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/msdavid/pi-distro.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/msdavid/pi-distro/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"pi-package",
|
|
18
|
+
"pi",
|
|
19
|
+
"coding-agent",
|
|
20
|
+
"configuration",
|
|
21
|
+
"distro",
|
|
22
|
+
"developer-tools"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=22.19.0"
|
|
26
|
+
},
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"files": [
|
|
29
|
+
"extensions",
|
|
30
|
+
"skills",
|
|
31
|
+
"harnesses",
|
|
32
|
+
"README.md",
|
|
33
|
+
"docs",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"CHANGELOG.md"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"pi": {
|
|
41
|
+
"extensions": ["./extensions"],
|
|
42
|
+
"skills": ["./skills"],
|
|
43
|
+
"image": "https://raw.githubusercontent.com/msdavid/pi-distro/main/docs/preview.png"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"test": "node --import tsx --test tests/*.test.ts"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@earendil-works/pi-ai": "*",
|
|
51
|
+
"@earendil-works/pi-agent-core": "*",
|
|
52
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
53
|
+
"@earendil-works/pi-tui": "*",
|
|
54
|
+
"typebox": "*"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@earendil-works/pi-ai": "^0.80.0",
|
|
58
|
+
"@earendil-works/pi-coding-agent": "^0.80.0",
|
|
59
|
+
"@earendil-works/pi-tui": "^0.80.0",
|
|
60
|
+
"@types/node": "^24.0.0",
|
|
61
|
+
"tsx": "^4.23.0",
|
|
62
|
+
"typebox": "^1.1.24",
|
|
63
|
+
"typescript": "^5.0.0"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pi-distro
|
|
3
|
+
description: "Manages pi distros — reusable, composable project configurations. Use when deploying a distro (/pi-distro deploy), saving the current project config as a distro (/pi-distro save), listing/showing/removing distros, or checking distro status. Triggers on: distro, save my config, deploy a distro, set up a distro."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pi-distro Skill
|
|
7
|
+
|
|
8
|
+
This skill guides the agent through the interactive phases of the pi-distro
|
|
9
|
+
extension: deploying a distro (`/pi-distro deploy`) and saving a live project
|
|
10
|
+
configuration as a distro (`/pi-distro save`). The extension command handles
|
|
11
|
+
catalogue reading, UI selectors, and kickoff-message injection; this skill provides
|
|
12
|
+
the agent-side guidance for those non-deterministic, collaborative flows.
|
|
13
|
+
|
|
14
|
+
## Governing principle: the user is in the loop for every decision
|
|
15
|
+
|
|
16
|
+
pi-distro is a **collaborative, agent-driven** tool. The agent never makes a
|
|
17
|
+
state-changing decision for the user. Before overwriting a file, installing a
|
|
18
|
+
package, skipping a step, replacing a tool, applying an upgrade, or resolving any
|
|
19
|
+
conflict (merge, redundancy, version downgrade, same-version, etc.), the agent
|
|
20
|
+
must:
|
|
21
|
+
|
|
22
|
+
1. **Surface** the decision clearly — what it's about to do, and why.
|
|
23
|
+
2. **Present** the available options (skip / replace / keep theirs / keep both /
|
|
24
|
+
cancel, as applicable).
|
|
25
|
+
3. **Wait** for the user's explicit choice. Never proceed on assumption.
|
|
26
|
+
|
|
27
|
+
Never silently skip, silently overwrite, silently substitute, or silently choose.
|
|
28
|
+
If a decision is ambiguous or the user is unsure, explain the tradeoffs and let
|
|
29
|
+
them choose. **The agent proposes; the user disposes.** Every other rule in this
|
|
30
|
+
skill (merge-don't-clobber, package-redundancy, version-aware deploy, the GitHub
|
|
31
|
+
trust gate) is a specific instance of this principle.
|
|
32
|
+
|
|
33
|
+
## `/pi-distro deploy` — Distro Deployment
|
|
34
|
+
|
|
35
|
+
When you receive a kickoff message from the `deploy` command, it contains:
|
|
36
|
+
|
|
37
|
+
- The full `harness.md` body (directives) for the selected distro.
|
|
38
|
+
- A manifest of bundled files (source path → target path) and the absolute path of
|
|
39
|
+
the distro `files/` directory on disk.
|
|
40
|
+
- The merge-don't-clobber rule.
|
|
41
|
+
- An instruction to write/update provenance.
|
|
42
|
+
|
|
43
|
+
The distro may come from the local catalogue (seed or user-saved) or from GitHub
|
|
44
|
+
(`/pi-distro deploy owner/repo`). For GitHub distros, the extension has already
|
|
45
|
+
cloned the repo, displayed a security warning + preview, and obtained the user's
|
|
46
|
+
explicit confirmation before sending the kickoff — so you can proceed normally.
|
|
47
|
+
The provenance `sourceCatalogue` will be `github:owner/repo[/subpath]`.
|
|
48
|
+
Bundled files for GitHub distros are located in a temp directory (`/tmp/`) — copy
|
|
49
|
+
them from there as usual.
|
|
50
|
+
|
|
51
|
+
### Deployment steps
|
|
52
|
+
|
|
53
|
+
1. **Read the directives.** The `harness.md` body tells you what to set up — bundled
|
|
54
|
+
files, pi packages to install, hooks/extensions to create, context to write, and
|
|
55
|
+
skills/prompts to configure. Follow those directives.
|
|
56
|
+
|
|
57
|
+
2. **Deploy bundled files with merge-don't-clobber.** For every bundled file in the
|
|
58
|
+
manifest that maps to a target path in the project:
|
|
59
|
+
|
|
60
|
+
- If the target file does **not** exist, copy it verbatim from the distro `files/`
|
|
61
|
+
directory.
|
|
62
|
+
- If the target file **already exists**, do **NOT** overwrite it silently. Instead:
|
|
63
|
+
- Read both the existing file and the bundled source.
|
|
64
|
+
- Show the user a diff (or summary of differences).
|
|
65
|
+
- Ask the user whether to **overwrite**, **keep theirs**, or **merge**.
|
|
66
|
+
- For **JSON files** (e.g. `settings.json`): if the user chooses merge, merge
|
|
67
|
+
field-by-field — combine keys from both objects, with the bundled values applied
|
|
68
|
+
on top but respecting existing user customisations where the user prefers to keep
|
|
69
|
+
them. Never silently destroy a key the user added.
|
|
70
|
+
- For **AGENTS.md**: never replace. Append the bundled content under a clearly
|
|
71
|
+
delimited section, e.g.:
|
|
72
|
+
|
|
73
|
+
```markdown
|
|
74
|
+
<!-- pi-distro: <distro-name> -->
|
|
75
|
+
...bundled AGENTS.md content...
|
|
76
|
+
<!-- /pi-distro: <distro-name> -->
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If the section already exists (re-deploy), replace only that delimited section.
|
|
80
|
+
|
|
81
|
+
3. **Install pi packages — with redundancy/conflict detection.** If the directives list pi packages to
|
|
82
|
+
install, run `pi install -l <package>` for each one — the `-l` flag installs
|
|
83
|
+
**project-locally** (writes to `./.pi/settings.json`, not global) — but **only after
|
|
84
|
+
confirming with the user** AND after evaluating tool redundancy/conflicts:
|
|
85
|
+
|
|
86
|
+
**Do NOT pre-add packages to `./.pi/settings.json` by hand.** `pi install -l` is the single
|
|
87
|
+
mechanism that registers a package: it installs the package AND appends the source to
|
|
88
|
+
`./.pi/settings.json` on success. If an install fails, nothing is added to settings — so
|
|
89
|
+
settings never contains a package that isn't actually installed. (This is why the bundled
|
|
90
|
+
`settings.json` does not list packages — they are registered by `pi install -l`, not by
|
|
91
|
+
merging a `packages` array.)
|
|
92
|
+
|
|
93
|
+
**Redundancy/conflict evaluation (do this BEFORE installing each package):** Some packages
|
|
94
|
+
may provide tools that overlap with already-active tools. This can be:
|
|
95
|
+
- An **exact name collision** — two tools with the same name. pi handles these by load
|
|
96
|
+
order (project-local tools shadow global ones; the conflict is a **non-fatal diagnostic**,
|
|
97
|
+
not a fatal error — pi still starts, but the shadowed tool is unavailable).
|
|
98
|
+
- **Semantic redundancy** — different tool names, but doing very similar things (e.g. two
|
|
99
|
+
web-search tools, two browser-automation tools, two todo-list tools). These both load,
|
|
100
|
+
leaving the user with duplicate capability and a confusing tool set.
|
|
101
|
+
You (the agent) must **evaluate** this — it requires judgment, not just string matching.
|
|
102
|
+
Before installing each package:
|
|
103
|
+
1. Read the **already-active tools** and **project packages** from the kickoff's
|
|
104
|
+
"Current project state" section, and run `pi list` to see globally-installed packages.
|
|
105
|
+
2. For each to-be-installed package, compare its stated purpose (from the directives)
|
|
106
|
+
against the already-active tools. Ask: *does this package do something an existing tool
|
|
107
|
+
already does?* Consider both exact name matches and semantic overlap.
|
|
108
|
+
3. If redundancy or a conflict is detected, do **NOT** install blindly — present the user
|
|
109
|
+
a choice and explain the overlap:
|
|
110
|
+
- **(a) Skip** — the capability already exists; don't install the package. Note this
|
|
111
|
+
in the provenance/deployment report.
|
|
112
|
+
- **(b) Replace** — `pi remove -l <overlapping-package>` (or remove it globally with
|
|
113
|
+
`pi remove <pkg>` if that's where it lives), then `pi install -l <new-package>`.
|
|
114
|
+
- **(c) Keep both** — install it anyway. Use this when the user prefers the new tool,
|
|
115
|
+
or when the two tools serve subtly different purposes despite surface similarity.
|
|
116
|
+
- **(d) Cancel** — don't install anything.
|
|
117
|
+
4. Only proceed with the user's chosen option.
|
|
118
|
+
|
|
119
|
+
4. **Create hooks / extensions / prompts / skills.** If the directives instruct creating
|
|
120
|
+
files under `./.pi/extensions/`, `./.pi/prompts/`, or `./.pi/skills/`, create them
|
|
121
|
+
using the bundled source files or the directives' instructions. Apply the same
|
|
122
|
+
merge-don't-clobber rule for any that already exist.
|
|
123
|
+
|
|
124
|
+
5. **Write/update provenance.** When the deployment is complete, write (or update)
|
|
125
|
+
`./.pi/harness.md` in the project directory. The provenance file is itself a valid
|
|
126
|
+
`harness.md` (the applied distro's frontmatter + directives) with a provenance
|
|
127
|
+
header injected at the top of the body:
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
<!-- pi-distro provenance
|
|
131
|
+
appliedHarness: <name>
|
|
132
|
+
appliedVersion: <version>
|
|
133
|
+
sourceCatalogue: <user|seed|none>
|
|
134
|
+
lastUpdated: <ISO8601>
|
|
135
|
+
-->
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
- `appliedHarness`: the name of the distro that was deployed.
|
|
139
|
+
- `appliedVersion`: the version from the distro frontmatter.
|
|
140
|
+
- `sourceCatalogue`: `seed` if it came from the package seeds, `user` if from
|
|
141
|
+
`~/.pi/harnesses/`.
|
|
142
|
+
- `lastUpdated`: current timestamp in ISO 8601 format.
|
|
143
|
+
|
|
144
|
+
6. **Report.** Summarise what was deployed, merged, skipped, and any packages installed.
|
|
145
|
+
Mention that the user can run `/pi-distro status` to see the current configuration.
|
|
146
|
+
|
|
147
|
+
7. **Recommend a restart.** Tell the user to **restart pi** — newly installed packages and
|
|
148
|
+
extensions are loaded at startup and are not available until the next session. The
|
|
149
|
+
configuration changes (settings, context, skills) take effect immediately, but code
|
|
150
|
+
that runs at startup (extensions, package-provided tools) requires a restart.
|
|
151
|
+
|
|
152
|
+
### Version-aware deploy
|
|
153
|
+
|
|
154
|
+
The kickoff message includes a **Version note** section that compares the incoming distro
|
|
155
|
+
version against the project's existing provenance (`appliedVersion` in `./.pi/harness.md`).
|
|
156
|
+
Follow it:
|
|
157
|
+
- **Upgrade** (incoming > existing): proceed normally with merge-don't-clobber. Existing
|
|
158
|
+
user customisations should be preserved — the new version adds/changes, it doesn't wipe.
|
|
159
|
+
- **Downgrade** (incoming < existing): **ask the user to confirm** before proceeding — this
|
|
160
|
+
may remove features or regress fixes. Only proceed if they confirm.
|
|
161
|
+
- **Same version** (incoming == existing): **ask the user** whether to (a) skip (no changes
|
|
162
|
+
— the project already has this exact distro) or (b) force re-deploy (re-run the merge,
|
|
163
|
+
useful if files were manually edited or the distro was updated in-place without a version
|
|
164
|
+
bump). Only proceed if they choose (b).
|
|
165
|
+
- **Different distro** (existing `appliedHarness` != incoming name): treat as a distro
|
|
166
|
+
switch — do not assume the new distro's files are a superset of the old. Merge with
|
|
167
|
+
existing config; the user may want to clean up files the old distro added.
|
|
168
|
+
- **First deploy** (no existing provenance): proceed normally.
|
|
169
|
+
|
|
170
|
+
## `/pi-distro update` — Update Applied Distro
|
|
171
|
+
|
|
172
|
+
When you receive a kickoff from the `update` command, the extension has already:
|
|
173
|
+
|
|
174
|
+
1. Read the project's provenance (`appliedHarness`, `appliedVersion`, `sourceCatalogue`).
|
|
175
|
+
2. Resolved the *current* version of that distro from the catalogue (or re-cloned the
|
|
176
|
+
GitHub repo if `sourceCatalogue` starts with `github:`).
|
|
177
|
+
3. Compared versions.
|
|
178
|
+
4. If a newer version exists: displayed a preview to the user and obtained their explicit
|
|
179
|
+
confirmation before sending the kickoff.
|
|
180
|
+
|
|
181
|
+
So by the time you (the agent) receive the kickoff, the user has already confirmed they
|
|
182
|
+
want the update. Proceed exactly as a normal deploy (merge-don't-clobber, user-involvement
|
|
183
|
+
rule, package-redundancy check, version note — which will show as an "upgrade"). The
|
|
184
|
+
update is just a re-deploy of the same distro at a newer version, with the user's consent
|
|
185
|
+
already obtained.
|
|
186
|
+
|
|
187
|
+
If the extension did NOT send a kickoff (e.g. "already up to date" or "downgrade
|
|
188
|
+
warning"), there is nothing for you to do — those cases are handled entirely by the
|
|
189
|
+
extension with a notification.
|
|
190
|
+
|
|
191
|
+
## `/pi-distro pick` — Partial Deploy
|
|
192
|
+
|
|
193
|
+
When you receive a kickoff from the `pick` command, the user wants to **select which
|
|
194
|
+
components to apply** from a distro — not the whole thing. This lets them combine pieces
|
|
195
|
+
from different distros to build their own configuration.
|
|
196
|
+
|
|
197
|
+
The kickoff lists the distro's components grouped by category (packages, bundled files,
|
|
198
|
+
and any other components described in the directives) along with the full directives for
|
|
199
|
+
your reference. Follow the selection procedure in the kickoff exactly:
|
|
200
|
+
|
|
201
|
+
1. **Walk the user through each category, one at a time.** Use `ctx.ui.select`/`ctx.ui.confirm`
|
|
202
|
+
to let them pick which items to apply. Present each item with its one-line purpose (from
|
|
203
|
+
the directives). Let them select any subset — including none (skip the category).
|
|
204
|
+
2. **Surface dependencies.** As the user selects, evaluate cross-component dependencies and
|
|
205
|
+
warn about them before applying. Example: if they pick an extension that references a
|
|
206
|
+
theme provided by a package they skipped, point that out and ask whether to also install
|
|
207
|
+
the package or skip the extension. Reason about the dependencies from the directives
|
|
208
|
+
prose — this is a judgment task. Never silently install a dependency the user didn't pick.
|
|
209
|
+
3. **Apply only the selected components** with the same rules as a full deploy:
|
|
210
|
+
merge-don't-clobber, package-redundancy check, `pi install -l` for packages (after
|
|
211
|
+
confirming), copy/merge for files (overwrite / keep theirs / merge).
|
|
212
|
+
4. **Do NOT write standard provenance.** A partial deploy is a custom config, not "this
|
|
213
|
+
distro was applied." Do not write `appliedHarness`/`appliedVersion` provenance. Instead,
|
|
214
|
+
after applying, suggest the next step: "This is a custom configuration. Run
|
|
215
|
+
`/pi-distro save` to snapshot it as your own reusable distro" (which writes clean
|
|
216
|
+
provenance for the saved distro).
|
|
217
|
+
5. **Recommend a restart** if any packages or extensions were installed.
|
|
218
|
+
|
|
219
|
+
The natural loop is: `/pi-distro pick <distro-A>` → `/pi-distro pick <distro-B>` →
|
|
220
|
+
`/pi-distro save` (snapshot the combined result as a new distro). This is how users build
|
|
221
|
+
their own distro from pieces of others.
|
|
222
|
+
|
|
223
|
+
## `/pi-distro undeploy` — Remove Applied Distro
|
|
224
|
+
|
|
225
|
+
When you receive a kickoff from the `undeploy` command, the user wants to **remove** the
|
|
226
|
+
applied distro from the project — the reverse of `deploy`. The extension has already read
|
|
227
|
+
provenance and sent you the distro's directives plus the current project state (which of
|
|
228
|
+
the distro's packages are still installed, whether the `AGENTS.md` delimited section
|
|
229
|
+
exists, what's in `.pi/settings.json`).
|
|
230
|
+
|
|
231
|
+
**Critical context:** provenance records the distro's *intentions* (the directives), not
|
|
232
|
+
the exact outcome of the interactive deploy. The user may have skipped packages during
|
|
233
|
+
deploy, customized files afterward, or removed things manually. So you must compare the
|
|
234
|
+
directives against the *current* project state and let the user decide what to remove.
|
|
235
|
+
|
|
236
|
+
Follow the removal procedure in the kickoff exactly:
|
|
237
|
+
|
|
238
|
+
1. **Walk the user through each removal category, one at a time:**
|
|
239
|
+
- **(a) Packages** — for each distro package still installed, offer `pi remove -l <pkg>`.
|
|
240
|
+
Ask per package — the user may want to keep some. Warn if removing a package that other
|
|
241
|
+
components depend on.
|
|
242
|
+
- **(b) Bundled files** — for each file the distro placed, check if it exists. If it
|
|
243
|
+
does, **show the user the file (or a summary) before removing** — they may have
|
|
244
|
+
customized it. Offer: remove / keep. Never silently delete. For `settings.json`, offer
|
|
245
|
+
to remove specific keys the distro merged, not the whole file.
|
|
246
|
+
- **(c) AGENTS.md delimited section** — if the `<!-- pi-distro: <name> -->` ...
|
|
247
|
+
`<!-- /pi-distro: <name> -->` block exists, offer to remove it. Leave any non-distro
|
|
248
|
+
content.
|
|
249
|
+
- **(d) Extensions / skills / prompts / themes** — if described in the directives and
|
|
250
|
+
present, offer to remove each (show before delete).
|
|
251
|
+
2. **Remove provenance last** — only after the user confirms the component removals, remove
|
|
252
|
+
`./.pi/harness.md`. Confirm before deleting.
|
|
253
|
+
3. **Report and recommend a restart** — summarise what was removed vs. kept. Tell the user to
|
|
254
|
+
restart pi so removed packages/extensions fully unload.
|
|
255
|
+
|
|
256
|
+
Removal is destructive — the user-involvement rule applies doubly here. Never silently
|
|
257
|
+
skip, delete, or strip. The user decides; you execute their choices.
|
|
258
|
+
|
|
259
|
+
> **Note:** `undeploy` only works for full deploys (which write provenance). A partial
|
|
260
|
+
> deploy via `pick` doesn't write provenance — there's nothing to undeploy as a unit.
|
|
261
|
+
|
|
262
|
+
## `/pi-distro save` — Distro Authoring
|
|
263
|
+
|
|
264
|
+
When you receive a draft request from the `save` command, it contains a live-config
|
|
265
|
+
snapshot of the current project: the system prompt options (tools, skills, context
|
|
266
|
+
files, guidelines), and the raw contents of **every project-local config file** found
|
|
267
|
+
under `./` (root `AGENTS.md`/`CLAUDE.md` variants), `./.pi/` (recursively — `settings.json`,
|
|
268
|
+
`SYSTEM.md`, `APPEND_SYSTEM.md`, `extensions/`, `skills/`, `prompts/`, `themes/`, and any
|
|
269
|
+
per-extension/skill config files like `.pi/<name>.json`), `./.crew/{agents,teams,workflows}/`
|
|
270
|
+
(pi-crew project-local authored definitions — NOT the runtime state subdirs), and
|
|
271
|
+
`./.agents/skills/` (project root only). Data/runtime dirs (`npm/`, `git/`, `sessions/`,
|
|
272
|
+
`state/`, `tmp/`, the non-config subdirs of `.crew/`, `node_modules/`) and the provenance file
|
|
273
|
+
`./.pi/harness.md` are excluded. Ancestor (parent-dir) `AGENTS.md` / `.agents/skills/`
|
|
274
|
+
appear only in the context-files list as informational — they are out of scope and must NOT
|
|
275
|
+
be bundled.
|
|
276
|
+
|
|
277
|
+
### Authoring steps
|
|
278
|
+
|
|
279
|
+
1. **Analyse the snapshot.** Review the live tools, skills, context files, installed
|
|
280
|
+
packages, and raw config files to understand what makes this project's configuration
|
|
281
|
+
unique and reproducible.
|
|
282
|
+
|
|
283
|
+
2. **Draft a `harness.md`.** Write a distro that reproduces this configuration:
|
|
284
|
+
- **Frontmatter**: propose a `name` (slug: lowercase a-z/0-9/hyphens, no
|
|
285
|
+
leading/trailing/consecutive hyphens, matching what the distro directory will be
|
|
286
|
+
named), a `title` (human-readable), a `description` (one-liner, ≤300 chars), and a
|
|
287
|
+
`version` (semver). Optionally `author` and `tags`.
|
|
288
|
+
- **Directives body**: include sections for bundled files, pi packages to install,
|
|
289
|
+
hooks/extensions, context, and skills/prompts — mirroring the live config.
|
|
290
|
+
|
|
291
|
+
3. **Propose & confirm.** Present the proposed `name`, `title`, `description`, and the full
|
|
292
|
+
draft to the user. Ask for confirmation or edits. Do not proceed until the user
|
|
293
|
+
confirms.
|
|
294
|
+
|
|
295
|
+
4. **Save to the catalogue (you perform this, not the extension).** Follow the procedure in
|
|
296
|
+
the kickoff message exactly:
|
|
297
|
+
- Ask the user whether to **save as a new distro** or **update an existing distro**.
|
|
298
|
+
- If **save as new**: validate the slug; warn on collisions with existing user
|
|
299
|
+
distros or seed names and ask whether to overwrite.
|
|
300
|
+
- If **update existing**: let the user pick from the existing user distros listed in
|
|
301
|
+
the kickoff. Refuse to update names not in that list (those are read-only package
|
|
302
|
+
seeds). Back the old distro up to `~/.pi/harnesses/.trash/<name>-<timestamp>/` before
|
|
303
|
+
overwriting. **Bump the version**: read the old distro's `version` and increment it
|
|
304
|
+
with semver — **patch** for small tweaks/bug fixes, **minor** for new capabilities or
|
|
305
|
+
config additions, **major** for breaking changes (removed packages, changed
|
|
306
|
+
conventions). Never keep the same version when updating. Propose the bumped version to
|
|
307
|
+
the user and let them confirm or adjust.
|
|
308
|
+
- Write `~/.pi/harnesses/<name>/harness.md` with the confirmed frontmatter + directives.
|
|
309
|
+
- Copy the project's config files into `~/.pi/harnesses/<name>/files/` preserving
|
|
310
|
+
their path relative to the project root — root context (`AGENTS.md`/`CLAUDE.md`),
|
|
311
|
+
`.pi/settings.json`, `.pi/SYSTEM.md` & `.pi/APPEND_SYSTEM.md`, `.pi/extensions/**`
|
|
312
|
+
(incl. subdir extensions), `.pi/skills/**`, `.pi/prompts/**`, `.pi/themes/**`,
|
|
313
|
+
`.agents/skills/**`, `.crew/{agents,teams,workflows}/**` (pi-crew project-local authored
|
|
314
|
+
definitions only), and any per-extension/skill config files (e.g. `.pi/<name>.json`)
|
|
315
|
+
listed in the snapshot. Use `cp -r` for trees. Do NOT copy `./.pi/harness.md`
|
|
316
|
+
(provenance) or the data/runtime dirs (`npm/`, `git/`, `sessions/`, `state/`, `tmp/`,
|
|
317
|
+
the non-config subdirs of `.crew/` i.e. state/artifacts/worktrees/imports/audit/cache/graphs,
|
|
318
|
+
`node_modules/`).
|
|
319
|
+
- **Theme dedup:** before bundling a `.pi/themes/<name>.json`, check `pi list` for a
|
|
320
|
+
package that already provides that theme (package themes surface at
|
|
321
|
+
`~/.pi/agent/themes/`). If one does, do NOT bundle it — reference it via the package
|
|
322
|
+
install directive instead (a bundled copy collides on deploy, like pi-crew's
|
|
323
|
+
`crew-*` themes). Bundle only genuinely custom themes.
|
|
324
|
+
- **pi-crew agents/teams/workflows dedup:** a `.crew/agents/foo.md` (or one under
|
|
325
|
+
`.pi/teams/agents/`, `.pi/agents/`) may be a `--copy-builtins` copy of a pi-crew
|
|
326
|
+
shipped builtin, not custom-authored. Compare against pi-crew's package builtins
|
|
327
|
+
(`<pkg>/agents/`, `teams/`, `workflows/`); if a file is an unmodified builtin copy,
|
|
328
|
+
do NOT bundle it (the `pi-crew` install directive already provides it). Bundle only
|
|
329
|
+
genuinely custom/authored definitions.
|
|
330
|
+
- **Write a README.md:** also write `~/.pi/harnesses/<name>/README.md` — a human-readable
|
|
331
|
+
description of the distro (a few paragraphs: what it sets up, which packages it
|
|
332
|
+
installs and why, what workflow it targets, and any prerequisites). This complements
|
|
333
|
+
the one-liner `description` in the frontmatter. The README lives only in the
|
|
334
|
+
catalogue — it is not copied into the target project on deploy.
|
|
335
|
+
|
|
336
|
+
5. **Update provenance.** Update `./.pi/harness.md` in the project to reflect the saved
|
|
337
|
+
distro (the saved frontmatter + directives with the provenance header at the top of
|
|
338
|
+
the body — see "Provenance file format" below).
|
|
339
|
+
|
|
340
|
+
6. **Report.** Tell the user: "Saved distro '<name>'. Run `/pi-distro deploy` elsewhere to
|
|
341
|
+
deploy it."
|
|
342
|
+
|
|
343
|
+
### Authoring conventions
|
|
344
|
+
|
|
345
|
+
See `docs/authoring.md` (shipped with the `@msdavid/pi-distro` package) for the
|
|
346
|
+
complete distro format reference: frontmatter fields, bundled `files/` directory
|
|
347
|
+
conventions, directive section types, and merge-don't-clobber expectations.
|
|
348
|
+
|
|
349
|
+
## Provenance file format
|
|
350
|
+
|
|
351
|
+
The provenance file at `./.pi/harness.md` is a living record of which distro was
|
|
352
|
+
applied to the project. It is a valid `harness.md` (same frontmatter + directives as
|
|
353
|
+
the applied distro) with the provenance header comment at the top of the body. The
|
|
354
|
+
extension updates it automatically as a side-effect of `deploy`, `save`, and `undeploy`
|
|
355
|
+
commands.
|
|
356
|
+
|
|
357
|
+
When `/pi-distro save` snapshots a project, the provenance file is regenerated to
|
|
358
|
+
reflect the *current* live config — it becomes the record of "this project's distro
|
|
359
|
+
now".
|