@introspection-ai/pi-recipes 0.1.0-beta.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.
@@ -0,0 +1,529 @@
1
+ # Recipe CLI
2
+
3
+ `recipes` is the Pi recipe manager. It installs, registers, lists, removes,
4
+ validates, scaffolds, and publishes recipe folders for Pi.
5
+
6
+ ## Install
7
+
8
+ Install the recipe tooling into the environment where you run Pi:
9
+
10
+ ```bash
11
+ npm install -g @introspection-ai/pi-recipes
12
+ ```
13
+
14
+ The first `recipes install ...` run checks whether the companion Pi extension
15
+ is installed. If it is missing, `recipes` runs:
16
+
17
+ ```bash
18
+ pi install npm:@introspection-ai/pi-recipes
19
+ ```
20
+
21
+ You can run setup explicitly:
22
+
23
+ ```bash
24
+ recipes setup
25
+ ```
26
+
27
+ For local development:
28
+
29
+ ```bash
30
+ pnpm install
31
+ pnpm build
32
+ pnpm link --global
33
+ recipes setup "$(pwd)" --force
34
+ ```
35
+
36
+ The CLI binary is `recipes`:
37
+
38
+ ```bash
39
+ recipes --help
40
+ ```
41
+
42
+ ## Store
43
+
44
+ Recipes are tracked in a local store:
45
+
46
+ ```text
47
+ ~/.pi/recipes/recipes.json
48
+ ```
49
+
50
+ Use a different store with either:
51
+
52
+ ```bash
53
+ PI_RECIPES_HOME=/path/to/store recipes list
54
+ recipes list --store /path/to/store
55
+ ```
56
+
57
+ Remote Git recipes are cloned into the store. Local recipes are registered by
58
+ path, so edits to the local directory are immediately visible to the harness.
59
+ If a recipe declares extension runtime dependencies in `package.json`,
60
+ `recipes install` installs them in that recipe directory.
61
+
62
+ ## Create a Recipe
63
+
64
+ Create a starter recipe with:
65
+
66
+ ```bash
67
+ recipes create ./my-recipe
68
+ ```
69
+
70
+ This writes a working recipe skeleton:
71
+
72
+ ```text
73
+ my-recipe/
74
+ package.json
75
+ README.md
76
+ SYSTEM.md
77
+ agents/
78
+ agent.yaml
79
+ ```
80
+
81
+ Use `--name` when the directory name is not the recipe identifier you want:
82
+
83
+ ```bash
84
+ recipes create ./recipes/code-review --name code-review
85
+ ```
86
+
87
+ `recipes create` refuses to overwrite existing scaffold files unless `--force` is
88
+ provided. After generating the starter, edit the files to fit your workflow.
89
+
90
+ Minimal `package.json`:
91
+
92
+ ```json
93
+ {
94
+ "name": "my-recipe",
95
+ "version": "0.1.0",
96
+ "description": "A short description of what this recipe is for.",
97
+ "type": "module",
98
+ "pi": {
99
+ "agents": ["agents/*.yaml"]
100
+ }
101
+ }
102
+ ```
103
+
104
+ Minimal `agents/agent.yaml`:
105
+
106
+ ```yaml
107
+ name: agent
108
+ description: Main recipe agent.
109
+ model:
110
+ name: openai/gpt-5.4
111
+ thinking_level: medium
112
+ tools:
113
+ - read
114
+ - bash
115
+ skills: []
116
+ subagents: []
117
+ system_instructions:
118
+ mode: append
119
+ content: |
120
+ Follow the recipe's workflow.
121
+ ```
122
+
123
+ `agents/agent.yaml` is the conventional default entrypoint. A named variant is
124
+ another agent that inherits from a base with `from:`:
125
+
126
+ ```yaml
127
+ name: agent-high-recall
128
+ from: agent
129
+ model:
130
+ thinking_level: high
131
+ ```
132
+
133
+ Objects such as `model` and `extensions` merge by key, while arrays such as
134
+ `tools`, `skills`, and `subagents` replace the inherited array.
135
+
136
+ `SYSTEM.md` is optional. When present, Pi uses it as the recipe-level system
137
+ prompt before applying the selected agent's `system_instructions`.
138
+
139
+ ## Develop a Recipe
140
+
141
+ Validate the current recipe directory:
142
+
143
+ ```bash
144
+ recipes doctor .
145
+ ```
146
+
147
+ `doctor` checks the manifest, resolves declared resources, catches missing
148
+ required agent globs, and warns when no default agent can be inferred.
149
+
150
+ Register the local recipe:
151
+
152
+ ```bash
153
+ recipes install ./my-recipe
154
+ ```
155
+
156
+ Inspect what was registered:
157
+
158
+ ```bash
159
+ recipes list
160
+ recipes path my-recipe
161
+ recipes doctor my-recipe
162
+ ```
163
+
164
+ Run it in Pi:
165
+
166
+ ```bash
167
+ pi --recipe my-recipe
168
+ pi --recipe my-recipe --agent agent
169
+ ```
170
+
171
+ ## `package.json` and `pi`
172
+
173
+ Recipes use `package.json` as their manifest. Top-level package fields describe
174
+ the recipe identity:
175
+
176
+ - `name`: the identifier users pass to `pi --recipe` and `recipes path`
177
+ - `version`: the recipe version shown in Pi sessions
178
+ - `description`: a short summary for humans
179
+
180
+ The `pi` block declares recipe-owned resources:
181
+
182
+ - `agents`: agent definition globs
183
+ - `extensions`: TypeScript extension globs
184
+ - `skills`: skill paths or globs
185
+ - `prompts`: prompt paths or globs
186
+ - `themes`: theme paths or globs
187
+
188
+ Normal package-manager fields such as `dependencies`, `optionalDependencies`,
189
+ `peerDependencies`, `devDependencies`, `packageManager`, and lockfile metadata
190
+ live in the same `package.json`. This keeps recipe discovery, publishing, and
191
+ extension dependency installation on one obvious path.
192
+
193
+ ## Resource Folders
194
+
195
+ Declare resources in `package.json#pi` when you want explicit package
196
+ boundaries:
197
+
198
+ ```json
199
+ {
200
+ "pi": {
201
+ "agents": ["agents/*.yaml"],
202
+ "extensions": ["extensions/*.ts", "extensions/*/index.ts"],
203
+ "skills": ["skills/**/SKILL.md"],
204
+ "prompts": ["prompts"],
205
+ "themes": ["themes/*.json"]
206
+ }
207
+ }
208
+ ```
209
+
210
+ When entries are omitted, conventional folders are used if present:
211
+
212
+ - `agents`
213
+ - `skills`
214
+ - `prompts`
215
+ - `themes`
216
+
217
+ `extensions` are only loaded when declared.
218
+
219
+ ## Extension Dependencies
220
+
221
+ Recipes that declare TypeScript extensions add runtime dependencies to the same
222
+ `package.json`:
223
+
224
+ ```text
225
+ my-recipe/
226
+ package.json
227
+ package-lock.json
228
+ extensions/
229
+ tools.ts
230
+ ```
231
+
232
+ Example extension:
233
+
234
+ ```ts
235
+ import { defineTool, type ExtensionFactory } from "@earendil-works/pi-coding-agent";
236
+ import { Type } from "typebox";
237
+ import { z } from "zod";
238
+
239
+ const NameParams = z.object({ name: z.string().min(1) });
240
+
241
+ const extension: ExtensionFactory = (pi) => {
242
+ pi.registerTool(
243
+ defineTool({
244
+ name: "hello_validated",
245
+ label: "Hello",
246
+ description: "Return a validated greeting.",
247
+ parameters: Type.Object({ name: Type.String() }),
248
+ async execute(_id, params) {
249
+ const { name } = NameParams.parse(params);
250
+ return { content: [{ type: "text", text: `Hello ${name}` }] };
251
+ },
252
+ })
253
+ );
254
+ };
255
+
256
+ export default extension;
257
+ ```
258
+
259
+ Example `package.json` for that extension:
260
+
261
+ ```json
262
+ {
263
+ "name": "zod-tools",
264
+ "version": "0.1.0",
265
+ "description": "Recipe with an extension that validates inputs with zod.",
266
+ "type": "module",
267
+ "pi": {
268
+ "agents": ["agents/*.yaml"],
269
+ "extensions": ["extensions/*.ts"]
270
+ },
271
+ "dependencies": {
272
+ "zod": "^4.0.0"
273
+ },
274
+ "peerDependencies": {
275
+ "@earendil-works/pi-coding-agent": "*",
276
+ "typebox": "*"
277
+ }
278
+ }
279
+ ```
280
+
281
+ Create and commit a lockfile from the recipe directory:
282
+
283
+ ```bash
284
+ cd my-recipe
285
+ npm install --package-lock-only
286
+ ```
287
+
288
+ Then register or install the recipe:
289
+
290
+ ```bash
291
+ recipes install .
292
+ ```
293
+
294
+ `recipes install` installs production dependencies into the recipe directory so
295
+ extension imports resolve from that recipe. For local recipes, this modifies the
296
+ local recipe directory. For remote Git recipes, dependencies are installed into
297
+ the cloned recipe cache.
298
+
299
+ When a remote Git recipe has `dependencies` or `optionalDependencies`, it must
300
+ also commit a lockfile:
301
+
302
+ - `package-lock.json`
303
+ - `npm-shrinkwrap.json`
304
+ - `pnpm-lock.yaml`
305
+ - `yarn.lock`
306
+
307
+ `recipes install` installs production dependencies with lifecycle scripts disabled:
308
+
309
+ - npm: `npm ci --omit=dev --ignore-scripts`
310
+ - pnpm: `pnpm install --prod --frozen-lockfile --ignore-scripts`
311
+ - yarn: `yarn install --production --frozen-lockfile --ignore-scripts`
312
+
313
+ It chooses the package manager from `packageManager` when present, otherwise
314
+ from the lockfile. If you use pnpm or yarn, set `packageManager` and commit the
315
+ matching lockfile:
316
+
317
+ ```json
318
+ {
319
+ "name": "zod-tools",
320
+ "version": "0.1.0",
321
+ "type": "module",
322
+ "packageManager": "pnpm@10.0.0",
323
+ "pi": {
324
+ "agents": ["agents/*.yaml"],
325
+ "extensions": ["extensions/*.ts"]
326
+ },
327
+ "dependencies": {
328
+ "zod": "^4.0.0"
329
+ }
330
+ }
331
+ ```
332
+
333
+ Pi runtime packages imported by extensions, such as
334
+ `@earendil-works/pi-coding-agent`, `@earendil-works/pi-ai`, and `typebox`,
335
+ should be peers. The Pi recipe extension aliases those packages to the host Pi
336
+ installation so recipe extensions share the running Pi runtime.
337
+
338
+ Use `devDependencies` for packages needed only while developing the recipe, such
339
+ as test runners or local build tools. They are not installed when a remote
340
+ recipe is installed for runtime use.
341
+
342
+ ## Install Recipes
343
+
344
+ Install from a local directory:
345
+
346
+ ```bash
347
+ recipes install ./my-recipe
348
+ ```
349
+
350
+ Install from GitHub shorthand:
351
+
352
+ ```bash
353
+ recipes install github:owner/repo
354
+ recipes install github:owner/repo/path/to/recipe
355
+ recipes install owner/repo
356
+ ```
357
+
358
+ Install a pinned ref:
359
+
360
+ ```bash
361
+ recipes install github:owner/repo#v1.0.0
362
+ recipes install github:owner/repo/path/to/recipe#v1.0.0
363
+ ```
364
+
365
+ Install from explicit Git URLs:
366
+
367
+ ```bash
368
+ recipes install git@github.com:owner/private-recipe.git
369
+ recipes install git+https://github.com/owner/recipe.git#v1.0.0
370
+ recipes install file:///path/to/recipe.git#v1.0.0
371
+ ```
372
+
373
+ Re-clone an existing remote source:
374
+
375
+ ```bash
376
+ recipes install github:owner/repo --force
377
+ ```
378
+
379
+ Print machine-readable output:
380
+
381
+ ```bash
382
+ recipes install github:owner/repo --json
383
+ recipes list --json
384
+ recipes doctor my-recipe --json
385
+ ```
386
+
387
+ ## Customize Recipes
388
+
389
+ When you want to make a small local change to a recipe installed from elsewhere,
390
+ copy it into an editable local recipe:
391
+
392
+ ```bash
393
+ recipes customize pi-codex
394
+ ```
395
+
396
+ This creates a copy under the recipe store's `local/` directory, registers that
397
+ copy under the same recipe name, and leaves remote clone caches alone. Edit the
398
+ printed directory, then run:
399
+
400
+ ```bash
401
+ recipes doctor pi-codex
402
+ pi --recipe pi-codex
403
+ ```
404
+
405
+ If the recipe is already registered as an editable local copy, `customize`
406
+ reuses it. Pass `--force` only when the target local directory already exists
407
+ while copying from another registered source.
408
+
409
+ ## Resolve Recipes
410
+
411
+ `recipes path <identifier>` resolves an installed recipe directory:
412
+
413
+ ```bash
414
+ recipes path my-recipe
415
+ recipes path github:owner/repo
416
+ recipes path owner/repo
417
+ recipes path repo
418
+ ```
419
+
420
+ Identifiers can match:
421
+
422
+ - short recipe name, such as `my-recipe`
423
+ - scoped recipe name, such as `owner/my-recipe`
424
+ - local directory path
425
+
426
+ The Pi extension uses the same resolution rules for `--recipe`.
427
+
428
+ ## Remove Recipes
429
+
430
+ Remove a recipe record from the store:
431
+
432
+ ```bash
433
+ recipes remove my-recipe
434
+ recipes remove owner/my-recipe
435
+ ```
436
+
437
+ This removes the store record. Remote clone contents may remain in the store
438
+ cache and can be reused by a later install unless `--force` is used.
439
+
440
+ ## Publish Recipes
441
+
442
+ Publish a recipe to GitHub:
443
+
444
+ ```bash
445
+ recipes publish ./my-recipe --github owner/my-recipe --visibility public
446
+ ```
447
+
448
+ `recipes publish` runs the same development validation as `doctor`, updates
449
+ `package.json#name` to `@owner/my-recipe`, commits local changes, creates the
450
+ GitHub repository when needed, pushes `main`, and re-registers the local recipe.
451
+
452
+ For a standalone public recipe:
453
+
454
+ ```bash
455
+ mkdir my-recipe
456
+ cd my-recipe
457
+ # add package.json, SYSTEM.md, agents/, skills/, extensions/ as needed
458
+ git init
459
+ git add .
460
+ git commit -m "initial recipe"
461
+ gh repo create owner/my-recipe --private=false --source . --push
462
+ ```
463
+
464
+ Users install it with:
465
+
466
+ ```bash
467
+ recipes install github:owner/my-recipe
468
+ ```
469
+
470
+ For a private recipe, use normal GitHub access control. Users can install via
471
+ SSH:
472
+
473
+ ```bash
474
+ recipes install git@github.com:owner/private-recipe.git
475
+ ```
476
+
477
+ For CI or noninteractive GitHub installs, set a token:
478
+
479
+ ```bash
480
+ GITHUB_TOKEN=... recipes install github:owner/private-recipe
481
+ ```
482
+
483
+ For reproducible releases, tag the Git repository and tell users to install the
484
+ tag:
485
+
486
+ ```bash
487
+ git tag v1.0.0
488
+ git push origin v1.0.0
489
+ recipes install github:owner/my-recipe#v1.0.0
490
+ ```
491
+
492
+ For monorepos or recipe collections, put each recipe in a subdirectory:
493
+
494
+ ```text
495
+ recipes/
496
+ code-review/
497
+ package.json
498
+ research/
499
+ package.json
500
+ ```
501
+
502
+ Install a subdirectory recipe with:
503
+
504
+ ```bash
505
+ recipes install github:owner/repo/recipes/code-review
506
+ recipes install github:owner/repo/recipes/research#v1.0.0
507
+ ```
508
+
509
+ ## Troubleshooting
510
+
511
+ If a private GitHub recipe fails to install with `github:owner/repo`, use SSH or
512
+ set a token:
513
+
514
+ ```bash
515
+ recipes install git@github.com:owner/repo.git
516
+ GITHUB_TOKEN=... recipes install github:owner/repo
517
+ ```
518
+
519
+ If `doctor` reports missing resources, check that glob paths are relative to the
520
+ recipe directory and that direct paths exist. If `recipes install` reports missing
521
+ extension dependency lockfiles, commit the lockfile generated by your package
522
+ manager.
523
+
524
+ If Pi cannot find a recipe by name, confirm it is in the same store:
525
+
526
+ ```bash
527
+ recipes list
528
+ PI_RECIPES_HOME=/same/store pi --recipe my-recipe
529
+ ```
@@ -0,0 +1,148 @@
1
+ # Pi Recipes: Install, Customize, Publish
2
+
3
+ A recipe is a shareable Pi workflow package: it can add agents, instructions,
4
+ skills, prompts, themes, and optional runtime extensions.
5
+
6
+ Use `recipes` to install recipes, make local edits, validate them, and
7
+ publish your own.
8
+
9
+ ## 1. Install the Tooling
10
+
11
+ Install the recipe CLI once:
12
+
13
+ ```bash
14
+ npm install -g @introspection-ai/pi-recipes
15
+ ```
16
+
17
+ `recipes` works with a companion Pi extension. Install it explicitly with:
18
+
19
+ ```bash
20
+ recipes setup
21
+ ```
22
+
23
+ After that, install recipes with `recipes install ...`.
24
+
25
+ Recipes are stored under:
26
+
27
+ ```text
28
+ ~/.pi/recipes
29
+ ```
30
+
31
+ ## 2. Install and Run a Recipe
32
+
33
+ Install a recipe from GitHub:
34
+
35
+ ```bash
36
+ recipes install github:tfidfwastaken/pi-codex
37
+ ```
38
+
39
+ See what is installed:
40
+
41
+ ```bash
42
+ recipes list
43
+ ```
44
+
45
+ Run it in Pi:
46
+
47
+ ```bash
48
+ pi --recipe pi-codex
49
+ ```
50
+
51
+ If two installed recipes share the same short name, use the scoped name shown by
52
+ `recipes list`:
53
+
54
+ ```bash
55
+ pi --recipe tfidfwastaken/pi-codex
56
+ ```
57
+
58
+ ## 3. Customize an Installed Recipe
59
+
60
+ Use `customize` when you want to edit a recipe you installed from elsewhere:
61
+
62
+ ```bash
63
+ recipes customize pi-codex
64
+ ```
65
+
66
+ Example output:
67
+
68
+ ```text
69
+ Created editable copy for pi-codex
70
+
71
+ Edit this folder:
72
+ /Users/atharva/.pi/recipes/local/tfidfwastaken-pi-codex
73
+
74
+ Then check and run it:
75
+ recipes doctor pi-codex
76
+ pi --recipe pi-codex
77
+ ```
78
+
79
+ Edit files in the printed folder, then validate and run the customized copy:
80
+
81
+ ```bash
82
+ recipes doctor pi-codex
83
+ pi --recipe pi-codex
84
+ ```
85
+
86
+ To discard a customized copy, delete the editable folder and reinstall the
87
+ original source:
88
+
89
+ ```bash
90
+ rm -rf ~/.pi/recipes/local/tfidfwastaken-pi-codex
91
+ recipes install github:tfidfwastaken/pi-codex
92
+ ```
93
+
94
+ ## 4. Create a New Recipe
95
+
96
+ Create a starter recipe:
97
+
98
+ ```bash
99
+ recipes create ./my-recipe
100
+ ```
101
+
102
+ The starter contains:
103
+
104
+ ```text
105
+ my-recipe/
106
+ package.json
107
+ README.md
108
+ SYSTEM.md
109
+ agents/
110
+ agent.yaml
111
+ ```
112
+
113
+ Validate and try it locally:
114
+
115
+ ```bash
116
+ recipes doctor ./my-recipe
117
+ recipes install ./my-recipe
118
+ pi --recipe my-recipe
119
+ ```
120
+
121
+ ## 5. Publish a Recipe
122
+
123
+ Publishing turns a local recipe into a GitHub-backed recipe. It validates the
124
+ recipe, updates `package.json#name` to match the target repo, commits changes,
125
+ creates the GitHub repo if needed, pushes `main`, and re-registers the local
126
+ recipe.
127
+
128
+ ```bash
129
+ recipes publish ./my-recipe --github owner/my-recipe --visibility private
130
+ ```
131
+
132
+ Use `--visibility public` for public recipes.
133
+
134
+ After publishing, other users install it with:
135
+
136
+ ```bash
137
+ recipes install github:owner/my-recipe
138
+ pi --recipe my-recipe
139
+ ```
140
+
141
+ ## Mental Model
142
+
143
+ - `install` gets a recipe into your local Pi recipe store.
144
+ - `list` shows what Pi can run and where the local files are.
145
+ - `customize` creates an editable local copy of an installed recipe.
146
+ - `doctor` validates a recipe before running or publishing it.
147
+ - `create` starts a new recipe from scratch.
148
+ - `publish` pushes a recipe to GitHub so others can install it.