@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,413 @@
1
+ # Pi Recipe Extension
2
+
3
+ The Pi recipe extension resolves a recipe directory, selects a recipe agent, and
4
+ maps recipe resources into the live Pi session.
5
+
6
+ ## Install
7
+
8
+ Install the recipe tooling:
9
+
10
+ ```bash
11
+ npm install -g @introspection-ai/pi-recipes
12
+ ```
13
+
14
+ `recipes install ...` automatically installs this companion extension into
15
+ Pi when it is missing. To set it up explicitly:
16
+
17
+ ```bash
18
+ recipes setup
19
+ ```
20
+
21
+ Manual Pi installation is still available:
22
+
23
+ ```bash
24
+ pi install npm:@introspection-ai/pi-recipes
25
+ ```
26
+
27
+ For a local clone:
28
+
29
+ ```bash
30
+ pnpm install
31
+ pnpm build
32
+ pi install "$(pwd)"
33
+ ```
34
+
35
+ Re-run `pnpm build` after changing extension source.
36
+
37
+ ## Launch
38
+
39
+ Launch with a local recipe directory:
40
+
41
+ ```bash
42
+ pi --recipe /path/to/recipe
43
+ ```
44
+
45
+ Launch with an installed recipe:
46
+
47
+ ```bash
48
+ recipes install github:owner/repo
49
+ pi --recipe owner/repo
50
+ pi --recipe recipe-name
51
+ ```
52
+
53
+ Select an explicit recipe agent:
54
+
55
+ ```bash
56
+ pi --recipe recipe-name --agent reviewer
57
+ ```
58
+
59
+ Environment variable equivalents:
60
+
61
+ ```bash
62
+ PI_RECIPE_DIR=recipe-name pi
63
+ PI_RECIPE_DIR=recipe-name PI_AGENT_NAME=reviewer pi
64
+ ```
65
+
66
+ `--recipe` accepts:
67
+
68
+ - an existing local directory
69
+ - an installed short recipe name
70
+ - an installed scoped recipe name
71
+
72
+ The extension resolves installed recipes from the `recipes` store. Set
73
+ `PI_RECIPES_HOME` if Pi should use a non-default store.
74
+
75
+ ## Launch Flow
76
+
77
+ On session startup, the extension:
78
+
79
+ 1. Reads `--recipe` or `PI_RECIPE_DIR`.
80
+ 2. Resolves the value as a local directory or installed recipe.
81
+ 3. Loads the recipe manifest from `package.json`.
82
+ 4. Selects the active recipe agent.
83
+ 5. Loads declared recipe extensions.
84
+ 6. Sets the Pi session name.
85
+ 7. Sets the model and thinking level from the selected agent when specified.
86
+ 8. Selects active tools from the selected agent.
87
+ 9. Returns recipe resources for skills, prompts, and themes.
88
+ 10. Composes the runtime system prompt from Pi defaults, `SYSTEM.md`, selected agent instructions, and recipe runtime context.
89
+
90
+ The current Pi working directory remains the user's project workspace. The
91
+ recipe directory is available in runtime context, but it does not become the
92
+ workspace.
93
+
94
+ ## Manifest File
95
+
96
+ `package.json` is the recipe manifest. Top-level package fields tell Pi what
97
+ recipe this is:
98
+
99
+ - `name`, `version`, and `description`
100
+
101
+ The `pi` block tells Pi which recipe-owned files should be loaded:
102
+
103
+ - agent definition globs
104
+ - extension globs
105
+ - skill, prompt, and theme paths
106
+
107
+ The same file also carries normal Node package metadata for extension
108
+ dependencies. Add `dependencies`, `peerDependencies`, `packageManager`, and a
109
+ lockfile when TypeScript extensions under `extensions/` import npm packages.
110
+
111
+ Minimal example:
112
+
113
+ ```json
114
+ {
115
+ "name": "my-recipe",
116
+ "version": "0.1.0",
117
+ "description": "A short description of what this recipe is for.",
118
+ "type": "module",
119
+ "pi": {
120
+ "agents": ["agents/*.yaml"]
121
+ }
122
+ }
123
+ ```
124
+
125
+ ## Agent Selection
126
+
127
+ Selection order:
128
+
129
+ 1. `--agent` or `PI_AGENT_NAME`
130
+ 2. `agents/agent.yaml`
131
+ 3. the only available agent
132
+
133
+ If multiple agents exist and no default can be inferred, launch fails with a
134
+ clear error.
135
+
136
+ Agent files are YAML:
137
+
138
+ ```yaml
139
+ name: agent
140
+ description: Main coordinator
141
+ model:
142
+ name: openai/gpt-5.4
143
+ thinking_level: medium
144
+ tools:
145
+ - read
146
+ - bash
147
+ skills:
148
+ - repo-index
149
+ subagents:
150
+ - explorer
151
+ system_instructions:
152
+ mode: append
153
+ content: |
154
+ Extra instructions for this agent.
155
+ ```
156
+
157
+ A named variant is another agent that inherits from a base with `from:`:
158
+
159
+ ```yaml
160
+ name: agent-opus
161
+ from: agent
162
+ model:
163
+ name: openrouter/anthropic/claude-opus-4.8
164
+ ```
165
+
166
+ Objects such as `model` and `extensions` merge by key. Arrays such as `tools`,
167
+ `skills`, and `subagents` replace the inherited array.
168
+
169
+ `system_instructions.mode` can be:
170
+
171
+ - `append`: append to the current prompt
172
+ - `replace`: replace the current prompt
173
+
174
+ ## Session Prompt
175
+
176
+ The session prompt is assembled from:
177
+
178
+ 1. Pi's base system prompt
179
+ 2. recipe `SYSTEM.md`, when present
180
+ 3. selected agent `system_instructions`
181
+ 4. runtime context containing the current workspace and recipe directory
182
+
183
+ This lets recipes carry durable workflow guidance without changing where the
184
+ user is working.
185
+
186
+ ## Tools
187
+
188
+ The selected agent controls active tools:
189
+
190
+ ```yaml
191
+ tools:
192
+ - read
193
+ - bash
194
+ - WebFetch
195
+ ```
196
+
197
+ If the selected agent has visible subagents, the extension also enables the
198
+ recipe `agent` tool.
199
+
200
+ Recipe extensions must be loaded before active tools are selected, because they
201
+ can register additional tools such as `WebFetch`, `WebSearch`, `todo_write`, or
202
+ custom workflow tools.
203
+
204
+ The selected agent can gate which declared recipe extensions load:
205
+
206
+ ```yaml
207
+ extensions:
208
+ include:
209
+ - "*"
210
+ exclude:
211
+ - optional-runtime
212
+ ```
213
+
214
+ Omitting `extensions` or `extensions.include` loads all declared recipe
215
+ extensions. `exclude` subtracts matching extension names.
216
+
217
+ ## Commands
218
+
219
+ When a recipe is active, the extension registers:
220
+
221
+ ```text
222
+ /recipe
223
+ /recipe reload
224
+ ```
225
+
226
+ `/recipe` shows:
227
+
228
+ - active recipe name and version
229
+ - selected agent
230
+ - selected model and thinking level
231
+ - visible subagents
232
+ - active recipe tools
233
+ - recipe directory
234
+ - project workspace
235
+
236
+ `/recipe reload` asks Pi to reload extensions, skills, prompts, and themes, and
237
+ clears the cached recipe manifest and agent state first. Use it after editing a
238
+ local recipe's `package.json`, agent files, resources, or extension code.
239
+
240
+ ## Resources
241
+
242
+ The extension responds to Pi `resources_discover` with:
243
+
244
+ - `skillPaths`
245
+ - `promptPaths`
246
+ - `themePaths`
247
+
248
+ Declared manifest paths are used first. When omitted, conventional folders are
249
+ used if present:
250
+
251
+ - `skills`
252
+ - `prompts`
253
+ - `themes`
254
+
255
+ Skills become Pi `/skill:name` commands. Prompt templates and themes are
256
+ surfaced through Pi's normal resource system.
257
+
258
+ ## Subagents
259
+
260
+ Recipe subagents are other agents from the same recipe, exposed through the
261
+ `agent` tool.
262
+
263
+ If the selected agent declares `subagents`, only those agents are visible:
264
+
265
+ ```yaml
266
+ name: agent
267
+ subagents:
268
+ - explorer
269
+ - reviewer
270
+ ```
271
+
272
+ If it omits `subagents`, every other recipe agent is visible.
273
+
274
+ The `agent` tool accepts:
275
+
276
+ - `name`: child agent name
277
+ - `task`: delegated task
278
+ - `label`: optional display label
279
+ - `wait`: wait for completion on start, defaulting to `true`
280
+ - `action`: `start`, `status`, `wait`, `interrupt`, or `close`
281
+ - `id`: child-run id for management actions
282
+
283
+ Child runs use the same recipe directory and current Pi workspace as the parent
284
+ session.
285
+
286
+ ## Recipe Extensions
287
+
288
+ Recipes can declare Pi extensions:
289
+
290
+ ```json
291
+ {
292
+ "pi": {
293
+ "extensions": ["extensions/*.ts", "extensions/*/index.ts"]
294
+ }
295
+ }
296
+ ```
297
+
298
+ Extensions are loaded during `session_start`. If one extension fails, Pi shows a
299
+ warning and continues loading the rest of the recipe. During local recipe
300
+ development, run `/recipe reload` after editing extension files to reload them
301
+ without restarting Pi.
302
+
303
+ Extension glob branches are optional, so a recipe can declare both flat and
304
+ nested extension layouts without failing when one branch has no matches.
305
+
306
+ Extensions are loaded with module resolution rooted at the recipe directory. If
307
+ an extension imports a third-party package, declare that dependency in the
308
+ recipe's `package.json` and install/register the recipe with `recipes install`
309
+ so dependencies are installed into the recipe directory. For remote Git recipes,
310
+ commit a lockfile with the recipe.
311
+
312
+ Example layout:
313
+
314
+ ```text
315
+ my-recipe/
316
+ package.json
317
+ package-lock.json
318
+ agents/
319
+ agent.yaml
320
+ extensions/
321
+ tools.ts
322
+ ```
323
+
324
+ Example dependency manifest:
325
+
326
+ ```json
327
+ {
328
+ "name": "hello-tools",
329
+ "version": "0.1.0",
330
+ "type": "module",
331
+ "pi": {
332
+ "agents": ["agents/*.yaml"],
333
+ "extensions": ["extensions/*.ts"]
334
+ },
335
+ "dependencies": {
336
+ "zod": "^4.0.0"
337
+ },
338
+ "peerDependencies": {
339
+ "@earendil-works/pi-coding-agent": "*",
340
+ "typebox": "*"
341
+ }
342
+ }
343
+ ```
344
+
345
+ Generate the lockfile from inside the recipe directory:
346
+
347
+ ```bash
348
+ cd my-recipe
349
+ npm install --package-lock-only
350
+ recipes install .
351
+ ```
352
+
353
+ For a remote Git recipe, commit `package.json` and the lockfile.
354
+ When users run `recipes install github:owner/repo`, the CLI installs production
355
+ dependencies into that cloned recipe before Pi loads extensions.
356
+
357
+ Imports of Pi runtime packages such as `@earendil-works/pi-coding-agent`,
358
+ `@earendil-works/pi-ai`, and `typebox` are resolved to the host Pi installation.
359
+ Declare those as peers in the recipe `package.json` rather than bundling another
360
+ copy.
361
+
362
+ Use normal `dependencies` for packages your extension imports at runtime. Use
363
+ `devDependencies` only for local recipe development tools; they are not needed
364
+ for Pi to run the recipe.
365
+
366
+ Example extension:
367
+
368
+ ```ts
369
+ import { defineTool, type ExtensionFactory } from "@earendil-works/pi-coding-agent";
370
+ import { Type } from "typebox";
371
+
372
+ const extension: ExtensionFactory = (pi) => {
373
+ pi.registerTool(
374
+ defineTool({
375
+ name: "hello_recipe",
376
+ label: "Hello",
377
+ description: "Return a greeting from the recipe.",
378
+ parameters: Type.Object({ name: Type.String() }),
379
+ async execute(_id, params) {
380
+ return { content: [{ type: "text", text: `Hello ${params.name}` }] };
381
+ },
382
+ })
383
+ );
384
+ };
385
+
386
+ export default extension;
387
+ ```
388
+
389
+ ## Troubleshooting
390
+
391
+ If Pi cannot find an installed recipe, check the store:
392
+
393
+ ```bash
394
+ recipes list
395
+ recipes path recipe-name
396
+ ```
397
+
398
+ If Pi and `recipes` are using different stores, set:
399
+
400
+ ```bash
401
+ PI_RECIPES_HOME=/path/to/store pi --recipe recipe-name
402
+ ```
403
+
404
+ If an agent selects a model but Pi reports the model is unavailable, confirm the
405
+ model provider exists in Pi and the corresponding API key is configured.
406
+
407
+ If a recipe tool is listed in an agent but not active, confirm the extension
408
+ that registers the tool is declared in the recipe manifest and loads without a
409
+ warning.
410
+
411
+ If an extension fails with `Cannot find module`, confirm the dependency is in
412
+ the recipe `package.json`, the recipe was installed with `recipes install`, and the
413
+ dependency was written to the recipe's `node_modules`.