pi-hermes-memory 0.7.6 → 0.7.7

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
@@ -69,7 +69,7 @@ The extension manages three types of knowledge:
69
69
  |---|---|---|---|
70
70
  | **Memory** (MEMORY.md) | Facts — env details, project conventions, tool quirks | 5,000 chars max | Searchable by default |
71
71
  | **User Profile** (USER.md) | Who you are — name, preferences, communication style | 5,000 chars max | Searchable by default |
72
- | **Skills** (skills/*.md) | Procedures — *how* to do something, reusable across sessions | Unlimited | Available through skill tool |
72
+ | **Skills** (Pi-native `SKILL.md`) | Procedures — *how* to do something, reusable across sessions | Unlimited | Discoverable by Pi + manageable via the skill tool |
73
73
 
74
74
  ![Memory + Skills Architecture](docs/images/memory-architecture.svg)
75
75
 
@@ -119,7 +119,7 @@ System Prompt
119
119
  └─────────────────────────────────────────┘
120
120
  ```
121
121
 
122
- Set `"memoryPolicyStyle"` to `"full"`, `"compact"`, `"custom"`, or `"none"` to choose policy verbosity while keeping policy-only mode. Set `"memoryMode": "legacy-inject"` to restore the old behavior that injects MEMORY.md, USER.md, project memory, recent failures, and the skill index into the prompt.
122
+ Set `"memoryPolicyStyle"` to `"full"`, `"compact"`, `"custom"`, or `"none"` to choose policy verbosity while keeping policy-only mode. Set `"memoryMode": "legacy-inject"` to restore the old behavior that injects MEMORY.md, USER.md, project memory, and recent failures into the prompt.
123
123
 
124
124
  ## Failure Memory
125
125
 
@@ -177,13 +177,29 @@ The agent also gets a `skill` tool for saving reusable procedures:
177
177
 
178
178
  | Action | What it does |
179
179
  |---|---|
180
- | `create` | Save a new skill (name, description, step-by-step body) |
181
- | `view` | Read a skill's full content, or list all skills if no name given |
182
- | `patch` | Update one section of an existing skill (e.g., just the Procedure section) |
183
- | `edit` | Replace the description and/or full body of a skill |
184
- | `delete` | Remove a skill |
180
+ | `create` | Save a new skill (name, description, step-by-step body, optional `scope`) |
181
+ | `view` | Read a skill's full content by `skill_id`, or list all skills if no id is given |
182
+ | `patch` | Update one section of an existing skill by `skill_id` |
183
+ | `edit` | Replace the description and/or full body of a skill by `skill_id` |
184
+ | `delete` | Remove a skill by `skill_id` |
185
185
 
186
- Skills are stored as `SKILL.md` files in `~/.pi/agent/memory/skills/`. Each has a structured body:
186
+ Skills are stored in Pi-native locations:
187
+
188
+ - Global skills: `~/.pi/agent/skills/<slug>/SKILL.md`
189
+ - Project skills: `~/.pi/agent/projects-memory/<project>/skills/<slug>/SKILL.md`
190
+
191
+ The extension classifies new skills automatically:
192
+
193
+ - `global` for transferable procedures
194
+ - `project` for repo-specific workflows tied to local paths, scripts, architecture, deploy steps, or conventions
195
+
196
+ Global skill creation also has duplicate/similarity guards:
197
+
198
+ - exact slug match → blocked (update existing via `patch`/`edit`)
199
+ - near-name + high description similarity → blocked as similar (enhance existing)
200
+ - near-name + low description similarity → blocked as name collision (rename to a clearer distinct skill name)
201
+
202
+ Each skill uses a structured `SKILL.md` body:
187
203
 
188
204
  ```markdown
189
205
  ---
@@ -209,13 +225,23 @@ When you see TypeScript compilation errors, especially in monorepo setups.
209
225
  Run `tsc --noEmit` and confirm zero errors.
210
226
  ```
211
227
 
228
+ ### Project Skill Discovery (`resources_discover`)
229
+
230
+ Project-scoped skills are loaded via Pi's `resources_discover` hook.
231
+
232
+ On discovery, the extension returns the active project's skills directory as a skill path:
233
+
234
+ - `~/.pi/agent/projects-memory/<project>/skills/`
235
+
236
+ This lets Pi discover project skills as native skills without copying them into the global skills folder.
237
+
212
238
  ### Memory vs User Profile vs Skills
213
239
 
214
240
  | Store | File | What goes here | Limit |
215
241
  |---|---|---|---|
216
242
  | **memory** | `MEMORY.md` | Agent's notes — env facts, project conventions, tool quirks, lessons learned | 5,000 chars |
217
243
  | **user** | `USER.md` | User profile — name, preferences, communication style, habits | 5,000 chars |
218
- | **skills** | `skills/*.md` | Procedures — *how* to debug, deploy, test, or fix something | Unlimited |
244
+ | **skills** | `~/.pi/agent/skills/<slug>/SKILL.md` or `projects-memory/<project>/skills/<slug>/SKILL.md` | Procedures — *how* to debug, deploy, test, or fix something | Unlimited |
219
245
  | **extended** | `sessions.db` | Searchable memories beyond the core limit | Unlimited |
220
246
  | **sessions** | `sessions.db` | Past conversation history (searchable via FTS5) | Unlimited |
221
247
 
@@ -295,13 +321,13 @@ This means skills build up naturally over time without you having to ask.
295
321
  | Command | What it does |
296
322
  |---|---|
297
323
  | `/memory-insights` | Shows everything stored in memory and user profile |
298
- | `/memory-skills` | Lists all agent-created skills |
324
+ | `/memory-skills` | Lists global and active-project skills with their ids |
299
325
  | `/memory-consolidate` | Manually trigger memory consolidation to free space |
300
326
  | `/memory-interview` | Answer a few questions to pre-fill your user profile |
301
327
  | `/memory-switch-project` | List all project memories and their entry counts |
302
328
  | `/memory-index-sessions` | Import past Pi sessions into the search database |
303
329
  | `/memory-sync-markdown` | Backfill Markdown memories into the SQLite search store |
304
- | `/memory-preview-context` | Preview the memory policy or legacy memory/skill blocks appended to the system prompt |
330
+ | `/memory-preview-context` | Preview the memory policy or legacy memory blocks appended to the system prompt |
305
331
  | `/learn-memory-tool` | Skill that teaches users how to use the memory system |
306
332
 
307
333
  ### `/memory-insights` Output
@@ -331,13 +357,17 @@ This means skills build up naturally over time without you having to ask.
331
357
  ║ 🧠 Procedural Skills ║
332
358
  ╚══════════════════════════════════════════════╝
333
359
 
360
+ Global Skills
361
+ ─────────────
334
362
  📄 debug-typescript-errors
335
363
  Step-by-step approach to debugging TS errors in monorepos
336
- file: debug-typescript-errors.md
364
+ id: global:debug-typescript-errors
337
365
 
366
+ Project Skills (pi-hermes-memory)
367
+ ────────────────────────────────
338
368
  📄 deploy-checklist
339
369
  Pre-deploy verification steps for this project
340
- file: deploy-checklist.md
370
+ id: project:pi-hermes-memory:deploy-checklist
341
371
  ```
342
372
 
343
373
  ## Configuration
@@ -373,7 +403,7 @@ Create `~/.pi/agent/hermes-memory-config.json`:
373
403
 
374
404
  | Setting | Default | Description |
375
405
  |---|---|---|
376
- | `memoryMode` | `policy-only` | Prompt behavior: `policy-only` injects only memory policy; `legacy-inject` restores full memory/skill prompt injection |
406
+ | `memoryMode` | `policy-only` | Prompt behavior: `policy-only` injects only memory policy; `legacy-inject` restores full memory prompt injection |
377
407
  | `memoryPolicyStyle` | `full` | Policy text used in `policy-only` mode: `full` preserves the default v0.7 policy; `compact` uses shorter built-in guidance; `custom` uses `memoryPolicyCustomText`; `none` injects no policy text |
378
408
  | `memoryPolicyCustomText` | unset | Custom policy text used when `memoryPolicyStyle` is `custom`; blank or missing text falls back to `compact` |
379
409
  | `memoryCharLimit` | `5000` | Max characters in MEMORY.md |
@@ -405,23 +435,29 @@ Create `~/.pi/agent/hermes-memory-config.json`:
405
435
 
406
436
  ```
407
437
  ~/.pi/agent/
438
+ ├── skills/ ← Global Pi-native skills
439
+ │ ├── debug-typescript-errors/
440
+ │ │ └── SKILL.md
441
+ │ └── testing-checklist/
442
+ │ └── SKILL.md
408
443
  ├── projects-memory/ ← ALL project-scoped memories (one subfolder per project)
409
444
  │ ├── my-project/
410
- │ │ └── MEMORY.md
445
+ │ │ ├── MEMORY.md
446
+ │ │ └── skills/
447
+ │ │ └── deploy-checklist/
448
+ │ │ └── SKILL.md
411
449
  │ └── another-project/
412
450
  │ └── MEMORY.md
413
451
  ├── memory/ ← Global memory
414
452
  │ ├── MEMORY.md ← Agent's personal notes (env facts, patterns, lessons)
415
453
  │ ├── USER.md ← User profile (name, preferences, habits)
416
454
  │ ├── sessions.db ← SQLite database (session history + extended memory)
417
- │ └── skills/
418
- │ ├── debug-typescript-errors.md
419
- │ └── deploy-checklist.md
455
+ │ └── .skills-migrated-to-pi-native
420
456
  ├── hermes-memory-config.json
421
457
  └── ...
422
458
  ```
423
459
 
424
- These are plain markdown files. You can read and edit them directly if you want to curate what the agent remembers. Memory entries are separated by `§` (section sign). Skills use standard SKILL.md format with frontmatter.
460
+ These are plain markdown files. You can read and edit them directly if you want to curate what the agent remembers. Memory entries are separated by `§` (section sign). Skills use Pi-compatible `SKILL.md` files with frontmatter.
425
461
 
426
462
  If you are upgrading from a version that stored project memory directly at `~/.pi/agent/<project>/MEMORY.md`, the extension copies or merges those entries into `~/.pi/agent/projects-memory/<project>/MEMORY.md` on startup. The old folders are left in place as a backup.
427
463
 
@@ -435,7 +471,8 @@ The `sessions.db` SQLite database stores session history and extended memory ent
435
471
  - **Older Markdown memories may need backfill**: If you saved memories before the SQLite mirror existed or search looks stale, run `/memory-sync-markdown`.
436
472
  - **Core memory limits still apply**: SQLite search mirroring does not bypass the 5,000-char core Markdown limit. If consolidation cannot free space, the write fails instead of becoming SQLite-only memory invisibly.
437
473
  - **System prompts are invisible**: Pi's TUI does not display the system prompt. Use `/memory-preview-context` to inspect whether policy-only or legacy memory injection is active.
438
- - **Skills are agent-generated**: Skills are created by the agent based on its experience. They may not always be perfectly structured. You can edit or delete them in `~/.pi/agent/memory/skills/`.
474
+ - **Project skill visibility depends on Pi discovery cycles**: project skills are exposed through `resources_discover` using the active project's `skills/` path. If a new skill doesn't show up immediately in a running session, trigger a reload/new session so Pi refreshes discovered resources.
475
+ - **Skills are agent-generated**: Skills are created by the agent based on its experience. They may not always be perfectly structured. You can edit or delete them in `~/.pi/agent/skills/` or the active project's `skills/` folder.
439
476
 
440
477
  ## Architecture
441
478
 
@@ -45,7 +45,7 @@ Target state:
45
45
  "image": "https://raw.githubusercontent.com/chandra447/pi-hermes-memory/main/docs/assets/hermes-memory-preview.png"
46
46
  },
47
47
  "peerDependencies": {
48
- "@mariozechner/pi-coding-agent": "*"
48
+ "@earendil-works/pi-coding-agent": "*"
49
49
  }
50
50
  }
51
51
  ```
package/docs/ROADMAP.md CHANGED
@@ -131,7 +131,7 @@ Hermes creates skills after complex tasks (5+ tool calls). Skills are SKILL.md f
131
131
  **Key insight**: Pi already has a skill system. Our skill tool should write SKILL.md files that are compatible with Pi's skill discovery. This means our skills are immediately usable as Pi slash commands — no separate ecosystem needed.
132
132
 
133
133
  - [ ] `skill` tool — register via `pi.registerTool()` with actions: `create`, `patch`, `edit`, `delete`
134
- - [ ] Skill storage in `~/.pi/agent/memory/skills/` (not `~/.pi/agent/skills/` avoid conflicting with user's own skills)
134
+ - [x] Skill storage split by scope: global skills in `~/.pi/agent/skills/<slug>/SKILL.md`, project skills in `~/.pi/agent/projects-memory/<project>/skills/<slug>/SKILL.md` (discovered via `resources_discover`)
135
135
  - [ ] SKILL.md format — compatible with Pi's SKILL.md spec (frontmatter + markdown body)
136
136
  - [ ] Progressive disclosure — skill index (name + description only) injected into system prompt, full content loaded on demand via `skill_view` action
137
137
  - [ ] Auto-trigger after complex tasks — track tool calls per turn, trigger skill extraction at 5+ tool calls
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-hermes-memory",
3
- "version": "0.7.6",
3
+ "version": "0.7.7",
4
4
  "description": "🧠 Persistent memory + 🔍 session search + 🛡️ secret scanning for Pi. Token-aware policy-only memory by default, SQLite FTS5 search, auto-consolidation, procedural skills. 368 tests. Ported from Hermes agent.",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -45,11 +45,11 @@
45
45
  "url": "https://github.com/chandra447/pi-hermes-memory"
46
46
  },
47
47
  "peerDependencies": {
48
- "@mariozechner/pi-coding-agent": ">=0.70.0"
48
+ "@earendil-works/pi-coding-agent": ">=0.74.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@mariozechner/pi-ai": "^0.70.0",
52
- "@mariozechner/pi-coding-agent": "^0.70.0",
51
+ "@earendil-works/pi-ai": "^0.74.0",
52
+ "@earendil-works/pi-coding-agent": "^0.74.0",
53
53
  "@types/better-sqlite3": "^7.6.13",
54
54
  "tsx": "^4.21.0",
55
55
  "typebox": "^1.1.33",
package/src/constants.ts CHANGED
@@ -134,7 +134,7 @@ export const COMBINED_REVIEW_PROMPT = `Review the conversation above and conside
134
134
 
135
135
  For failures, include: what was tried, why it failed, what error occurred, and what worked instead.
136
136
 
137
- **Skills**: Was a complex, non-trivial approach used to complete a task — one that required trial and error, multiple tool calls, or changing course? If so, save a reusable procedure using the skill tool with action 'create'. Include: when to use it, step-by-step procedure, pitfalls to avoid, and how to verify success. If a related skill already exists, use action 'patch' to update it instead of creating a duplicate.
137
+ **Skills**: Was a complex, non-trivial approach used to complete a task — one that required trial and error, multiple tool calls, or changing course? If so, save a reusable procedure using the skill tool with action 'create'. Always pass scope explicitly on create (scope='global' or scope='project'). Choose scope='global' for transferable procedures and scope='project' when the workflow depends on this repo's paths, scripts, architecture, deploy steps, or conventions. Include: when to use it, step-by-step procedure, pitfalls to avoid, and how to verify success. If a related skill already exists, use action 'patch' with its skill_id instead of creating a duplicate.
138
138
 
139
139
  Only act if there's something genuinely worth saving. If nothing stands out, just say 'Nothing to save.' and stop.`;
140
140
 
@@ -221,13 +221,17 @@ Priority:
221
221
  Use the memory tool to save. If this contradicts an existing entry, use 'replace' to update it.`;
222
222
 
223
223
  // ─── Skill tool description ───
224
- export const SKILL_TOOL_DESCRIPTION = `Save reusable procedures and patterns as skills that survive across sessions. Skills are procedural memory — they capture HOW to do something, not just what happened.
224
+ export const SKILL_TOOL_DESCRIPTION = `Save reusable procedures and patterns as Pi-native skills that survive across sessions. Skills are procedural memory — they capture HOW to do something, not just what happened.
225
225
 
226
226
  WHEN TO CREATE A SKILL:
227
227
  - After completing a complex task that required trial and error or multiple tool calls
228
228
  - When you discover a non-obvious approach that could be reused
229
229
  - When the user teaches you a specific workflow or procedure
230
230
 
231
+ SCOPE:
232
+ - 'global': transferable procedures that can be reused across repositories
233
+ - 'project': procedures tied to this repo's paths, scripts, architecture, deploy flow, or conventions
234
+
231
235
  WHEN TO UPDATE A SKILL (use 'patch'):
232
236
  - You discover a better approach for an existing skill
233
237
  - A pitfall or edge case not covered by the skill
@@ -238,7 +242,7 @@ SKILL FORMAT:
238
242
  - description: one-line summary of when to use it
239
243
  - body: structured with sections — ## When to Use, ## Procedure, ## Pitfalls, ## Verification
240
244
 
241
- ACTIONS: create (new skill), view (read full content), patch (update a section), edit (replace description + body), delete (remove skill).`;
245
+ ACTIONS: create (new skill), view (read full content or list), patch (update a section by skill_id), edit (replace description + body by skill_id), delete (remove by skill_id).`;
242
246
 
243
247
  // ─── Interview prompt (onboarding) ───
244
248
  export const INTERVIEW_PROMPT = `You are conducting a brief onboarding interview with a new user. Your goal is to pre-fill their USER PROFILE so future sessions start with context instead of a blank slate.
@@ -7,7 +7,7 @@
7
7
  * from disk after consolidation completes.
8
8
  */
9
9
 
10
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
10
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
11
11
  import { MemoryStore } from "../store/memory-store.js";
12
12
  import { CONSOLIDATION_PROMPT, ENTRY_DELIMITER } from "../constants.js";
13
13
  import type { ConsolidationResult } from "../types.js";
@@ -7,7 +7,7 @@
7
7
  * keeping us within Pi's intended extension API.
8
8
  */
9
9
 
10
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
10
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
11
11
  import { MemoryStore } from "../store/memory-store.js";
12
12
  import { COMBINED_REVIEW_PROMPT } from "../constants.js";
13
13
  import type { MemoryConfig } from "../types.js";
@@ -8,7 +8,7 @@
8
8
  * - Negative patterns: suppress even if a positive pattern matched
9
9
  */
10
10
 
11
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
11
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
12
12
  import { MemoryStore } from "../store/memory-store.js";
13
13
  import { DatabaseManager } from "../store/db.js";
14
14
  import {
@@ -5,7 +5,7 @@
5
5
  import path from 'node:path';
6
6
  import fs from 'node:fs';
7
7
  import os from 'node:os';
8
- import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
8
+ import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
9
9
  import { DatabaseManager } from '../store/db.js';
10
10
  import { indexAllSessions, getSessionStats } from '../store/session-indexer.js';
11
11
 
@@ -2,7 +2,7 @@
2
2
  * Insights command — /memory-insights shows what's stored in persistent memory.
3
3
  */
4
4
 
5
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
5
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
6
6
  import { MemoryStore } from "../store/memory-store.js";
7
7
 
8
8
  export function registerInsightsCommand(pi: ExtensionAPI, store: MemoryStore, projectStore: MemoryStore | null, projectName: string): void {
@@ -6,7 +6,7 @@
6
6
  * zero value until multiple sessions accumulate facts organically.
7
7
  */
8
8
 
9
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
9
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
10
10
  import { MemoryStore } from "../store/memory-store.js";
11
11
  import { INTERVIEW_PROMPT } from "../constants.js";
12
12
 
@@ -2,7 +2,7 @@
2
2
  * Learn memory tool command — /learn-memory-tool teaches users about the memory system.
3
3
  */
4
4
 
5
- import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
5
+ import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
6
6
 
7
7
  export function registerLearnMemoryCommand(pi: ExtensionAPI): void {
8
8
  pi.registerCommand("learn-memory-tool", {
@@ -34,7 +34,7 @@ export function registerLearnMemoryCommand(pi: ExtensionAPI): void {
34
34
  lines.push(" 🧠 Memory │ MEMORY.md │ 5,000 chars");
35
35
  lines.push(" 👤 User Profile │ USER.md │ 5,000 chars");
36
36
  lines.push(" ⚠️ Failures │ failures.md │ 10,000 chars");
37
- lines.push(" 📚 Skills │ skills/*.md │ Unlimited");
37
+ lines.push(" 📚 Skills │ Pi-native skill dirs │ Unlimited");
38
38
  lines.push(" 💾 Extended │ sessions.db │ Unlimited");
39
39
  lines.push("");
40
40
  lines.push(" Memory: Facts — env details, project conventions, tool quirks");
@@ -126,7 +126,7 @@ export function registerLearnMemoryCommand(pi: ExtensionAPI): void {
126
126
  lines.push(" 8. Session ends → Final flush");
127
127
  lines.push("");
128
128
  lines.push(" Legacy mode: set memoryMode=\"legacy-inject\" to restore full");
129
- lines.push(" MEMORY.md, USER.md, project memory, failure, and skill prompt blocks.");
129
+ lines.push(" MEMORY.md, USER.md, project memory, and failure prompt blocks.");
130
130
  }
131
131
 
132
132
  if (section.startsWith("🏗️")) {
@@ -153,7 +153,7 @@ export function registerLearnMemoryCommand(pi: ExtensionAPI): void {
153
153
  lines.push(" │ memory_search(\"auth\", cat:\"failure\")│");
154
154
  lines.push(" └─────────────────────────────────────┘");
155
155
  lines.push("");
156
- lines.push(" Legacy mode can still inject full memory/skill blocks for users");
156
+ lines.push(" Legacy mode can still inject full memory blocks for users");
157
157
  lines.push(" who explicitly opt into memoryMode=\"legacy-inject\".");
158
158
  }
159
159
 
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * Preview context command — /memory-preview-context shows the policy-only prompt
3
- * or legacy memory/skill blocks appended to the system prompt.
3
+ * or legacy memory blocks appended to the system prompt.
4
4
  */
5
5
 
6
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
6
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
7
7
  import { MemoryStore } from "../store/memory-store.js";
8
- import { SkillStore } from "../store/skill-store.js";
9
8
  import { resolveMemoryPolicyPrompt } from "../prompt-context.js";
10
9
  import type { MemoryConfig } from "../types.js";
11
10
 
@@ -13,12 +12,11 @@ export function registerPreviewContextCommand(
13
12
  pi: ExtensionAPI,
14
13
  store: MemoryStore,
15
14
  projectStore: MemoryStore | null,
16
- skillStore: SkillStore,
17
15
  projectName: string,
18
16
  config: Pick<MemoryConfig, "memoryMode" | "memoryPolicyStyle" | "memoryPolicyCustomText"> = { memoryMode: "policy-only" },
19
17
  ): void {
20
18
  pi.registerCommand("memory-preview-context", {
21
- description: "Preview the memory policy or legacy memory/skill context blocks",
19
+ description: "Preview the memory policy or legacy memory context blocks",
22
20
  handler: async (_args, ctx) => {
23
21
  if (config.memoryMode === "policy-only") {
24
22
  const policyPrompt = resolveMemoryPolicyPrompt(config);
@@ -48,7 +46,6 @@ export function registerPreviewContextCommand(
48
46
 
49
47
  const memoryBlock = store.formatForSystemPrompt();
50
48
  const projectBlock = projectStore ? projectStore.formatProjectBlock(projectName) : "";
51
- const skillIndex = await skillStore.formatIndexForSystemPrompt();
52
49
 
53
50
  const lines: string[] = [];
54
51
  lines.push("");
@@ -56,7 +53,7 @@ export function registerPreviewContextCommand(
56
53
  lines.push(" ║ 👀 Injected Context Preview ║");
57
54
  lines.push(" ╚══════════════════════════════════════════════╝");
58
55
  lines.push("");
59
- lines.push(" This is the memory/skill context appended to the system prompt.");
56
+ lines.push(" This is the memory context appended to the system prompt.");
60
57
  lines.push(" (Core hidden system instructions are NOT shown.)");
61
58
  lines.push("");
62
59
 
@@ -76,16 +73,9 @@ export function registerPreviewContextCommand(
76
73
  lines.push("");
77
74
  }
78
75
 
79
- if (skillIndex) {
80
- blockCount++;
81
- lines.push(" ── SKILL INDEX ─────────────────────────────────────────────");
82
- lines.push(skillIndex);
83
- lines.push("");
84
- }
85
-
86
76
  if (blockCount === 0) {
87
77
  lines.push(" No memory context blocks are currently injected.");
88
- lines.push(" Add memory entries or skills, then run this command again.");
78
+ lines.push(" Add memory entries, then run this command again.");
89
79
  lines.push("");
90
80
  }
91
81
 
@@ -4,7 +4,7 @@
4
4
  * See PLAN.md → "Hermes Source File Reference Map" for source lines.
5
5
  */
6
6
 
7
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
7
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
8
8
  import { MemoryStore } from "../store/memory-store.js";
9
9
  import { FLUSH_PROMPT } from "../constants.js";
10
10
  import type { MemoryConfig } from "../types.js";
@@ -5,13 +5,22 @@
5
5
  * This implements Hermes' "self-evaluation checkpoint" pattern.
6
6
  */
7
7
 
8
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
8
+ import * as path from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
9
11
  import { MemoryStore } from "../store/memory-store.js";
10
12
  import { SkillStore } from "../store/skill-store.js";
11
13
  import { COMBINED_REVIEW_PROMPT, DEFAULT_SKILL_TRIGGER_TOOL_CALLS, ENTRY_DELIMITER } from "../constants.js";
12
14
  import type { MemoryConfig } from "../types.js";
13
15
  import { getMessageText } from "../types.js";
14
16
 
17
+ const proceduralSkillCreatorPath = path.join(
18
+ path.dirname(fileURLToPath(import.meta.url)),
19
+ "..",
20
+ "skills",
21
+ "procedural-skill-creator",
22
+ );
23
+
15
24
  export function setupSkillAutoTrigger(
16
25
  pi: ExtensionAPI,
17
26
  store: MemoryStore,
@@ -71,10 +80,21 @@ export function setupSkillAutoTrigger(
71
80
 
72
81
  const currentMemory = store.getMemoryEntries().join(ENTRY_DELIMITER);
73
82
  const skillIndex = await skillStore.loadIndex();
74
- const skillSummary = skillIndex.map((s) => `${s.fileName}: ${s.name} - ${s.description}`).join("\n");
83
+ const skillSummary = skillIndex
84
+ .map((skill) => `${skill.skillId} [${skill.scope}]: ${skill.displayName || skill.name} - ${skill.description}`)
85
+ .join("\n");
86
+
87
+ const activeProjectName = skillStore.getProjectName();
88
+ const scopeLine = activeProjectName
89
+ ? `Active project context: '${activeProjectName}'. If workflow details depend on this project, use scope='project'; otherwise use scope='global'.`
90
+ : "No active project context detected. Use scope='global' unless the workflow is clearly project-specific.";
75
91
 
76
92
  const prompt = [
77
93
  "This was a complex task that required multiple tool calls. Extract any reusable procedures as skills.",
94
+ "A bundled skill named procedural-skill-creator is loaded for you. Read and follow it before deciding whether to create or patch a skill.",
95
+ "Always pass scope explicitly when creating a skill: scope='global' or scope='project'.",
96
+ "Choose scope='global' for transferable procedures and scope='project' when the workflow depends on this repo's paths, scripts, architecture, deploy steps, or conventions.",
97
+ scopeLine,
78
98
  "",
79
99
  "--- Existing Skills ---",
80
100
  skillSummary || "(none)",
@@ -86,11 +106,11 @@ export function setupSkillAutoTrigger(
86
106
  recentParts.join("\n\n"),
87
107
  "",
88
108
  "If a skill should be created, use the skill tool with action 'create'.",
89
- "If a related skill already exists, use 'patch' to update it.",
109
+ "If a related skill already exists, use 'patch' with its skill_id to update it.",
90
110
  "If nothing reusable happened, say 'Nothing to extract.' and stop.",
91
111
  ].join("\n");
92
112
 
93
- const result = await pi.exec("pi", ["-p", "--no-session", prompt], {
113
+ const result = await pi.exec("pi", ["-p", "--no-session", "--skill", proceduralSkillCreatorPath, prompt], {
94
114
  signal: ctx.signal,
95
115
  timeout: 60000,
96
116
  });
@@ -2,7 +2,7 @@
2
2
  * Skills command — /memory-skills lists all agent-created skills.
3
3
  */
4
4
 
5
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
5
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
6
6
  import { SkillStore } from "../store/skill-store.js";
7
7
 
8
8
  export function registerSkillsCommand(pi: ExtensionAPI, store: SkillStore): void {
@@ -10,6 +10,9 @@ export function registerSkillsCommand(pi: ExtensionAPI, store: SkillStore): void
10
10
  description: "List all agent-created skills (procedural memory)",
11
11
  handler: async (_args, ctx) => {
12
12
  const skills = await store.loadIndex();
13
+ const globalSkills = skills.filter((skill) => skill.scope === "global");
14
+ const projectSkills = skills.filter((skill) => skill.scope === "project");
15
+ const projectName = store.getProjectName();
13
16
 
14
17
  const lines: string[] = [];
15
18
  lines.push("");
@@ -24,11 +27,28 @@ export function registerSkillsCommand(pi: ExtensionAPI, store: SkillStore): void
24
27
  lines.push(" Skills are auto-created after complex tasks,");
25
28
  lines.push(" or you can ask the agent to create one.");
26
29
  } else {
27
- for (const skill of skills) {
28
- lines.push(` 📄 ${skill.name}`);
29
- lines.push(` ${skill.description}`);
30
- lines.push(` file: ${skill.fileName}`);
31
- lines.push("");
30
+ if (globalSkills.length > 0) {
31
+ lines.push(" Global Skills");
32
+ lines.push(" ─────────────");
33
+ for (const skill of globalSkills) {
34
+ lines.push(` 📄 ${skill.displayName || skill.name}`);
35
+ lines.push(` ${skill.description}`);
36
+ lines.push(` id: ${skill.skillId}`);
37
+ lines.push(` path: ${skill.path}`);
38
+ lines.push("");
39
+ }
40
+ }
41
+
42
+ if (projectSkills.length > 0) {
43
+ lines.push(` Project Skills${projectName ? ` (${projectName})` : ""}`);
44
+ lines.push(" ──────────────");
45
+ for (const skill of projectSkills) {
46
+ lines.push(` 📄 ${skill.displayName || skill.name}`);
47
+ lines.push(` ${skill.description}`);
48
+ lines.push(` id: ${skill.skillId}`);
49
+ lines.push(` path: ${skill.path}`);
50
+ lines.push("");
51
+ }
32
52
  }
33
53
  }
34
54
 
@@ -7,7 +7,7 @@
7
7
  * for a project they're not currently in.
8
8
  */
9
9
 
10
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
10
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
11
11
  import type { MemoryConfig } from "../types.js";
12
12
  import * as fs from "node:fs/promises";
13
13
  import * as path from "node:path";
@@ -5,7 +5,7 @@
5
5
 
6
6
  import fs from 'node:fs';
7
7
  import path from 'node:path';
8
- import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
8
+ import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
9
9
  import { DatabaseManager } from '../store/db.js';
10
10
  import {
11
11
  parseMarkdownMemoryEntry,