@oh-my-pi/pi-coding-agent 10.6.1 → 11.0.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +80 -79
  3. package/docs/compaction.md +182 -149
  4. package/docs/config-usage.md +141 -78
  5. package/docs/custom-tools.md +45 -16
  6. package/docs/extension-loading.md +56 -954
  7. package/docs/extensions.md +192 -51
  8. package/docs/hooks.md +109 -70
  9. package/docs/python-repl.md +52 -19
  10. package/docs/rpc.md +43 -19
  11. package/docs/sdk.md +270 -211
  12. package/docs/session-tree-plan.md +60 -417
  13. package/docs/session.md +104 -39
  14. package/docs/skills.md +59 -95
  15. package/docs/theme.md +139 -110
  16. package/docs/tree.md +42 -33
  17. package/docs/tui.md +226 -80
  18. package/package.json +8 -9
  19. package/src/capability/index.ts +3 -4
  20. package/src/cli/args.ts +4 -4
  21. package/src/cli/grep-cli.ts +1 -1
  22. package/src/commit/agentic/index.ts +4 -3
  23. package/src/commit/git/index.ts +2 -3
  24. package/src/commit/map-reduce/index.ts +2 -1
  25. package/src/config/prompt-templates.ts +2 -0
  26. package/src/config/settings-schema.ts +30 -7
  27. package/src/config/settings.ts +0 -14
  28. package/src/config.ts +2 -2
  29. package/src/discovery/agents.ts +36 -0
  30. package/src/discovery/index.ts +1 -0
  31. package/src/exa/mcp-client.ts +3 -3
  32. package/src/ipy/executor.ts +5 -7
  33. package/src/ipy/gateway-coordinator.ts +1 -1
  34. package/src/ipy/kernel.ts +20 -15
  35. package/src/ipy/prelude.py +1 -1
  36. package/src/ipy/runtime.ts +7 -6
  37. package/src/lsp/lspmux.ts +3 -3
  38. package/src/main.ts +6 -8
  39. package/src/mcp/tool-bridge.ts +19 -9
  40. package/src/modes/components/assistant-message.ts +2 -2
  41. package/src/modes/components/hook-editor.ts +4 -4
  42. package/src/modes/components/settings-defs.ts +37 -2
  43. package/src/modes/components/tool-execution.ts +7 -7
  44. package/src/modes/controllers/command-controller.ts +2 -2
  45. package/src/modes/controllers/event-controller.ts +4 -7
  46. package/src/modes/controllers/input-controller.ts +4 -4
  47. package/src/modes/controllers/selector-controller.ts +1 -0
  48. package/src/modes/interactive-mode.ts +3 -5
  49. package/src/modes/rpc/rpc-mode.ts +8 -9
  50. package/src/patch/index.ts +6 -6
  51. package/src/prompts/agents/explore.md +2 -2
  52. package/src/prompts/agents/frontmatter.md +5 -5
  53. package/src/prompts/agents/plan.md +3 -2
  54. package/src/prompts/agents/reviewer.md +1 -1
  55. package/src/prompts/system/system-prompt.md +1 -3
  56. package/src/sdk.ts +13 -9
  57. package/src/session/agent-session.ts +6 -4
  58. package/src/session/compaction/compaction.ts +3 -3
  59. package/src/session/session-manager.ts +8 -9
  60. package/src/ssh/connection-manager.ts +4 -4
  61. package/src/system-prompt.ts +2 -6
  62. package/src/task/agents.ts +1 -1
  63. package/src/task/executor.ts +31 -8
  64. package/src/task/index.ts +14 -35
  65. package/src/task/omp-command.ts +3 -1
  66. package/src/task/output-manager.ts +20 -6
  67. package/src/task/parallel.ts +3 -3
  68. package/src/task/render.ts +16 -2
  69. package/src/task/types.ts +13 -20
  70. package/src/task/worktree.ts +3 -3
  71. package/src/tools/ask.ts +3 -8
  72. package/src/tools/fetch.ts +2 -2
  73. package/src/tools/gemini-image.ts +5 -6
  74. package/src/tools/grep.ts +5 -5
  75. package/src/tools/index.ts +12 -5
  76. package/src/tools/read.ts +1 -1
  77. package/src/tools/todo-write.ts +2 -3
  78. package/src/utils/frontmatter.ts +1 -1
  79. package/src/utils/image-resize.ts +1 -1
  80. package/src/utils/timings.ts +3 -2
  81. package/src/web/scrapers/github.ts +2 -2
  82. package/src/web/scrapers/utils.ts +2 -3
  83. package/src/web/scrapers/youtube.ts +2 -3
  84. package/src/web/search/auth.ts +5 -6
  85. package/src/web/search/providers/anthropic.ts +3 -2
  86. package/src/utils/terminal-notify.ts +0 -37
package/docs/session.md CHANGED
@@ -5,10 +5,12 @@ Sessions are stored as JSONL (JSON Lines) files. Each line is a JSON object with
5
5
  ## File Location
6
6
 
7
7
  ```
8
- ~/.omp/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonl
8
+ ~/.omp/agent/sessions/--<cwd>--/<timestamp>_<sessionId>.jsonl
9
9
  ```
10
10
 
11
- Where `<path>` is the working directory with `/` replaced by `-`.
11
+ Default base directory comes from `getAgentDir()` (overridable via `PI_CODING_AGENT_DIR`).
12
+ `<cwd>` is the working directory with the leading slash removed and `/`, `\`, `:` replaced by `-`.
13
+ `<timestamp>` is ISO-8601 with `:`/`.` replaced by `-`. `sessionId` is a snowflake hex string.
12
14
 
13
15
  ## Session Version
14
16
 
@@ -16,14 +18,16 @@ Sessions have a version field in the header:
16
18
 
17
19
  - **Version 1**: Linear entry sequence (legacy, auto-migrated on load)
18
20
  - **Version 2**: Tree structure with `id`/`parentId` linking
21
+ - **Version 3**: Renamed legacy `hookMessage` role to `custom`
19
22
 
20
- Existing v1 sessions are automatically migrated to v2 when loaded.
23
+ Existing sessions are automatically migrated to the latest version when loaded.
21
24
 
22
25
  ## Type Definitions
23
26
 
24
- - [`src/core/session-manager.ts`](../src/core/session-manager.ts) - Session entry types
25
- - [`packages/agent/src/types.ts`](../../agent/src/types.ts) - `AgentMessage`, `Attachment`, `ThinkingLevel`
26
- - [`packages/ai/src/types.ts`](../../ai/src/types.ts) - `UserMessage`, `AssistantMessage`, `ToolResultMessage`, `Usage`, `ToolCall`
27
+ - [`src/session/session-manager.ts`](../src/session/session-manager.ts) - Session entry types and `SessionManager`
28
+ - [`src/session/messages.ts`](../src/session/messages.ts) - Custom message roles and LLM conversion
29
+ - [`packages/agent/src/types.ts`](../../agent/src/types.ts) - `AgentMessage`, `ThinkingLevel`
30
+ - [`packages/ai/src/types.ts`](../../ai/src/types.ts) - `Message`, content blocks, `Usage`, `ToolCall`
27
31
 
28
32
  ## Entry Base
29
33
 
@@ -32,7 +36,7 @@ All entries (except `SessionHeader`) extend `SessionEntryBase`:
32
36
  ```typescript
33
37
  interface SessionEntryBase {
34
38
  type: string;
35
- id: string; // 8-char hex ID
39
+ id: string; // Short snowflake suffix (8 hex chars)
36
40
  parentId: string | null; // Parent entry ID (null for first entry)
37
41
  timestamp: string; // ISO timestamp
38
42
  }
@@ -42,28 +46,39 @@ interface SessionEntryBase {
42
46
 
43
47
  ### SessionHeader
44
48
 
45
- First line of the file. Metadata only, not part of the tree (no `id`/`parentId`).
49
+ First line of the file. Metadata only, not part of the tree (no `id`/`parentId`). `version` is absent in v1 sessions.
46
50
 
47
51
  ```json
48
- { "type": "session", "version": 2, "id": "uuid", "timestamp": "2024-12-03T14:00:00.000Z", "cwd": "/path/to/project" }
52
+ {
53
+ "type": "session",
54
+ "version": 3,
55
+ "id": "a1b2c3d4e5f60001",
56
+ "timestamp": "2024-12-03T14:00:00.000Z",
57
+ "cwd": "/path/to/project",
58
+ "title": "Optional title"
59
+ }
49
60
  ```
50
61
 
51
- For sessions with a parent (created via `/branch` or `newSession({ parentSession })`):
62
+ For sessions with a parent (created via `/branch`, `newSession({ parentSession })`, or fork operations):
52
63
 
53
64
  ```json
54
65
  {
55
66
  "type": "session",
56
- "version": 2,
57
- "id": "uuid",
67
+ "version": 3,
68
+ "id": "a1b2c3d4e5f60001",
58
69
  "timestamp": "2024-12-03T14:00:00.000Z",
59
70
  "cwd": "/path/to/project",
60
71
  "parentSession": "/path/to/original/session.jsonl"
61
72
  }
62
73
  ```
63
74
 
75
+ `parentSession` is an opaque string used for lineage tracking (typically a session file path).
76
+
64
77
  ### SessionMessageEntry
65
78
 
66
- A message in the conversation. The `message` field contains an `AgentMessage`.
79
+ A message in the conversation. The `message` field contains an `AgentMessage`,
80
+ including base LLM messages plus coding-agent custom roles (bash/python execution,
81
+ custom/legacy `hookMessage` messages from v2 sessions, file mentions, etc.).
67
82
 
68
83
  ```json
69
84
  {"type":"message","id":"a1b2c3d4","parentId":"prev1234","timestamp":"2024-12-03T14:00:01.000Z","message":{"role":"user","content":"Hello"}}
@@ -73,7 +88,7 @@ A message in the conversation. The `message` field contains an `AgentMessage`.
73
88
 
74
89
  ### ModelChangeEntry
75
90
 
76
- Emitted when the user switches models mid-session.
91
+ Emitted when the user switches models mid-session. `model` is stored as `provider/modelId`.
77
92
 
78
93
  ```json
79
94
  {
@@ -81,8 +96,8 @@ Emitted when the user switches models mid-session.
81
96
  "id": "d4e5f6g7",
82
97
  "parentId": "c3d4e5f6",
83
98
  "timestamp": "2024-12-03T14:05:00.000Z",
84
- "provider": "openai",
85
- "modelId": "gpt-4o"
99
+ "model": "openai/gpt-4o",
100
+ "role": "default"
86
101
  }
87
102
  ```
88
103
 
@@ -100,6 +115,8 @@ Emitted when the user changes the thinking/reasoning level.
100
115
  }
101
116
  ```
102
117
 
118
+ `thinkingLevel` matches `ThinkingLevel` from `packages/agent` (e.g., `off`, `minimal`, `low`, `medium`, `high`, `xhigh`).
119
+
103
120
  ### CompactionEntry
104
121
 
105
122
  Created when context is compacted. Stores a summary of earlier messages.
@@ -111,19 +128,23 @@ Created when context is compacted. Stores a summary of earlier messages.
111
128
  "parentId": "e5f6g7h8",
112
129
  "timestamp": "2024-12-03T14:10:00.000Z",
113
130
  "summary": "User discussed X, Y, Z...",
131
+ "shortSummary": "Quick recap...",
114
132
  "firstKeptEntryId": "c3d4e5f6",
115
- "tokensBefore": 50000
133
+ "tokensBefore": 50000,
134
+ "fromExtension": false
116
135
  }
117
136
  ```
118
137
 
119
138
  Optional fields:
120
139
 
121
- - `details`: Compaction-implementation specific data (e.g., file operations for default implementation, or custom data for custom hook implementations)
122
- - `fromHook`: `true` if generated by a hook, `false`/`undefined` if omp-generated
140
+ - `details`: Compaction-implementation specific data (extension data, version markers, etc.)
141
+ - `shortSummary`: Short-form summary for UI contexts
142
+ - `preserveData`: Hook/extension data to persist across compaction
143
+ - `fromExtension`: `true` if generated by an extension, `false`/`undefined` if pi-generated
123
144
 
124
145
  ### BranchSummaryEntry
125
146
 
126
- Created when switching branches via `/tree` with an LLM generated summary of the left branch up to the common ancestor. Captures context from the abandoned path.
147
+ Created when switching branches with an LLM-generated summary of the abandoned path. Captures context from the previous branch.
127
148
 
128
149
  ```json
129
150
  {
@@ -136,14 +157,16 @@ Created when switching branches via `/tree` with an LLM generated summary of the
136
157
  }
137
158
  ```
138
159
 
160
+ `fromId` is the branch point entry id; when branching from the root it is `"root"`.
161
+
139
162
  Optional fields:
140
163
 
141
- - `details`: File tracking data (`{ readFiles: string[], modifiedFiles: string[] }`) for default implementation, arbitrary for custom implementation
142
- - `fromHook`: `true` if generated by a hook
164
+ - `details`: Extension-specific data (not sent to LLM)
165
+ - `fromExtension`: `true` if generated by an extension
143
166
 
144
167
  ### CustomEntry
145
168
 
146
- Hook state persistence. Does NOT participate in LLM context.
169
+ Extension state persistence. Does NOT participate in LLM context.
147
170
 
148
171
  ```json
149
172
  {
@@ -151,16 +174,16 @@ Hook state persistence. Does NOT participate in LLM context.
151
174
  "id": "h8i9j0k1",
152
175
  "parentId": "g7h8i9j0",
153
176
  "timestamp": "2024-12-03T14:20:00.000Z",
154
- "customType": "my-hook",
177
+ "customType": "my-extension",
155
178
  "data": { "count": 42 }
156
179
  }
157
180
  ```
158
181
 
159
- Use `customType` to identify your hook's entries on reload.
182
+ Use `customType` to identify your extension's entries on reload.
160
183
 
161
184
  ### CustomMessageEntry
162
185
 
163
- Hook-injected messages that DO participate in LLM context.
186
+ Extension-injected messages that DO participate in LLM context.
164
187
 
165
188
  ```json
166
189
  {
@@ -168,7 +191,7 @@ Hook-injected messages that DO participate in LLM context.
168
191
  "id": "i9j0k1l2",
169
192
  "parentId": "h8i9j0k1",
170
193
  "timestamp": "2024-12-03T14:25:00.000Z",
171
- "customType": "my-hook",
194
+ "customType": "my-extension",
172
195
  "content": "Injected context...",
173
196
  "display": true
174
197
  }
@@ -177,8 +200,8 @@ Hook-injected messages that DO participate in LLM context.
177
200
  Fields:
178
201
 
179
202
  - `content`: String or `(TextContent | ImageContent)[]` (same as UserMessage)
180
- - `display`: `true` = show in TUI with purple styling, `false` = hidden
181
- - `details`: Optional hook-specific metadata (not sent to LLM)
203
+ - `display`: `true` = show in TUI with distinct styling, `false` = hidden
204
+ - `details`: Optional extension-specific metadata (not sent to LLM)
182
205
 
183
206
  ### LabelEntry
184
207
 
@@ -197,6 +220,37 @@ User-defined bookmark/marker on an entry.
197
220
 
198
221
  Set `label` to `undefined` to clear a label.
199
222
 
223
+ ### TtsrInjectionEntry
224
+
225
+ Tracks which time-traveling stream rules were injected during the session.
226
+
227
+ ```json
228
+ {
229
+ "type": "ttsr_injection",
230
+ "id": "k1l2m3n4",
231
+ "parentId": "j0k1l2m3",
232
+ "timestamp": "2024-12-03T14:31:00.000Z",
233
+ "injectedRules": ["rule-a", "rule-b"]
234
+ }
235
+ ```
236
+
237
+ ### SessionInitEntry
238
+
239
+ Captures initial context for subagent sessions (debugging/replay). Not used in LLM context building.
240
+
241
+ ```json
242
+ {
243
+ "type": "session_init",
244
+ "id": "l2m3n4o5",
245
+ "parentId": "k1l2m3n4",
246
+ "timestamp": "2024-12-03T14:32:00.000Z",
247
+ "systemPrompt": "...",
248
+ "task": "Initial task...",
249
+ "tools": ["bash", "read"],
250
+ "outputSchema": { "type": "object" }
251
+ }
252
+ ```
253
+
200
254
  ## Tree Structure
201
255
 
202
256
  Entries form a tree:
@@ -217,13 +271,15 @@ Entries form a tree:
217
271
  `buildSessionContext()` walks from the current leaf to the root, producing the message list for the LLM:
218
272
 
219
273
  1. Collects all entries on the path
220
- 2. Extracts current model and thinking level settings
274
+ 2. Extracts current model map, thinking level, and injected TTSR rules
221
275
  3. If a `CompactionEntry` is on the path:
222
276
  - Emits the summary first
223
277
  - Then messages from `firstKeptEntryId` to compaction
224
278
  - Then messages after compaction
225
279
  4. Converts `BranchSummaryEntry` and `CustomMessageEntry` to appropriate message formats
226
280
 
281
+ Return value is a `SessionContext` containing `messages`, `models`, `thinkingLevel`, and `injectedTtsrRules`.
282
+
227
283
  ## Parsing Example
228
284
 
229
285
  ```typescript
@@ -231,7 +287,6 @@ const text = await Bun.file("session.jsonl").text();
231
287
  const entries = Bun.JSONL.parse(text);
232
288
 
233
289
  for (const entry of entries) {
234
-
235
290
  switch (entry.type) {
236
291
  case "session":
237
292
  console.log(`Session v${entry.version ?? 1}: ${entry.id}`);
@@ -249,13 +304,19 @@ for (const entry of entries) {
249
304
  console.log(`[${entry.id}] Custom (${entry.customType}): ${JSON.stringify(entry.data)}`);
250
305
  break;
251
306
  case "custom_message":
252
- console.log(`[${entry.id}] Hook message (${entry.customType}): ${entry.content}`);
307
+ console.log(`[${entry.id}] Custom message (${entry.customType}): ${entry.content}`);
308
+ break;
309
+ case "ttsr_injection":
310
+ console.log(`[${entry.id}] TTSR rules: ${entry.injectedRules.join(", ")}`);
311
+ break;
312
+ case "session_init":
313
+ console.log(`[${entry.id}] Init: ${entry.tools.join(", ")}`);
253
314
  break;
254
315
  case "label":
255
316
  console.log(`[${entry.id}] Label "${entry.label}" on ${entry.targetId}`);
256
317
  break;
257
318
  case "model_change":
258
- console.log(`[${entry.id}] Model: ${entry.provider}/${entry.modelId}`);
319
+ console.log(`[${entry.id}] Model: ${entry.model} (${entry.role ?? "default"})`);
259
320
  break;
260
321
  case "thinking_level_change":
261
322
  console.log(`[${entry.id}] Thinking: ${entry.thinkingLevel}`);
@@ -279,22 +340,26 @@ Key methods for working with sessions programmatically:
279
340
 
280
341
  - `appendMessage(message)` - Add message
281
342
  - `appendThinkingLevelChange(level)` - Record thinking change
282
- - `appendModelChange(provider, modelId)` - Record model change
283
- - `appendCompaction(summary, firstKeptEntryId, tokensBefore, details?, fromHook?)` - Add compaction
284
- - `appendCustomEntry(customType, data?)` - Hook state (not in context)
285
- - `appendCustomMessageEntry(customType, content, display, details?)` - Hook message (in context)
343
+ - `appendModelChange(model, role?)` - Record model change (`model` = `provider/modelId`)
344
+ - `appendSessionInit(init)` - Record initial subagent context
345
+ - `appendCompaction(summary, shortSummary, firstKeptEntryId, tokensBefore, details?, fromExtension?, preserveData?)`
346
+ - `appendCustomEntry(customType, data?)` - Extension state (not in context)
347
+ - `appendCustomMessageEntry(customType, content, display, details?)` - Extension message (in context)
348
+ - `appendTtsrInjection(ruleNames)` - Record injected TTSR rules
286
349
  - `appendLabelChange(targetId, label)` - Set/clear label
287
350
 
288
351
  ### Tree Navigation
289
352
 
290
353
  - `getLeafId()` - Current position
354
+ - `getLeafEntry()` - Current leaf entry
291
355
  - `getEntry(id)` - Get entry by ID
292
- - `getPath(fromId?)` - Walk from entry to root
356
+ - `getBranch(fromId?)` - Walk from entry to root
293
357
  - `getTree()` - Get full tree structure
294
358
  - `getChildren(parentId)` - Get direct children
295
359
  - `getLabel(id)` - Get label for entry
296
360
  - `branch(entryId)` - Move leaf to earlier entry
297
- - `branchWithSummary(entryId, summary, details?, fromHook?)` - Branch with context summary
361
+ - `branchWithSummary(entryId | null, summary, details?, fromExtension?)` - Branch with context summary
362
+ - `resetLeaf()` - Move leaf to before first entry
298
363
 
299
364
  ### Context
300
365
 
package/docs/skills.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Skills are self-contained capability packages that the agent loads on-demand. A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks.
6
6
 
7
- OMP implements the [Agent Skills standard](https://agentskills.io/specification).
7
+ OMP follows the [Agent Skills](https://agentskills.io/specification) SKILL.md format (YAML frontmatter + markdown body) and exposes skills via `skill://` URLs.
8
8
 
9
9
  **Example use cases:**
10
10
  - Web search and content extraction (Brave Search API)
@@ -87,99 +87,78 @@ cd /path/to/skill && npm install
87
87
 
88
88
  ### Frontmatter Fields
89
89
 
90
- Per the [Agent Skills specification](https://agentskills.io/specification#frontmatter-required):
90
+ | Field | Required | Notes |
91
+ |-------|----------|-------|
92
+ | `name` | No | Defaults to the skill directory name. Use lowercase + hyphens for compatibility. |
93
+ | `description` | Yes (OMP/custom), recommended everywhere | Used for skill matching and shown in the system prompt. |
91
94
 
92
- | Field | Required | Constraints |
93
- |-------|----------|-------------|
94
- | `name` | Yes | Max 64 chars. Lowercase a-z, 0-9, hyphens only. Must match parent directory name. |
95
- | `description` | Yes | Max 1024 chars. What the skill does and when to use it. |
96
- | `license` | No | License name or reference to bundled license file. |
97
- | `compatibility` | No | Max 500 chars. Environment requirements (system packages, network access, etc.). |
98
- | `metadata` | No | Arbitrary key-value mapping for additional metadata. |
99
- | `allowed-tools` | No | Space-delimited list of pre-approved tools (experimental). |
95
+ OMP ignores additional frontmatter fields, but other tooling may use them.
100
96
 
101
- #### Name Validation
97
+ #### Naming Guidance
102
98
 
103
- The `name` field must:
104
- - Be 1-64 characters
105
- - Contain only lowercase letters (a-z), numbers (0-9), and hyphens
106
- - Not start or end with a hyphen
107
- - Not contain consecutive hyphens (--)
108
- - Match the parent directory name exactly
109
-
110
- Valid: `pdf-processing`, `data-analysis`, `code-review`
111
- Invalid: `PDF-Processing`, `-pdf`, `pdf--processing`
112
-
113
- #### Description Best Practices
114
-
115
- The `description` is critical. It determines when the agent loads the skill. Be specific about both what it does and when to use it.
116
-
117
- Good:
118
- ```yaml
119
- description: Extracts text and tables from PDF files, fills PDF forms, and merges multiple PDFs. Use when working with PDF documents or when the user mentions PDFs, forms, or document extraction.
120
- ```
121
-
122
- Poor:
123
- ```yaml
124
- description: Helps with PDFs.
125
- ```
99
+ OMP does not enforce naming rules, but skill names must match exactly for `skill://<name>` and `/skill:<name>` lookups. For cross-tool compatibility, keep names lowercase, hyphenated, and aligned with the directory name.
126
100
 
127
101
  ### File References
128
102
 
129
- Use relative paths from the skill directory:
103
+ Use `skill://` URLs to reference files inside a skill directory:
130
104
 
131
105
  ```markdown
132
- See [the reference guide](references/REFERENCE.md) for details.
106
+ Read the full skill:
107
+ \`\`\`
108
+ skill://my-skill
109
+ \`\`\`
133
110
 
134
- Run the extraction script:
135
- \`\`\`bash
136
- ./scripts/extract.py input.pdf
111
+ Read a reference file:
112
+ \`\`\`
113
+ skill://my-skill/references/api-reference.md
137
114
  \`\`\`
138
115
  ```
139
116
 
140
117
  ## Skill Locations
141
118
 
142
- Skills are discovered from these locations (later wins on name collision):
119
+ Skills are discovered from these sources (first match wins on name collisions):
120
+
121
+ - OMP user: `~/.omp/agent/skills/<skill>/SKILL.md` (legacy alias: `~/.pi/agent/skills/...`)
122
+ - OMP project: `<cwd>/.omp/skills/<skill>/SKILL.md` (legacy alias: `<cwd>/.pi/skills/...`)
123
+ - Claude Code: `~/.claude/skills/<skill>/SKILL.md` and `<cwd>/.claude/skills/<skill>/SKILL.md`
124
+ - Agents standard: `~/.agents/skills/<skill>/SKILL.md`
125
+ - Codex CLI: `~/.codex/skills/<skill>/SKILL.md` and `<cwd>/.codex/skills/<skill>/SKILL.md`
126
+ - Custom directories from `skills.customDirectories` (scanned recursively)
143
127
 
144
- 1. `~/.codex/skills/**/SKILL.md` (Codex CLI, recursive)
145
- 2. `~/.claude/skills/*/SKILL.md` (Claude Code user, one level)
146
- 3. `<cwd>/.claude/skills/*/SKILL.md` (Claude Code project, one level)
147
- 4. `~/.omp/agent/skills/**/SKILL.md` (OMP user, recursive)
148
- 5. `<cwd>/.omp/skills/**/SKILL.md` (OMP project, recursive)
128
+ Discovery skips hidden directories and `node_modules`, and respects `.gitignore`, `.ignore`, and `.fdignore` rules.
149
129
 
150
130
  ## Configuration
151
131
 
152
- Configure skill loading in `~/.omp/agent/settings.json`:
153
-
154
- ```json
155
- {
156
- "skills": {
157
- "enabled": true,
158
- "enableCodexUser": true,
159
- "enableClaudeUser": true,
160
- "enableClaudeProject": true,
161
- "enablePiUser": true,
162
- "enablePiProject": true,
163
- "customDirectories": ["~/my-skills-repo"],
164
- "ignoredSkills": ["deprecated-skill"],
165
- "includeSkills": ["git-*", "docker"]
166
- }
167
- }
132
+ Global settings live in `~/.omp/agent/config.yml` (migrated from legacy `settings.json`). Project overrides live in `<cwd>/.omp/settings.json` or `<cwd>/.pi/settings.json`.
133
+
134
+ ```yaml
135
+ skills:
136
+ enabled: true
137
+ enableSkillCommands: true
138
+ enableCodexUser: true
139
+ enableClaudeUser: true
140
+ enableClaudeProject: true
141
+ enablePiUser: true
142
+ enablePiProject: true
143
+ customDirectories: []
144
+ ignoredSkills: []
145
+ includeSkills: []
168
146
  ```
169
147
 
170
148
  | Setting | Default | Description |
171
149
  |---------|---------|-------------|
172
150
  | `enabled` | `true` | Master toggle for all skills |
151
+ | `enableSkillCommands` | `true` | Register `/skill:<name>` commands in interactive mode |
173
152
  | `enableCodexUser` | `true` | Load from `~/.codex/skills/` |
174
153
  | `enableClaudeUser` | `true` | Load from `~/.claude/skills/` |
175
154
  | `enableClaudeProject` | `true` | Load from `<cwd>/.claude/skills/` |
176
- | `enableOmpUser` | `true` | Load from `~/.omp/agent/skills/` |
177
- | `enableOmpProject` | `true` | Load from `<cwd>/.omp/skills/` |
178
- | `customDirectories` | `[]` | Additional directories to scan (supports `~` expansion) |
179
- | `ignoredSkills` | `[]` | Glob patterns to exclude (e.g., `["deprecated-*", "test-skill"]`) |
180
- | `includeSkills` | `[]` | Glob patterns to include (empty = all; e.g., `["git-*", "docker"]`) |
155
+ | `enablePiUser` | `true` | Load from `~/.omp/agent/skills/` (or `~/.pi/agent/skills/`) |
156
+ | `enablePiProject` | `true` | Load from `<cwd>/.omp/skills/` (or `<cwd>/.pi/skills/`) |
157
+ | `customDirectories` | `[]` | Additional directories to scan recursively (use absolute paths) |
158
+ | `ignoredSkills` | `[]` | Glob patterns to exclude (e.g., `"deprecated-*"`) |
159
+ | `includeSkills` | `[]` | Glob patterns to include (empty = all) |
181
160
 
182
- **Note:** `ignoredSkills` takes precedence over both `includeSkills` in settings and the `--skills` CLI flag. A skill matching any ignore pattern will be excluded regardless of include patterns.
161
+ **Note:** `ignoredSkills` takes precedence over both `includeSkills` and the `--skills` CLI flag.
183
162
 
184
163
  ### CLI Filtering
185
164
 
@@ -200,25 +179,19 @@ This overrides the `includeSkills` setting for the current session.
200
179
 
201
180
  ## How Skills Work
202
181
 
203
- 1. At startup, omp scans skill locations and extracts names + descriptions
204
- 2. The system prompt includes available skills in XML format
205
- 3. When a task matches, the agent uses `read` to load the full SKILL.md
206
- 4. The agent follows the instructions, using relative paths to reference scripts/assets
182
+ 1. At startup, omp scans enabled skill locations and filters them by settings and CLI flags.
183
+ 2. If the `read` tool is available, skill names + descriptions are injected into the system prompt as XML.
184
+ 3. When a task matches a skill, the agent loads it with `read skill://<name>` or `skill://<name>/<path>`.
185
+ 4. When skills are preloaded (e.g., Task tool with explicit skills), their full contents are inlined under `<preloaded_skills>` and no `read` call is needed.
207
186
 
208
- This is progressive disclosure: only descriptions are always in context, full instructions load on-demand.
187
+ This is progressive disclosure: only descriptions are always in context, full instructions load on-demand unless explicitly preloaded.
209
188
 
210
- ## Validation Warnings
189
+ ## Warnings
211
190
 
212
- OMP validates skills against the Agent Skills standard and warns (but still loads) non-compliant skills:
191
+ OMP emits warnings when:
213
192
 
214
- - Name doesn't match parent directory
215
- - Name exceeds 64 characters
216
- - Name contains invalid characters
217
- - Name starts/ends with hyphen or has consecutive hyphens
218
- - Description missing or exceeds 1024 characters
219
- - Unknown frontmatter fields
220
-
221
- Name collisions (same name from different locations) warn and keep the first skill found.
193
+ - A skill directory or file cannot be read
194
+ - Two skills share the same name (the first loaded wins; later ones are skipped)
222
195
 
223
196
  ## Example: Web Search Skill
224
197
 
@@ -258,12 +231,6 @@ cd /path/to/brave-search && npm install
258
231
  \`\`\`
259
232
  ```
260
233
 
261
- ## Compatibility
262
-
263
- **Claude Code**: OMP reads skills from `~/.claude/skills/*/SKILL.md`. The `allowed-tools` and `model` frontmatter fields are ignored.
264
-
265
- **Codex CLI**: OMP reads skills from `~/.codex/skills/` recursively. Hidden files/directories and symlinks are skipped.
266
-
267
234
  ## Skill Repositories
268
235
 
269
236
  For inspiration and ready-to-use skills:
@@ -278,13 +245,10 @@ CLI:
278
245
  omp --no-skills
279
246
  ```
280
247
 
281
- Settings (`~/.omp/agent/settings.json`):
282
- ```json
283
- {
284
- "skills": {
285
- "enabled": false
286
- }
287
- }
248
+ Settings:
249
+ ```yaml
250
+ skills:
251
+ enabled: false
288
252
  ```
289
253
 
290
254
  Use the granular `enable*` flags to disable individual sources (e.g., `enableClaudeUser: false` to skip `~/.claude/skills`).