@lebronj/pi-suite 0.1.4 → 0.1.5

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 CHANGED
@@ -15,7 +15,7 @@ pi install npm:pi-subagents
15
15
  Or use the bootstrap script to install Pi, configure the team OpenAI-compatible endpoint, install this suite, and set up Bun + qmd for memory search:
16
16
 
17
17
  ```bash
18
- curl -fsSL https://registry.npmjs.org/@lebronj/pi-suite/-/pi-suite-0.1.3.tgz | tar -xzO package/scripts/bootstrap.sh | bash
18
+ curl -fsSL https://registry.npmjs.org/@lebronj/pi-suite/-/pi-suite-0.1.5.tgz | tar -xzO package/scripts/bootstrap.sh | bash
19
19
  ```
20
20
 
21
21
  ## What Is Included
@@ -23,7 +23,7 @@ curl -fsSL https://registry.npmjs.org/@lebronj/pi-suite/-/pi-suite-0.1.3.tgz | t
23
23
  - Local extensions: goal mode, pet, prompt URL widget, TUI redraw stats, snake, TPS notifications.
24
24
  - Prompts: changelog audit, issue analysis, PR review, wrap workflow.
25
25
  - Skills: provider checklist, weather, LeetCode array practice, Pi capability reference, image-to-editable-PPT workflow.
26
- - Vendored package: `@jhp/pi-memory`.
26
+ - Vendored package: `@jhp/pi-memory`, including qmd search, external curator service, and memory/skill-draft versioning.
27
27
 
28
28
  Install optional packages separately if needed:
29
29
 
@@ -49,7 +49,7 @@ The bootstrap script asks for an API key and writes:
49
49
 
50
50
  The API key is written to `~/.pi/agent/models.json` on the user's machine. Do not publish a shared key in this package.
51
51
 
52
- ## Memory Search
52
+ ## Memory And Versioning
53
53
 
54
54
  `@jhp/pi-memory` works without qmd for core memory features:
55
55
 
@@ -67,6 +67,20 @@ qmd collection add ~/.pi/agent/memory --name pi-memory
67
67
  qmd embed
68
68
  ```
69
69
 
70
+ Memory versioning is enabled by default. It snapshots `~/.pi/agent/memory` and `~/.pi/agent/skill-drafts` into `~/.pi/agent/evolution`, commits local changes automatically, and leaves push manual by default.
71
+
72
+ Useful commands:
73
+
74
+ ```bash
75
+ /memory-version-status
76
+ /memory-version-snapshot optional reason
77
+ /memory-version-list
78
+ /memory-version-restore <snapshot-id> [memory|skill-drafts|all]
79
+ /memory-version-push
80
+ ```
81
+
82
+ Default evolution remote: `https://github.com/LRM-Teams/pi-evolution.git`. Keep it private because it stores memory plaintext. Set `PI_EVOLUTION_AUTO_PUSH=1` only if automatic remote sync is desired.
83
+
70
84
  ## Goal Mode
71
85
 
72
86
  Use `/goal <objective>` to keep Pi working on one task until it is verified complete. Goal mode injects hidden task context, enables a `goal` tool for completion/drop/resume, and auto-continues between turns instead of stopping at a minimal implementation.
@@ -192,6 +192,10 @@ export default function goalModeExtension(pi: ExtensionAPI): void {
192
192
  if (previousTools) {
193
193
  pi.setActiveTools(previousTools);
194
194
  previousTools = undefined;
195
+ return;
196
+ }
197
+ if (activeTools.includes(GOAL_TOOL_NAME)) {
198
+ pi.setActiveTools(activeTools.filter((tool) => tool !== GOAL_TOOL_NAME));
195
199
  }
196
200
  }
197
201
 
@@ -421,6 +425,8 @@ export default function goalModeExtension(pi: ExtensionAPI): void {
421
425
  autoContinue = restored.autoContinue;
422
426
  if (goal?.status === "active") {
423
427
  setGoalToolEnabled(true);
428
+ } else {
429
+ setGoalToolEnabled(false);
424
430
  }
425
431
  updateUi(ctx);
426
432
  });
package/extensions/pet.ts CHANGED
@@ -23,6 +23,9 @@
23
23
 
24
24
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
25
25
  import { complete, type Message } from "@earendil-works/pi-ai";
26
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
27
+ import { homedir } from "node:os";
28
+ import { dirname, join } from "node:path";
26
29
  import {
27
30
  BorderedLoader,
28
31
  convertToLlm,
@@ -112,6 +115,7 @@ const PET_ITEMS: PetItem[] = [
112
115
  { id: "violet-badge", name: "Violet Badge", rarity: "epic", glyph: "#", color: "error", trigger: "memory" },
113
116
  { id: "star-crown", name: "Star Crown", rarity: "legendary", glyph: "^", color: "warning", trigger: "memory" },
114
117
  ];
118
+ const PERSISTED_PET_PROFILE_FILE = join(homedir(), ".pi", "agent", "pet-profile.json");
115
119
  const PET_COMMAND_COMPLETIONS: PetCommandCompletion[] = [
116
120
  { name: "on", description: "Show the pet" },
117
121
  { name: "off", description: "Hide the pet" },
@@ -244,6 +248,105 @@ const PET_ART: Record<PetKind, Record<PetMood | "blink" | "sleep", string[][]>>
244
248
  },
245
249
  };
246
250
 
251
+ function colorItemGlyph(item: PetItem, theme: Theme, glyph = item.glyph): string {
252
+ return item.rarity === "common" ? glyph : theme.fg(item.color, glyph);
253
+ }
254
+
255
+ function replaceFirstMatch(lines: string[], replacements: Array<[string, string]>): string[] {
256
+ return lines.map((line) => {
257
+ for (const [from, to] of replacements) {
258
+ if (line.includes(from)) return line.replace(from, to);
259
+ }
260
+ return line;
261
+ });
262
+ }
263
+
264
+ function chestReplacements(species: PetKind, mark: string): Array<[string, string]> {
265
+ switch (species) {
266
+ case "cat":
267
+ return [["> ^ <", `> ${mark} <`]];
268
+ case "dog":
269
+ return [["\\_^_/", `\\_${mark}_/`]];
270
+ case "fox":
271
+ return [["\\ v /", `\\ ${mark} /`]];
272
+ case "bot":
273
+ return [["|___|", `|_${mark}_|`]];
274
+ }
275
+ }
276
+
277
+ function scarfReplacements(species: PetKind): Array<[string, string]> {
278
+ switch (species) {
279
+ case "cat":
280
+ return [["> ^ <", "~ ^ ~"]];
281
+ case "dog":
282
+ return [["\\_^_/", "~_^_~"]];
283
+ case "fox":
284
+ return [["\\ v /", "~ v ~"]];
285
+ case "bot":
286
+ return [["|___|", "|~~~|"]];
287
+ }
288
+ }
289
+
290
+ function lensReplacements(species: PetKind, lens: string): Array<[string, string]> {
291
+ switch (species) {
292
+ case "cat":
293
+ case "fox":
294
+ return [
295
+ ["( o.o )", `( ${lens}.o )`],
296
+ ["( -.- )", `( ${lens}.- )`],
297
+ ["( ^.^ )", `( ${lens}.^ )`],
298
+ ["( >.< )", `( ${lens}.< )`],
299
+ ];
300
+ case "dog":
301
+ return [
302
+ ["( o o )", `( ${lens} o )`],
303
+ ["( - - )", `( ${lens} - )`],
304
+ ["( ^ ^ )", `( ${lens} ^ )`],
305
+ ["( > < )", `( ${lens} < )`],
306
+ ];
307
+ case "bot":
308
+ return [
309
+ ["[ o_o ]", `[ ${lens}_o ]`],
310
+ ["[ -_- ]", `[ ${lens}_- ]`],
311
+ ["[ ^_^ ]", `[ ${lens}_^ ]`],
312
+ ["[ >_< ]", `[ ${lens}_< ]`],
313
+ ];
314
+ }
315
+ }
316
+
317
+ function addItemParticles(lines: string[], item: PetItem, theme: Theme, frame: number): string[] {
318
+ if (item.rarity !== "epic" && item.rarity !== "legendary") return lines;
319
+ const glyphs = item.rarity === "legendary" ? ["*", "+", "."] : ["*", "."];
320
+ const left = theme.fg(item.color, glyphs[frame % glyphs.length] ?? "*");
321
+ const right = theme.fg(item.color, glyphs[(frame + 1) % glyphs.length] ?? "+");
322
+ if (item.rarity === "legendary") return [` ${left} ${colorItemGlyph(item, theme, "^")} ${right}`, ...lines];
323
+ return lines.map((line, index) => (index === 0 ? `${left} ${line} ${right}` : line));
324
+ }
325
+
326
+ function decoratePetArt(species: PetKind, art: string[], item: PetItem | undefined, theme: Theme, frame: number): string[] {
327
+ if (!item) return [...art];
328
+ const mark = colorItemGlyph(item, theme);
329
+ let lines = [...art];
330
+
331
+ switch (item.id) {
332
+ case "memory-lens":
333
+ lines = replaceFirstMatch(lines, lensReplacements(species, mark));
334
+ break;
335
+ case "green-scarf":
336
+ lines = replaceFirstMatch(lines, scarfReplacements(species));
337
+ break;
338
+ case "tin-bell":
339
+ case "amber-token":
340
+ case "violet-badge":
341
+ lines = replaceFirstMatch(lines, chestReplacements(species, mark));
342
+ break;
343
+ case "star-crown":
344
+ break;
345
+ }
346
+
347
+ return addItemParticles(lines, item, theme, frame);
348
+ }
349
+
247
350
  class PetComponent implements Component {
248
351
  private profile: PetProfile;
249
352
  private mood: PetMood = "idle";
@@ -299,9 +402,10 @@ class PetComponent implements Component {
299
402
  render(width: number): string[] {
300
403
  const pose = this.getPose();
301
404
  const frames = PET_ART[this.profile.species][pose];
302
- const art = frames[this.frame % frames.length] ?? frames[0];
405
+ const baseArt = frames[this.frame % frames.length] ?? frames[0];
303
406
  const equipped = getPetItem(this.profile.equippedItemId);
304
- const charm = equipped ? ` ${this.theme.fg(equipped.color, equipped.glyph)}` : "";
407
+ const art = decoratePetArt(this.profile.species, baseArt, equipped, this.theme, this.frame);
408
+ const charm = equipped ? ` ${colorItemGlyph(equipped, this.theme)}` : "";
305
409
  const title = `${this.profile.name} ${this.profile.rarity} ${this.profile.personality}`;
306
410
  const label = this.theme.fg("accent", `pet:${this.profile.species}`);
307
411
  const mood = this.theme.fg("dim", this.mood);
@@ -374,6 +478,23 @@ function defaultProfile(): PetProfile {
374
478
  };
375
479
  }
376
480
 
481
+ function readPersistedProfile(): PetProfile | undefined {
482
+ try {
483
+ return normalizeProfile(JSON.parse(readFileSync(PERSISTED_PET_PROFILE_FILE, "utf8")));
484
+ } catch {
485
+ return undefined;
486
+ }
487
+ }
488
+
489
+ function writePersistedProfile(profile: PetProfile): void {
490
+ try {
491
+ mkdirSync(dirname(PERSISTED_PET_PROFILE_FILE), { recursive: true });
492
+ writeFileSync(PERSISTED_PET_PROFILE_FILE, `${JSON.stringify(profile, undefined, 2)}\n`, "utf8");
493
+ } catch {
494
+ // Session-local pet state still works if the durable profile cannot be written.
495
+ }
496
+ }
497
+
377
498
  function normalizeProfile(value: unknown): PetProfile | undefined {
378
499
  if (!value || typeof value !== "object") return undefined;
379
500
  const partial = value as Partial<PetProfile>;
@@ -655,16 +776,26 @@ export default function petExtension(pi: ExtensionAPI) {
655
776
  let agentRunning = false;
656
777
 
657
778
  function saveProfile(): void {
779
+ writePersistedProfile(profile);
658
780
  pi.appendEntry(PET_PROFILE_TYPE, profile);
659
781
  }
660
782
 
661
783
  function restoreProfile(ctx: ExtensionContext): void {
784
+ const durableProfile = readPersistedProfile();
785
+ if (durableProfile) {
786
+ profile = durableProfile;
787
+ return;
788
+ }
789
+
662
790
  const entries = ctx.sessionManager.getEntries();
663
791
  for (let i = entries.length - 1; i >= 0; i--) {
664
792
  const entry = entries[i];
665
793
  if (entry.type !== "custom" || entry.customType !== PET_PROFILE_TYPE) continue;
666
794
  const saved = normalizeProfile(entry.data);
667
- if (saved) profile = saved;
795
+ if (saved) {
796
+ profile = saved;
797
+ writePersistedProfile(profile);
798
+ }
668
799
  return;
669
800
  }
670
801
  }
@@ -0,0 +1,10 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+
3
+ export default function simpleRepliesExtension(pi: ExtensionAPI): void {
4
+ pi.on("before_agent_start", async (event) => {
5
+ if (event.prompt.trim().toLowerCase() !== "hi") return undefined;
6
+ return {
7
+ systemPrompt: `${event.systemPrompt}\n\nFor this turn only, the user's entire message is "hi". Reply exactly: hi`,
8
+ };
9
+ });
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lebronj/pi-suite",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "JHP's Pi extension suite for team coding workflows",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -94,12 +94,49 @@ link_if_safe() {
94
94
  WORKSPACE_DIR="${PI_WORKSPACE_DIR:-$PWD}"
95
95
  WORKSPACE_PI_DIR="$WORKSPACE_DIR/.pi"
96
96
  MEMORY_DIR="$AGENT_DIR/memory"
97
+ EVOLUTION_DIR="${PI_EVOLUTION_DIR:-$AGENT_DIR/evolution}"
98
+ EVOLUTION_REMOTE="${PI_EVOLUTION_REMOTE:-https://github.com/LRM-Teams/pi-evolution.git}"
99
+ EVOLUTION_BRANCH="${PI_EVOLUTION_BRANCH:-main}"
97
100
  SUITE_SKILLS_DIR="${PI_SUITE_SKILLS_DIR:-$AGENT_DIR/npm/node_modules/@lebronj/pi-suite/skills}"
98
101
 
99
102
  mkdir -p "$MEMORY_DIR"
100
103
  link_if_safe "$MEMORY_DIR" "$WORKSPACE_PI_DIR/memory" "memory"
101
104
  link_if_safe "$SUITE_SKILLS_DIR" "$WORKSPACE_PI_DIR/skills" "skills"
102
105
 
106
+ setup_evolution_repo() {
107
+ if [ "${PI_EVOLUTION_ENABLED:-1}" = "0" ]; then
108
+ echo "Memory evolution versioning disabled by PI_EVOLUTION_ENABLED=0."
109
+ return 0
110
+ fi
111
+ if ! command -v git >/dev/null 2>&1; then
112
+ echo "Skip memory evolution repo setup: git is not installed."
113
+ return 0
114
+ fi
115
+ if [ -e "$EVOLUTION_DIR" ] && [ ! -d "$EVOLUTION_DIR/.git" ]; then
116
+ if [ -z "$(find "$EVOLUTION_DIR" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null)" ]; then
117
+ rmdir "$EVOLUTION_DIR"
118
+ else
119
+ echo "Skip memory evolution repo setup: $EVOLUTION_DIR exists and is not a git repo."
120
+ return 0
121
+ fi
122
+ fi
123
+ if [ ! -e "$EVOLUTION_DIR" ]; then
124
+ mkdir -p "$(dirname "$EVOLUTION_DIR")"
125
+ if ! git clone --branch "$EVOLUTION_BRANCH" "$EVOLUTION_REMOTE" "$EVOLUTION_DIR"; then
126
+ mkdir -p "$EVOLUTION_DIR"
127
+ git -C "$EVOLUTION_DIR" init -b "$EVOLUTION_BRANCH" 2>/dev/null || git -C "$EVOLUTION_DIR" init
128
+ git -C "$EVOLUTION_DIR" checkout -B "$EVOLUTION_BRANCH" >/dev/null 2>&1 || true
129
+ git -C "$EVOLUTION_DIR" remote add origin "$EVOLUTION_REMOTE" 2>/dev/null || true
130
+ fi
131
+ fi
132
+ mkdir -p "$EVOLUTION_DIR/memory" "$EVOLUTION_DIR/skill-drafts" "$EVOLUTION_DIR/snapshots" "$EVOLUTION_DIR/manifests"
133
+ echo "Memory evolution repo ready: $EVOLUTION_DIR"
134
+ echo "Remote: $EVOLUTION_REMOTE"
135
+ echo "Auto push remains off by default. Use /memory-version-push or PI_EVOLUTION_AUTO_PUSH=1."
136
+ }
137
+
138
+ setup_evolution_repo
139
+
103
140
  ensure_bun() {
104
141
  if command -v bun >/dev/null 2>&1; then
105
142
  return 0
@@ -5,11 +5,11 @@ description: Reference for this pi agent's installed capabilities, tools, memory
5
5
 
6
6
  # Pi Skill
7
7
 
8
- This skill is the local capability index for this pi setup. Use it to answer "what can you do?", choose the right tool/workflow, and keep user-facing capability docs synchronized when features change.
8
+ This skill is the local capability index for this pi setup. Use it to answer "what can you do?", choose the right workflow, and keep user-facing capability docs synchronized when features change.
9
9
 
10
10
  ## Maintenance Rule
11
11
 
12
- When adding, removing, renaming, or materially changing any pi capability in this workspace, update this skill in the same change. This includes tools, packages, extensions, memory behavior, skills, subagents, MCP servers, web/search integrations, and code-intelligence workflows.
12
+ When adding, removing, renaming, or materially changing any pi capability in this workspace, update this skill in the same change. This includes tools, packages, extensions, memory behavior, skills, subagents, MCP servers, web/search integrations, code-intelligence workflows, commands, prompt templates, and bootstrap behavior.
13
13
 
14
14
  ## Core Coding Tools
15
15
 
@@ -17,24 +17,27 @@ When adding, removing, renaming, or materially changing any pi capability in thi
17
17
  - `bash`: run shell commands; prefer `rg`/`rg --files` for search.
18
18
  - `edit`: precise exact-text replacements in one file.
19
19
  - `write`: create or overwrite files.
20
- - `lsp_diagnostics` / `lsp_navigation`: primary code-intelligence path for diagnostics, definitions, references, hover, symbols, call hierarchy, rename, and workspace diagnostics.
21
- - `ast_grep_search` / `ast_grep_replace` / `ast_dump`: semantic AST-aware code search and replacement; prefer over raw text search for code patterns.
22
- - `lens_diagnostics`: inspect pi-lens warnings/errors for files touched this session.
20
+ - `goal`: inspect, resume/drop, or complete an active goal-mode objective when goal mode is running.
21
+ - `lsp_diagnostics` / `lsp_navigation`: code-intelligence path for diagnostics, definitions, references, hover, symbols, call hierarchy, rename, and workspace diagnostics when pi-lens/LSP tools are installed.
22
+ - `ast_grep_search` / `ast_grep_replace` / `ast_dump`: AST-aware code search and replacement when pi-lens tools are installed; prefer over raw text search for structural code patterns.
23
+ - `lens_diagnostics`: inspect pi-lens warnings/errors for files touched this session when available.
23
24
 
24
- ## Memory
25
+ ## Memory And Self-Evolution
25
26
 
26
- Installed memory package: `@jhp/pi-memory` from `.pi/packages/pi-memory`.
27
+ Installed memory capability comes from `@jhp/pi-memory`, vendored inside `@lebronj/pi-suite` and also usable as a standalone pi package.
27
28
 
28
29
  Memory files live under `~/.pi/agent/memory/`:
29
30
 
30
31
  - `MEMORY.md`: durable facts, decisions, and preferences.
31
32
  - `USER.md`: structured user profile and stable preferences.
32
33
  - `STATE.md`: current dated state, events, temporary facts, and quotas.
33
- - `REVIEW.md`: review queue for stale or merge-candidate memories.
34
+ - `REVIEW.md`: review queue for stale memories, learning candidates, and promotion proposals.
34
35
  - `SCRATCHPAD.md`: checklist for open items.
35
- - `daily/YYYY-MM-DD.md`: daily append-only logs.
36
+ - `daily/YYYY-MM-DD.md`: daily append-only logs and session handoffs.
36
37
  - `.curator-state.json`: last curator run state.
38
+ - `.curator-service.json`: external curator service state.
37
39
  - `audit/curator.jsonl`: curator audit trail.
40
+ - `~/.pi/agent/skill-drafts/<slug>/SKILL.md`: disabled skill drafts created after explicit approval.
38
41
 
39
42
  Memory tools:
40
43
 
@@ -44,9 +47,17 @@ Memory tools:
44
47
  - `scratchpad`: add/done/undo/clear/list checklist items.
45
48
  - `memory_search`: qmd-backed keyword, semantic, or deep search across memory files.
46
49
  - `memory_curate`: manually run curator lifecycle rules.
47
- - `memory_curator_enable`: enable external daily curator service using systemd user timer or cron fallback.
50
+ - `memory_learning_approve`: approve a proposed memory promotion or disabled skill draft by exact id.
51
+ - `memory_learning_reject`: reject or archive a review candidate/proposal without deleting it.
52
+ - `memory_skill_drafts`: list proposed skill drafts.
53
+ - `memory_curator_enable`: enable the external daily curator service using systemd user timer or cron fallback.
48
54
  - `memory_curator_disable`: disable and uninstall the external daily curator service.
49
55
  - `memory_curator_status`: show service backend, schedule, and state.
56
+ - `memory_version_status`: show local evolution repo status, remote, branch, dirty state, last commit, and auto-push setting.
57
+ - `memory_version_snapshot`: manually snapshot `memory/` and `skill-drafts/`, sync mirrors, and commit.
58
+ - `memory_version_list`: list recent snapshots.
59
+ - `memory_version_restore`: restore `memory`, `skill-drafts`, or `all` from a snapshot id after creating a pre-restore backup.
60
+ - `memory_version_push`: manually push the local evolution repo to GitHub.
50
61
 
51
62
  Structured metadata example:
52
63
 
@@ -55,18 +66,65 @@ Structured metadata example:
55
66
  User plans to watch the NBA Finals.
56
67
  ```
57
68
 
58
- Curator behavior:
69
+ Curator and learning behavior:
59
70
 
60
- - Exact dedupe.
61
- - Event status transitions: `planned -> today -> past`.
71
+ - Exact duplicate entries are deduplicated.
72
+ - Event status transitions: `planned -> today -> past` based on `date`.
62
73
  - Expired temporary memories go to `REVIEW.md`, not automatic deletion.
63
- - Quotas reset when month/reset rolls over.
74
+ - Quotas reset when `month` or `reset` rolls over.
64
75
  - Mutations are audited to `audit/curator.jsonl`.
65
- - External service control lives in `@jhp/pi-memory`: `jhp-pi-memory-curator enable|disable|status|run-once`.
66
- - The external curator service is independent of the pi process. It uses a systemd user timer when available, with cron fallback, so scheduled curation can run even when pi is closed.
67
- - Users can ask pi to enable, disable, or inspect the service via `memory_curator_enable`, `memory_curator_disable`, and `memory_curator_status`.
76
+ - Session shutdown may extract conservative learning candidates into `REVIEW.md`; they are not injected as normal memory and are not auto-enabled.
77
+ - Repeated candidates can become proposed memory promotions or proposed disabled skill drafts after `memory_curate`.
78
+ - Approval is explicit by default: memory proposals write to memory stores; skill proposals write disabled drafts under `~/.pi/agent/skill-drafts/`.
79
+ - The curator avoids semantic auto-delete/merge; ambiguous learning stays in review first.
80
+
81
+ Memory versioning:
82
+
83
+ - Runtime memory remains authoritative at `~/.pi/agent/memory`; disabled skill drafts remain authoritative at `~/.pi/agent/skill-drafts`.
84
+ - Versioning mirror and snapshots live at `~/.pi/agent/evolution` by default.
85
+ - Default remote is `https://github.com/LRM-Teams/pi-evolution.git`; it should be private because memory is committed in plaintext.
86
+ - Automatic local snapshot + commit is enabled by default; automatic push is disabled unless `PI_EVOLUTION_AUTO_PUSH=1`.
87
+ - Snapshots run before mutating memory tools, curator runs, learning approve/reject, session summaries/handoffs, compact handoffs, restore, and external curator `run-once`.
88
+ - Slash commands: `/memory-version-status`, `/memory-version-snapshot [reason]`, `/memory-version-list`, `/memory-version-restore <snapshot-id> [memory|skill-drafts|all]`, `/memory-version-push`.
89
+ - Restore always writes a pre-restore snapshot first, then restores selected files and commits the restored state.
90
+
91
+ External curator service:
92
+
93
+ - This is the main self-evolution maintenance loop: it can run daily outside the pi process, even when pi is closed.
94
+ - It uses a systemd user timer when available, with cron fallback.
95
+ - On `session_start` and after `/reload`, pi-memory checks service status. If the service is disabled and UI is available, it shows a startup hint with enable/status/disable commands.
96
+ - Enable with `/memory-curator-enable 03:00` or ask the agent to call `memory_curator_enable`.
97
+ - Inspect with `/memory-curator-status` or `memory_curator_status`.
98
+ - Disable with `/memory-curator-disable` or `memory_curator_disable`.
99
+ - CLI equivalent: `jhp-pi-memory-curator enable|disable|status|run-once` when the binary is linked by the package manager.
100
+ - Disable startup hints with `PI_MEMORY_CURATOR_STARTUP_HINT=0` if a user does not want reminders.
68
101
  - Before uninstalling `@jhp/pi-memory`, run `memory_curator_disable` or `jhp-pi-memory-curator disable` so any systemd timer or cron entry is removed.
69
- - `.pi/extensions/memory-curator.ts` is deprecated and only warns users to use `@jhp/pi-memory` service tools.
102
+
103
+ QMD search:
104
+
105
+ - Core memory works without qmd.
106
+ - `memory_search` requires qmd for keyword, semantic, and deep search.
107
+ - Bootstrap attempts to install Bun + qmd, adds `~/.pi/agent/memory` as the `pi-memory` collection, and runs `qmd embed`.
108
+ - After writes, qmd updates run in the background by default; use `PI_MEMORY_QMD_UPDATE=manual` or `off` to change that.
109
+
110
+ Useful memory environment variables:
111
+
112
+ - `PI_MEMORY_DIR`: override memory storage directory.
113
+ - `PI_MEMORY_SNAPSHOT`: `stable` or `per-turn` context injection mode.
114
+ - `PI_MEMORY_QMD_UPDATE`: `background`, `manual`, or `off`.
115
+ - `PI_MEMORY_NO_SEARCH=1`: disable per-turn search injection.
116
+ - `PI_MEMORY_SUMMARIZE_TRANSITIONS=1`: also summarize lifecycle transitions such as `/reload`.
117
+ - `PI_MEMORY_LEARNING`: `off`, `review`, or `auto-review`.
118
+ - `PI_MEMORY_SKILL_DRAFTS`: `off` or `review`.
119
+ - `PI_MEMORY_AUTO_APPROVE_MEMORY=1`: automatically approve newly created memory proposals.
120
+ - `PI_MEMORY_AUTO_APPROVE_SKILL_DRAFTS=1`: automatically create newly proposed disabled skill drafts.
121
+ - `PI_MEMORY_CURATOR_STARTUP_HINT=0`: hide the disabled-curator startup hint.
122
+ - `PI_EVOLUTION_ENABLED=0`: disable snapshot + git versioning.
123
+ - `PI_EVOLUTION_DIR`: override evolution repo directory; default `~/.pi/agent/evolution`.
124
+ - `PI_EVOLUTION_REMOTE`: override remote; default `https://github.com/LRM-Teams/pi-evolution.git`.
125
+ - `PI_EVOLUTION_BRANCH`: override branch; default `main`.
126
+ - `PI_EVOLUTION_AUTO_COMMIT=0`: disable automatic local commits.
127
+ - `PI_EVOLUTION_AUTO_PUSH=1`: push automatically after commits.
70
128
 
71
129
  ## Web And Research
72
130
 
@@ -74,11 +132,11 @@ Curator behavior:
74
132
  - `fetch_content`: fetch readable content from URLs, GitHub repos, YouTube transcripts/video frames, and local videos. For video questions, pass the user's exact question as `prompt`.
75
133
  - `get_search_content`: retrieve full content saved by `web_search` or `fetch_content`.
76
134
  - `code_search`: search programming examples, docs, APIs, GitHub, and Stack Overflow; use for library/API/debugging questions before implementation.
77
- - `librarian` skill: use for evidence-backed open-source library internals with exact GitHub source citations.
135
+ - `librarian` skill: use for evidence-backed open-source library internals with exact GitHub source citations when installed.
78
136
 
79
137
  ## Subagents
80
138
 
81
- Use the `pi-subagents` skill and `subagent` tool for delegation.
139
+ Use the `pi-subagents` skill and `subagent` tool for delegation when installed.
82
140
 
83
141
  Typical uses:
84
142
 
@@ -95,7 +153,7 @@ Rules:
95
153
 
96
154
  ## MCP
97
155
 
98
- Use `mcp` to discover and call Model Context Protocol servers/tools.
156
+ Use `mcp` to discover and call Model Context Protocol servers/tools when `pi-mcp-adapter` is installed.
99
157
 
100
158
  Common flow:
101
159
 
@@ -109,9 +167,36 @@ mcp({ tool: "tool_name", args: "{}" })
109
167
 
110
168
  Do not route built-in pi tools through MCP; call them directly.
111
169
 
112
- ## Existing Skills
170
+ ## Goal Mode
171
+
172
+ Goal mode is provided by `goal-mode.ts`.
173
+
174
+ - Start with `/goal <objective>`.
175
+ - It injects hidden goal context, enables the `goal` tool, and auto-continues until the objective is complete, paused, dropped, blocked, or interrupted.
176
+ - The agent must verify current files/checks before calling `goal({ op: "complete" })`.
177
+ - Useful commands: `/goal show`, `/goal pause`, `/goal resume`, `/goal drop`, `/goal auto on`, `/goal auto off`.
178
+
179
+ ## Pet Companion
180
+
181
+ The pet extension provides a small terminal companion and durable profile.
182
+
183
+ - Command: `/pet`.
184
+ - Subcommands include `on`, `off`, `cat`, `dog`, `fox`, `bot`, `name`, `mood`, `checkin`, `feed`, `bag`, `equip`, `unequip`, `position`, `reset`, and `ask`.
185
+ - `/pet ask <question>` answers from current context without saving the answer into the main session.
186
+ - Item drops can happen from tool usage, memory events, and daily check-ins, with pity counters.
187
+ - Pet profile/inventory is mirrored at `~/.pi/agent/pet-profile.json` so equipment survives `/new` and future sessions.
188
+
189
+ ## UI And Utility Extensions
113
190
 
114
- Local project skills currently include:
191
+ - `prompt-url-widget.ts`: detects PR/issue prompt templates, fetches GitHub metadata with `gh`, shows a widget, and names the session when possible.
192
+ - `redraws.ts`: `/tui` shows TUI full redraw stats.
193
+ - `snake.ts`: `/snake` opens a TUI snake game; `Esc` pauses/saves, `q` quits, arrows/WASD move.
194
+ - `tps.ts`: after each assistant run, shows tokens-per-second and token usage details.
195
+ - `memory-curator.ts`: deprecated compatibility notice only; external curation is managed by pi-memory service tools.
196
+
197
+ ## Skills
198
+
199
+ Suite skills currently include:
115
200
 
116
201
  - `add-llm-provider`: checklist for adding providers to `packages/ai`.
117
202
  - `image-to-editable-ppt-slide`: rebuild reference images as editable PowerPoint slides.
@@ -119,7 +204,7 @@ Local project skills currently include:
119
204
  - `weather`: current weather and forecasts using no-key services.
120
205
  - `pi-skill`: this capability index.
121
206
 
122
- Package-provided skills currently include:
207
+ Optional package-provided skills can include:
123
208
 
124
209
  - `librarian`: library internals research with source citations.
125
210
  - `pi-subagents`: subagent delegation workflows.
@@ -128,11 +213,24 @@ Package-provided skills currently include:
128
213
  - `write-ast-grep-rule`: author pi-lens ast-grep rules.
129
214
  - `write-tree-sitter-rule`: author pi-lens tree-sitter rules.
130
215
 
131
- ## Pi Package And Extension Notes
216
+ ## Prompt Templates
217
+
218
+ Suite prompt templates currently include:
219
+
220
+ - `/cl`: changelog audit workflow.
221
+ - `/is`: issue analysis workflow.
222
+ - `/pr`: GitHub PR review workflow.
223
+ - `/wr`: wrap-up workflow with final comment guidance.
224
+
225
+ ## Package And Bootstrap Notes
226
+
227
+ Global user package configuration is in `~/.pi/agent/settings.json`; project package configuration is in `.pi/settings.json` and `.pi/npm/package.json`.
228
+
229
+ Current suite package:
132
230
 
133
- Project package configuration is in `.pi/settings.json` and `.pi/npm/package.json`.
231
+ - `@lebronj/pi-suite`: bundles local extensions, prompts, suite skills, vendored `@jhp/pi-memory`, and optional package hooks for `pi-mcp-adapter`, `pi-subagents`, and `pi-web-access`.
134
232
 
135
- Current project packages:
233
+ Common project packages:
136
234
 
137
235
  - `@jhp/pi-memory`
138
236
  - `pi-web-access`
@@ -140,16 +238,24 @@ Current project packages:
140
238
  - `pi-subagents`
141
239
  - `pi-lens`
142
240
 
143
- Project extensions are in `.pi/extensions/`. Important current extensions:
241
+ Bootstrap behavior:
144
242
 
145
- - `pet.ts`: terminal pet UI with `/pet` subcommands, argument autocomplete for actions such as `/pet ask`, `/pet position`, and `/pet equip`, plus item drops with pity counters.
146
- - `memory-curator.ts`: deprecated compatibility notice only. The external curator service is managed by `@jhp/pi-memory`.
243
+ - Installs global `@earendil-works/pi-coding-agent`.
244
+ - Writes the team OpenAI-compatible provider to `~/.pi/agent/models.json`.
245
+ - Sets default provider/model in `~/.pi/agent/settings.json`.
246
+ - Runs `pi install npm:@lebronj/pi-suite` by default.
247
+ - Creates `~/.pi/agent/memory` and links it into the workspace `.pi/memory` when safe.
248
+ - Optionally initializes the local `~/.pi/agent/evolution` repo for memory/skill-draft snapshots; it never writes tokens or enables auto-push.
249
+ - Links suite skills into the workspace `.pi/skills` when safe.
250
+ - Installs Bun + qmd when possible and initializes the `pi-memory` qmd collection.
251
+ - Does not auto-enable the external memory curator service; the startup hint explains how to enable it.
147
252
 
148
253
  ## Recommended Workflows
149
254
 
150
- - For code changes: inspect files, edit, run targeted tests if tests changed, then run `npm run check` for repo code changes.
255
+ - For code changes: inspect files, edit deliberately, run targeted tests, then run the repo's relevant check command.
151
256
  - For memory changes: use `memory_write` for new facts and `memory_edit` for updates/removals.
152
257
  - For time-sensitive memory: write structured `STATE.md` entries with `type`, `status`, and date/reset metadata.
258
+ - For self-evolution upkeep: keep the external curator service enabled unless the user opts out, and review `REVIEW.md` proposals before approving memory or skill promotions.
153
259
  - For web facts or current events: use `web_search`; for page/video details, use `fetch_content`.
154
260
  - For library internals: use `librarian` or `code_search` with source-backed evidence.
155
261
  - For broad or risky tasks: use subagents for investigation/review, then integrate deliberately.