@oh-my-pi/pi-coding-agent 14.3.0 → 14.4.1

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 (120) hide show
  1. package/CHANGELOG.md +98 -1
  2. package/package.json +7 -7
  3. package/src/autoresearch/prompt.md +1 -1
  4. package/src/commit/agentic/prompts/analyze-file.md +1 -1
  5. package/src/config/model-registry.ts +67 -15
  6. package/src/config/prompt-templates.ts +5 -5
  7. package/src/config/settings-schema.ts +4 -4
  8. package/src/cursor.ts +3 -8
  9. package/src/discovery/helpers.ts +3 -3
  10. package/src/edit/diff.ts +50 -47
  11. package/src/edit/index.ts +86 -57
  12. package/src/edit/line-hash.ts +743 -24
  13. package/src/edit/modes/apply-patch.ts +0 -9
  14. package/src/edit/modes/atom.ts +893 -0
  15. package/src/edit/modes/chunk.ts +14 -24
  16. package/src/edit/modes/hashline.ts +193 -146
  17. package/src/edit/modes/patch.ts +5 -9
  18. package/src/edit/modes/replace.ts +6 -11
  19. package/src/edit/renderer.ts +14 -10
  20. package/src/edit/streaming.ts +50 -16
  21. package/src/exec/bash-executor.ts +2 -4
  22. package/src/export/html/template.generated.ts +1 -1
  23. package/src/export/html/template.js +4 -12
  24. package/src/extensibility/custom-tools/types.ts +2 -0
  25. package/src/extensibility/custom-tools/wrapper.ts +2 -1
  26. package/src/internal-urls/docs-index.generated.ts +2 -2
  27. package/src/lsp/defaults.json +142 -652
  28. package/src/lsp/index.ts +1 -1
  29. package/src/mcp/render.ts +1 -8
  30. package/src/modes/components/assistant-message.ts +4 -0
  31. package/src/modes/components/diff.ts +23 -14
  32. package/src/modes/components/footer.ts +21 -16
  33. package/src/modes/components/session-selector.ts +3 -3
  34. package/src/modes/components/settings-defs.ts +6 -1
  35. package/src/modes/components/todo-reminder.ts +1 -8
  36. package/src/modes/components/tool-execution.ts +1 -4
  37. package/src/modes/controllers/selector-controller.ts +1 -1
  38. package/src/modes/print-mode.ts +8 -0
  39. package/src/prompts/agents/librarian.md +1 -1
  40. package/src/prompts/agents/reviewer.md +4 -4
  41. package/src/prompts/ci-green-request.md +1 -1
  42. package/src/prompts/review-request.md +1 -1
  43. package/src/prompts/system/subagent-system-prompt.md +3 -3
  44. package/src/prompts/system/subagent-yield-reminder.md +11 -0
  45. package/src/prompts/system/system-prompt.md +3 -0
  46. package/src/prompts/tools/ask.md +3 -2
  47. package/src/prompts/tools/ast-edit.md +16 -20
  48. package/src/prompts/tools/ast-grep.md +19 -24
  49. package/src/prompts/tools/atom.md +87 -0
  50. package/src/prompts/tools/chunk-edit.md +37 -161
  51. package/src/prompts/tools/debug.md +4 -5
  52. package/src/prompts/tools/exit-plan-mode.md +4 -5
  53. package/src/prompts/tools/find.md +4 -8
  54. package/src/prompts/tools/github.md +18 -0
  55. package/src/prompts/tools/grep.md +4 -5
  56. package/src/prompts/tools/hashline.md +22 -89
  57. package/src/prompts/tools/{gemini-image.md → image-gen.md} +1 -1
  58. package/src/prompts/tools/inspect-image.md +6 -6
  59. package/src/prompts/tools/lsp.md +1 -1
  60. package/src/prompts/tools/patch.md +12 -19
  61. package/src/prompts/tools/python.md +3 -2
  62. package/src/prompts/tools/read-chunk.md +2 -3
  63. package/src/prompts/tools/read.md +2 -2
  64. package/src/prompts/tools/ssh.md +8 -17
  65. package/src/prompts/tools/todo-write.md +54 -41
  66. package/src/sdk.ts +14 -9
  67. package/src/session/agent-session.ts +25 -2
  68. package/src/session/session-manager.ts +4 -1
  69. package/src/task/executor.ts +43 -48
  70. package/src/task/render.ts +11 -13
  71. package/src/tools/ask.ts +7 -7
  72. package/src/tools/ast-edit.ts +45 -41
  73. package/src/tools/ast-grep.ts +77 -85
  74. package/src/tools/bash.ts +8 -9
  75. package/src/tools/browser.ts +32 -30
  76. package/src/tools/calculator.ts +4 -4
  77. package/src/tools/cancel-job.ts +1 -1
  78. package/src/tools/checkpoint.ts +2 -2
  79. package/src/tools/debug.ts +41 -37
  80. package/src/tools/exit-plan-mode.ts +1 -1
  81. package/src/tools/find.ts +4 -4
  82. package/src/tools/gh-renderer.ts +12 -4
  83. package/src/tools/gh.ts +509 -697
  84. package/src/tools/grep.ts +116 -131
  85. package/src/tools/{gemini-image.ts → image-gen.ts} +459 -60
  86. package/src/tools/index.ts +14 -32
  87. package/src/tools/inspect-image.ts +3 -3
  88. package/src/tools/json-tree.ts +114 -114
  89. package/src/tools/match-line-format.ts +8 -7
  90. package/src/tools/notebook.ts +8 -7
  91. package/src/tools/poll-tool.ts +2 -1
  92. package/src/tools/python.ts +9 -23
  93. package/src/tools/read.ts +32 -25
  94. package/src/tools/render-mermaid.ts +1 -1
  95. package/src/tools/render-utils.ts +18 -0
  96. package/src/tools/renderers.ts +2 -2
  97. package/src/tools/report-tool-issue.ts +3 -2
  98. package/src/tools/resolve.ts +1 -1
  99. package/src/tools/review.ts +12 -10
  100. package/src/tools/search-tool-bm25.ts +2 -4
  101. package/src/tools/ssh.ts +4 -4
  102. package/src/tools/todo-write.ts +172 -147
  103. package/src/tools/vim.ts +14 -15
  104. package/src/tools/write.ts +4 -4
  105. package/src/tools/{submit-result.ts → yield.ts} +11 -13
  106. package/src/utils/edit-mode.ts +2 -1
  107. package/src/utils/file-display-mode.ts +10 -5
  108. package/src/utils/git.ts +9 -5
  109. package/src/utils/shell-snapshot.ts +2 -3
  110. package/src/vim/render.ts +4 -4
  111. package/src/prompts/system/subagent-submit-reminder.md +0 -11
  112. package/src/prompts/tools/gh-issue-view.md +0 -11
  113. package/src/prompts/tools/gh-pr-checkout.md +0 -12
  114. package/src/prompts/tools/gh-pr-diff.md +0 -12
  115. package/src/prompts/tools/gh-pr-push.md +0 -12
  116. package/src/prompts/tools/gh-pr-view.md +0 -11
  117. package/src/prompts/tools/gh-repo-view.md +0 -11
  118. package/src/prompts/tools/gh-run-watch.md +0 -12
  119. package/src/prompts/tools/gh-search-issues.md +0 -11
  120. package/src/prompts/tools/gh-search-prs.md +0 -11
@@ -0,0 +1,87 @@
1
+ Applies precise file edits using full anchors from `read` output (for example `160sr`).
2
+
3
+ Read the file first. Copy the full anchors exactly as shown by `read`.
4
+
5
+ <operations>
6
+ **Top level**: `{ path, edits: […] }` — `path` is shared by all entries. You may still override the file inside `loc` with forms like `other.ts:160sr`.
7
+
8
+ Each entry has one shared locator plus one or more verbs:
9
+ - `loc: "160sr"` — single anchored line
10
+ - `loc: "^"` — beginning of file (only valid with `pre`)
11
+ - `loc: "$"` — end of file (only valid with `post`)
12
+ - `loc: "a.ts:160sr"` — cross-file override inside the locator
13
+
14
+ Verbs:
15
+ - `set: ["…"]` — replace the anchor line
16
+ - `pre: ["…"]` — insert before the anchor line (or at BOF when `loc:"^"`)
17
+ - `post: ["…"]` — insert after the anchor line (or at EOF when `loc:"$"`)
18
+ - `sed: "s/foo/bar/"` — sed-style substitution applied to the anchor line. **Prefer this over `set` for token-level changes**
19
+ Flags: `g` (all occurrences), `i` (case-insensitive), `F` (literal/fixed-string, no regex).
20
+ Delimiter is whatever character follows `s`.
21
+ You **MUST** keep the pattern as short as possible.
22
+
23
+ Combination rules:
24
+ - On a single-anchor `loc`, you may combine `pre`, `set`, and `post` in the same entry.
25
+ - `set: []` on a single-anchor `loc` deletes that line.
26
+ - `set:[""]` is **not** delete — it replaces the line with a blank line.
27
+ </operations>
28
+
29
+ <examples>
30
+ All examples below reference the same file:
31
+
32
+ ```ts title="a.ts"
33
+ {{hline 1 "const tag = \"BAD\";"}}
34
+ {{hline 2 ""}}
35
+ {{hline 3 "function beta(x) {"}}
36
+ {{hline 4 "\tif (x) {"}}
37
+ {{hline 5 "\t\treturn parse(data) || fallback;"}}
38
+ {{hline 6 "\t}"}}
39
+ {{hline 7 "\treturn null;"}}
40
+ {{hline 8 "}"}}
41
+ ```
42
+
43
+ # Replace a line with `set`
44
+ `{path:"a.ts",edits:[{loc:{{href 1 "const tag = \"BAD\";"}},set:["const tag = \"OK\";"]}]}`
45
+
46
+ # Combine `pre` + `set` + `post` in one entry
47
+ `{path:"a.ts",edits:[{loc:{{href 4 "\tif (x) {"}},pre:["\tvalidate();"],set:["\tif (!x) {"],post:["\t\tlog();"]}]}`
48
+
49
+ # Delete a line with `set: []`
50
+ `{path:"a.ts",edits:[{loc:{{href 7 "\treturn null;"}},set:[]}]}`
51
+
52
+ # Preserve a blank line with `set:[""]`
53
+ `{path:"a.ts",edits:[{loc:{{href 2 ""}},set:[""]}]}`
54
+
55
+ # Insert before / after a line
56
+ `{path:"a.ts",edits:[{loc:{{href 3 "function beta(x) {"}},pre:["function gamma() {","\tvalidate();","}",""]}]}`
57
+
58
+ # Substitute one token with `sed` (regex) — preferred for token-level edits
59
+ Use the smallest pattern that uniquely identifies the change.
60
+ `{path:"a.ts",edits:[{loc:{{href 5 "\t\treturn parse(data) || fallback;"}},sed:"s/\\|\\|/??/"}]}`
61
+
62
+ # Substitute every occurrence with `sed` (literal/fixed-string)
63
+ Use the `F` flag to disable regex; the delimiter can be any non-alphanumeric char.
64
+ `{path:"a.ts",edits:[{loc:{{href 5 "\t\treturn parse(data) || fallback;"}},sed:"s|data|input|gF"}]}`
65
+
66
+ # Prepend / append at file edges
67
+ `{path:"a.ts",edits:[{loc:"^",pre:["// Copyright (c) 2026",""]}]}`
68
+ `{path:"a.ts",edits:[{loc:"$",post:["","export const VERSION = \"1.0.0\";"]}]}`
69
+
70
+ # Cross-file override inside `loc`
71
+ `{path:"a.ts",edits:[{loc:"b.ts:{{href 1 "const tag = \"BAD\";"}}",set:["const tag = \"OK\";"]}]}`
72
+ </examples>
73
+
74
+ <critical>
75
+ - Make the minimum exact edit.
76
+ - Copy the full anchors exactly as shown by `read/grep` (for example `160sr`, not just `sr`).
77
+ - `loc` chooses the target. Verbs describe what to do there.
78
+ - On a single-anchor `loc`, you may combine `pre`, `set`, and `post`.
79
+ - `loc:"^"` only supports `pre`. `loc:"$"` only supports `post`.
80
+ - `set: []` deletes the anchored line. `set:[""]` preserves a blank line.
81
+ - Within a single request you may submit edits in any order — the runtime applies them bottom-up so they don't shift each other. After any request that mutates a file, anchors below the mutation are stale on disk; re-read before issuing more edits to that file.
82
+ - `set` operations target the current file content only. Do not try to reference old line text after the file has changed.
83
+ - For token-level edits, prefer `sed` over `set`. The `loc` anchor already pins the line — repeating the entire line in a `set` array invites hallucinated content. Use the smallest `sed` pattern that uniquely identifies the change on that line; do not pad it with surrounding text just to feel safe.
84
+ - When you do use `set`, re-read the anchored line first and copy it verbatim, changing only the required token(s). Anchor identity does not verify line content, so a hallucinated replacement will silently corrupt the file.
85
+ - Text content must be literal file content with matching indentation. If the file uses tabs, use real tabs.
86
+ - You **MUST NOT** use this tool to reformat or clean up unrelated code.
87
+ </critical>
@@ -8,7 +8,7 @@ Call format: `{"edits": [{"path": "file:chunk#ID~", "write": "new body"}, …]}`
8
8
 
9
9
  <rules>
10
10
  - **MUST** inspect first with `read`. Never invent chunk paths or IDs. Copy them from the latest `read` output or edit response.
11
- - `path` format: `file:selector` — e.g. `src/app.ts:fn_foo#ABCD~`. Append `~` for body, `^` for head, or nothing for the whole chunk. Include `#ID` for `write`/`delete`.
11
+ - `path` format: `file:selector` — e.g. `src/app.ts:fn_foo#thth~`. Append `~` for body, `^` for head, or nothing for the whole chunk. Include `#ID` for `write`/`delete`.
12
12
  - If the exact chunk path is unclear, run `read(path="file", sel="?")` and copy a selector from that listing.
13
13
  {{#if chunkAutoIndent}}
14
14
  - Use `\t` for indentation in `content`. Write content at indent-level 0 — the tool re-indents it to match the chunk's position in the file. For example, to replace `~` of a method, write the body starting at column 0:
@@ -75,32 +75,32 @@ Each edit entry has `path` (`file:selector`) plus **exactly one** operation fiel
75
75
  <examples>
76
76
  Given this `read` output for `counter.rs`:
77
77
  ```
78
- | counter.rs·62L·rust·#ZRPW
78
+ | counter.rs·62L·rust·#anth
79
79
  |
80
- @imp#MNHH
80
+ @imp#erhe
81
81
  1 |use std::fmt;
82
82
  |
83
- @struct_Counte#QTSX
83
+ @struct_Counte#onat
84
84
  3^|/// A simple counter that tracks a value and its history.
85
85
  4^|#[derive(Debug, Clone)]
86
86
  5^|pub struct Counter {
87
- -@struct_Counte.field_value#MQTW
87
+ -@struct_Counte.field_value#enth
88
88
  6 | /// The current value.
89
89
  7 | value: i32,
90
- -@struct_Counte.field_max#HJMQ
90
+ -@struct_Counte.field_max#seti
91
91
  8 | /// Maximum allowed value.
92
92
  9 | max: i32,
93
93
  10 |}
94
94
  |
95
- @impl_Counte#VNPP
95
+ @impl_Counte#reha
96
96
  12^|impl Counter {
97
- -@impl_Counte.fn_new#RWZV
97
+ -@impl_Counte.fn_new#ndas
98
98
  13^| /// Creates a new counter starting at zero.
99
99
  14^| pub fn new(max: i32) -> Self {
100
100
  15 | Self { value: 0, max }
101
101
  16 | }
102
102
  17 |
103
- -@impl_Counte.fn_increm#MNHV
103
+ -@impl_Counte.fn_increm#ouer
104
104
  18^| /// Increments the counter by one, clamping at max.
105
105
  19^| pub fn increment(&mut self) {
106
106
  20 | if self.value < self.max {
@@ -108,7 +108,7 @@ Given this `read` output for `counter.rs`:
108
108
  22 | }
109
109
  23 | }
110
110
  24 |
111
- -@impl_Counte.fn_decrem#TTWB
111
+ -@impl_Counte.fn_decrem#arve
112
112
  25^| /// Decrements the counter by one, clamping at zero.
113
113
  26^| pub fn decrement(&mut self) {
114
114
  27 | if self.value > 0 {
@@ -116,167 +116,43 @@ Given this `read` output for `counter.rs`:
116
116
  29 | }
117
117
  30 | }
118
118
  31 |
119
- -@impl_Counte.fn_get#PTNT
119
+ -@impl_Counte.fn_get#arco
120
120
  32^| /// Returns the current value.
121
121
  33^| pub fn get(&self) -> i32 {
122
122
  34 | self.value
123
123
  35 | }
124
124
  36 |}
125
125
  |
126
- @impl_Displa#BNJH
126
+ @impl_Displa#meha
127
127
  38^|impl fmt::Display for Counter {
128
- -@impl_Displa.fn_fmt#NKRN
128
+ -@impl_Displa.fn_fmt#deri
129
129
  39^| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130
130
  40 | write!(f, "Counter({}/{})", self.value, self.max)
131
131
  41 | }
132
132
  42 |}
133
- |
134
- @mod_tests#YWXM
135
- 44^|#[cfg(test)]
136
- 45^|mod tests {
137
- -@mod_tests.chunk#VSMY
138
- 46 | use super::*;
139
- 47 |
140
- -@mod_tests.fn_test_i#YXQZ
141
- 48^| #[test]
142
- 49^| fn test_increment() {
143
- 50 | let mut c = Counter::new(10);
144
- 51 | c.increment();
145
- 52 | assert_eq!(c.get(), 1);
146
- 53 | }
147
- 54 |
148
- -@mod_tests.fn_test_d#XPBQ
149
- 55^| #[test]
150
- 56^| fn test_decrement_at_zero() {
151
- 57 | let mut c = Counter::new(10);
152
- 58 | c.decrement();
153
- 59 | assert_eq!(c.get(), 0);
154
- 60 | }
155
- 61 |}
156
- ```
157
-
158
- **Understanding `^` markers in `read` output:** Lines marked with `^` between the line number and `|` (e.g. ` 3^|`) are **head** lines — doc comments, attributes, and the signature. Lines without `^` (e.g. ` 7 |`) are **body** lines. `~` replaces body lines only, keeping head lines intact.
159
-
160
- **Put body** (`~` — the common case):
161
- ```
162
- { "path": "counter.rs:impl_Counte.fn_increm#MNHV~", "write": "self.value = (self.value + 1).min(self.max);\n" }
163
- ```
164
- Result — only the body (non-`^` lines) changes; the doc comment, signature, and closing `}` are all preserved:
165
- ```
166
- /// Increments the counter by one, clamping at max.
167
- pub fn increment(&mut self) {
168
- self.value = (self.value + 1).min(self.max);
169
- }
170
- ```
171
-
172
- **Write whole chunk** (rewrite signature + doc comment + body):
173
- ```
174
- { "path": "counter.rs:impl_Counte.fn_increm#MNHV", "write": "/// Increments by the given step, clamping at max.\npub fn increment(&mut self, step: i32) {\n\tself.value = (self.value + step).min(self.max);\n}\n" }
175
- ```
176
- Result — **everything** including the doc comment and signature is rewritten. You must include them; omitting them deletes them:
177
- ```
178
- /// Increments by the given step, clamping at max.
179
- pub fn increment(&mut self, step: i32) {
180
- self.value = (self.value + step).min(self.max);
181
- }
182
- ```
183
-
184
- **Write head** (`^` — attributes, doc comments, signature):
185
- ```
186
- { "path": "counter.rs:impl_Counte.fn_get#PTNT^", "write": "/// Returns the current counter value.\n#[inline]\npub fn get(&self) -> i32 {\n" }
187
- ```
188
- Result — the head (all `^` lines + opening brace) changes, body untouched:
189
- ```
190
- /// Returns the current counter value.
191
- #[inline]
192
- pub fn get(&self) -> i32 {
193
- self.value
194
- }
195
- ```
196
-
197
- **Insert before a chunk** (`prepend`):
198
- ```
199
- { "path": "counter.rs:impl_Counte.fn_get", "insert": { "loc": "prepend", "body": "/// Resets the counter to zero.\npub fn reset(&mut self) {\n\tself.value = 0;\n}\n\n" } }
200
- ```
201
- Result — a new method is inserted before `fn get`:
202
- ```
203
- /// Resets the counter to zero.
204
- pub fn reset(&mut self) {
205
- self.value = 0;
206
- }
207
-
208
- /// Returns the current value.
209
- pub fn get(&self) -> i32 {
210
- ```
211
-
212
- **Insert after a chunk** (`append`):
213
- ```
214
- { "path": "counter.rs:struct_Counte", "insert": { "loc": "append", "body": "\nimpl Default for Counter {\n\tfn default() -> Self {\n\t\tSelf { value: 0, max: 100 }\n\t}\n}\n" } }
215
133
  ```
216
- Result a new impl block appears after the struct:
217
- ```
218
- }
219
-
220
- impl Default for Counter {
221
- fn default() -> Self {
222
- Self { value: 0, max: 100 }
223
- }
224
- }
225
-
226
- impl Counter {
227
- ```
228
-
229
- **Insert at start of container body** (`~` + `prepend`):
230
- ```
231
- { "path": "counter.rs:impl_Counte~", "insert": { "loc": "prepend", "body": "/// Creates a counter starting at the given value.\npub fn with_value(value: i32, max: i32) -> Self {\n\tSelf { value: value.min(max), max }\n}\n\n" } }
232
- ```
233
- Result — a new method is added at the top of the impl body, before existing methods:
234
- ```
235
- impl Counter {
236
- /// Creates a counter starting at the given value.
237
- pub fn with_value(value: i32, max: i32) -> Self {
238
- Self { value: value.min(max), max }
239
- }
240
-
241
- /// Creates a new counter starting at zero.
242
- pub fn new(max: i32) -> Self {
243
- ```
244
-
245
- **Insert at end of container body** (`~` + `append`):
246
- ```
247
- { "path": "counter.rs:impl_Counte~", "insert": { "loc": "append", "body": "\n/// Returns true if the counter is at its maximum.\npub fn is_maxed(&self) -> bool {\n\tself.value >= self.max\n}\n" } }
248
- ```
249
- Result — a new method is added at the end of the impl body, before the closing `}`:
250
- ```
251
- pub fn get(&self) -> i32 {
252
- self.value
253
- }
254
-
255
- /// Returns true if the counter is at its maximum.
256
- pub fn is_maxed(&self) -> bool {
257
- self.value >= self.max
258
- }
259
- }
260
- ```
261
-
262
- **Delete a chunk**:
263
- ```
264
- { "path": "counter.rs:impl_Counte.fn_decrem#TTWB", "delete": true }
265
- ```
266
- Result — the method (including its doc comment and signature) is removed.
267
- - Indentation rules (important):
268
- {{#if chunkAutoIndent}}
269
- - Use `\t` for each indent level. The tool converts tabs to the file's actual style (2-space, 4-space, etc.).
270
- {{else}}
271
- - Match the file's real indentation characters in your snippet. The tool preserves your literal tabs/spaces after adding the target region's base indent.
272
- {{/if}}
273
- - Do NOT include the chunk's base indentation — only indent relative to the region's opening level.
274
- - For `write`, the tool strips common leading whitespace shared by all non-empty lines, then adds the target region's base indent. If lines have mixed relative indentation, write them at column 0 so the common-margin cleanup cannot change the structure.
275
- - For `~` of a function: write at column 0, and use `\t` for *relative* nesting. Flat body: `"return x;\n"`. Multiple sibling lines: `"print(a)\nprint(b)\nprint(c)\n"` — all at column 0, the tool adds the function's base indent. Nested body: `"if (cond) {\n\treturn x;\n}\n"` — the `if` is at column 0, the `return` is one tab in. Python example — to replace `~` of `def divide(a, b):`, write: `"if b == 0:\n\treturn None\nreturn a / b\n"` — the `if` and `return a / b` are at column 0, `return None` is one `\t` in.
276
- - For `^`: write at column 0 relative to the head region, just like `~`. A class member's head uses `"/// doc\n#[attr]\npub fn start() {"` — do not include the class/member base indentation.
277
- {{#if chunkAutoIndent}}
278
- - For a top-level item: start at zero indent. Write `"fn foo() {\n\treturn 1;\n}\n"`.
279
- {{else}}
280
- - For a top-level item: start at zero indent. Write `"fn foo() {\n return 1;\n}\n"`.
281
- {{/if}}
134
+ Lines marked `^` between the line number and `|` are **head** lines (doc comments, attributes, signature). Lines without `^` are **body** lines. `~` replaces body lines only; `^` replaces head lines only.
135
+
136
+ # Put body (`~` — the common case)
137
+ `{ "path": "counter.rs:impl_Counte.fn_increm#ouer~", "write": "self.value = (self.value + 1).min(self.max);\n" }`
138
+ Only body changes; doc comment, signature, and closing `}` are preserved.
139
+ # Write whole chunk (rewrite signature + doc + body)
140
+ `{ "path": "counter.rs:impl_Counte.fn_increm#ouer", "write": "/// Increments by the given step, clamping at max.\npub fn increment(&mut self, step: i32) {\n\tself.value = (self.value + step).min(self.max);\n}\n" }`
141
+ Everything is rewritten. Omitting the doc comment or signature deletes them.
142
+ # Write head (`^` — attributes, doc comments, signature)
143
+ `{ "path": "counter.rs:impl_Counte.fn_get#arco^", "write": "/// Returns the current counter value.\n#[inline]\npub fn get(&self) → i32 {\n" }`
144
+ Head changes (all `^` lines + opening brace); body untouched.
145
+ # Insert before a chunk (`prepend`)
146
+ `{ "path": "counter.rs:impl_Counte.fn_get", "insert": { "loc": "prepend", "body": "/// Resets the counter to zero.\npub fn reset(&mut self) {\n\tself.value = 0;\n}\n\n" } }`
147
+ # Insert after a chunk (`append`)
148
+ `{ "path": "counter.rs:struct_Counte", "insert": { "loc": "append", "body": "\nimpl Default for Counter {\n\tfn default() → Self {\n\t\tSelf { value: 0, max: 100 }\n\t}\n}\n" } }`
149
+ # Insert at start of container body (`~` + `prepend`)
150
+ `{ "path": "counter.rs:impl_Counte~", "insert": { "loc": "prepend", "body": "/// Creates a counter starting at the given value.\npub fn with_value(value: i32, max: i32) → Self {\n\tSelf { value: value.min(max), max }\n}\n\n" } }`
151
+ Lands at the top of the impl body, before existing methods.
152
+ # Insert at end of container body (`~` + `append`)
153
+ `{ "path": "counter.rs:impl_Counte~", "insert": { "loc": "append", "body": "\n/// Returns true if the counter is at its maximum.\npub fn is_maxed(&self) → bool {\n\tself.value ≥ self.max\n}\n" } }`
154
+ Lands at the end of the impl body, before the closing `}`.
155
+ # Delete a chunk
156
+ `{ "path": "counter.rs:impl_Counte.fn_decrem#arve", "delete": true }`
157
+ Removes the method including its doc comment and signature.
282
158
  </examples>
@@ -16,14 +16,13 @@ Provides debugger access through the Debug Adapter Protocol (DAP). Use this to l
16
16
  - Adapter availability depends on local binaries. Common built-ins: `gdb`, `lldb-dap`, `python -m debugpy.adapter`, `dlv dap`.
17
17
  </caution>
18
18
 
19
- <example name="launch and inspect hang">
19
+ <examples>
20
+ # Launch and inspect hang
20
21
  1. `debug(action: "launch", program: "./my_app")`
21
22
  2. `debug(action: "set_breakpoint", file: "src/main.c", line: 42)`
22
23
  3. `debug(action: "continue")`
23
24
  4. If the program appears hung: `debug(action: "pause")`
24
25
  5. Inspect state with `threads`, `stack_trace`, `scopes`, and `variables`
25
- </example>
26
-
27
- <example name="raw debugger command through repl">
26
+ # Raw debugger command through repl
28
27
  `debug(action: "evaluate", expression: "info registers", context: "repl")`
29
- </example>
28
+ </examples>
@@ -19,15 +19,14 @@ Use when:
19
19
  Presents plan to user for approval. If approved, plan mode exits with full tool access restored and the plan is renamed to `local://<title>.md`.
20
20
  </output>
21
21
 
22
- <example name="ready">
22
+ <examples>
23
+ # Ready
23
24
  Plan complete at local://PLAN.md, no open questions.
24
25
  → Call `exit_plan_mode` with `{ "title": "WP_MIGRATION_PLAN" }`
25
- </example>
26
-
27
- <example name="unclear">
26
+ # Unclear
28
27
  Unsure about auth method (OAuth vs JWT).
29
28
  → Use `ask` first to clarify, then call `exit_plan_mode`
30
- </example>
29
+ </examples>
31
30
 
32
31
  <avoid>
33
32
  - **MUST NOT** call before plan is written to file
@@ -8,14 +8,10 @@ Finds files using fast pattern matching that works with any codebase size.
8
8
  Matching file paths sorted by modification time (most recent first). Truncated at 1000 entries or 50KB (configurable via `limit`).
9
9
  </output>
10
10
 
11
- <example name="find files">
12
- ```
13
- {
14
- "pattern": "src/**/*.ts",
15
- "limit": 1000
16
- }
17
- ```
18
- </example>
11
+ <examples>
12
+ # Find files
13
+ `{"pattern": "src/**/*.ts", "limit": 1000}`
14
+ </examples>
19
15
 
20
16
  <avoid>
21
17
  For open-ended searches requiring multiple rounds of globbing and grepping, you **MUST** use Task tool instead.
@@ -0,0 +1,18 @@
1
+ GitHub CLI tool with a single op-based dispatch. Wraps `gh` for repository, issue, pull request, search, checkout, push, and Actions watch workflows.
2
+
3
+ <instruction>
4
+ Pick the operation via `op`. Each op uses a subset of the parameters:
5
+ - `repo_view` — Read repository metadata. Optional `repo` (owner/repo) and `branch`. Falls back to the current checkout or default `gh` repo.
6
+ - `issue_view` — Read an issue. Required `issue` (number or URL). Optional `repo`. Set `comments: false` to skip discussion.
7
+ - `pr_view` — Read a pull request, including reviews and inline review comments. Optional `pr` (number, URL, or branch); omitting it targets the current branch's PR. Optional `repo`. Set `comments: false` for a lighter summary.
8
+ - `pr_diff` — Read a pull request diff. Optional `pr`, `repo`. Set `nameOnly: true` for changed file names. Use `exclude` to drop generated paths from the diff.
9
+ - `pr_checkout` — Check a pull request out into a dedicated git worktree. Optional `pr`, `repo`, `branch` (local), `worktree` (path), `force` (reset existing local branch).
10
+ - `pr_push` — Push a checked-out PR branch back to its source branch. Requires the branch to have been checked out via `op: pr_checkout` (carries push metadata). Optional `branch`; defaults to the current checked-out git branch. Optional `forceWithLease`.
11
+ - `search_issues` — Search issues using normal GitHub issue search syntax. Required `query`. Optional `repo`, `limit`.
12
+ - `search_prs` — Search pull requests using normal GitHub PR search syntax. Required `query`. Optional `repo`, `limit`.
13
+ - `run_watch` — Watch a GitHub Actions workflow run. Optional `run` (id or URL). Omitting `run` watches all workflow runs for the current HEAD commit; `branch` falls back to the current branch. Optional `tail` (log lines per failed job). Streams snapshots, fast-fails on the first detected job failure (with a brief grace period to capture concurrent failures), then fetches tailed logs for the failed jobs. The full failed-job logs are saved as a session artifact for on-demand reads.
14
+ </instruction>
15
+
16
+ <output>
17
+ Returns a concise readable summary tailored to the chosen op (repo/issue/PR metadata, diff text, search results, checkout info, push target, or workflow run snapshot). For `run_watch`, the full failed-job logs are saved as a session artifact when failures occur.
18
+ </output>
@@ -2,21 +2,20 @@ Searches files using powerful regex matching.
2
2
 
3
3
  <instruction>
4
4
  - Supports full regex syntax (e.g., `log.*Error`, `function\\s+\\w+`); literal braces need escaping (`interface\\{\\}` for `interface{}` in Go)
5
- - `path` also accepts comma-separated path lists; pair with `glob` when you need a relative file filter in addition to `type`
6
- - For cross-line patterns like `struct \\{[\\s\\S]*?field`, set `multiline: true`
7
- - If the pattern contains a literal `\n`, `multiline` defaults to true automatically
5
+ - `path` is required and accepts a file, directory, glob, comma-separated path list, or internal URL
6
+ - Cross-line patterns are detected from literal `\n` or escaped `\\n` in `pattern`
8
7
  </instruction>
9
8
 
10
9
  <output>
11
10
  {{#if IS_HASHLINE_MODE}}
12
- - Text output is CID prefixed: `LINE#ID:content`
11
+ - Text output is anchor-prefixed: `123th>content` (match) or `123th:content` (context). The 2-letter ID is a content fingerprint.
13
12
  {{else}}
14
13
  {{#if IS_LINE_NUMBER_MODE}}
15
14
  - Text output is line-number-prefixed
16
15
  {{/if}}
17
16
  {{/if}}
18
17
  {{#if IS_CHUNK_MODE}}
19
- - Text output is chunk-path-prefixed: `path:selector>LINE|content`
18
+ - Text output is chunk-path-prefixed: `path:sel>123|content`
20
19
  {{/if}}
21
20
  </output>
22
21
 
@@ -1,22 +1,21 @@
1
- Applies precise file edits using `LINE#ID` anchors from `read` output.
1
+ Applies precise file edits using full anchors from `read` output (for example `160sr`).
2
2
 
3
- Read the file first. Copy anchors exactly from the latest `read` output. After any successful edit, re-read before editing that file again.
3
+ Read the file first. Copy the full anchors exactly as shown by `read`.
4
4
 
5
5
  <operations>
6
6
  **Top level**
7
7
  - `edits` — array of edit entries
8
+ - `path` (optional) — default file path used when an entry omits its own `path`. Lets you share the path across many edits in one request.
8
9
 
9
- **Edit entry**: `{ path, loc, content }` or `{ path, delete: true }` or `{ path, move: "new/path" }`
10
- - `path` — file path
10
+ **Edit entry**: `{ path?, loc, content }`
11
+ - `path` — file path (omit to fall back to the request-level `path`)
11
12
  - `loc` — where to apply the edit (see below)
12
- - `content` — replacement/inserted lines (array of strings preferred, `null` to delete)
13
- - `delete` — delete the file
14
- - `move` — move/rename the file
13
+ - `content` — replacement/inserted lines (`string[]`, one element per line; `null` to delete)
15
14
 
16
15
  **`loc` values**
17
16
  - `"append"` / `"prepend"` — insert at end/start of file
18
- - `{ append: "N#ID" }` / `{ prepend: "N#ID" }` — insert after/before anchored line
19
- - `{ range: { pos: "N#ID", end: "N#ID" } }` — replace inclusive range `pos..end` with new content (set `pos == end` for single-line replace)
17
+ - `{ append: "123th" }` / `{ prepend: "123th" }` — insert after/before anchored line
18
+ - `{ range: { pos: "123th", end: "123th" } }` — replace inclusive range `pos..end` with new content (set `pos == end` for single-line replace)
20
19
  </operations>
21
20
 
22
21
  <examples>
@@ -43,92 +42,26 @@ All examples below reference the same file:
43
42
  {{hline 18 "}"}}
44
43
  ```
45
44
 
46
- <example name="replace a block body">
45
+ # Replace a block body
47
46
  Replace only the catch body. Do not target the shared boundary line `} catch (err) {`.
48
-
49
- ```
50
- {
51
- edits: [{
52
- path: "a.ts",
53
- loc: { range: { pos: {{href 15 "\t\tconsole.error(err);"}}, end: {{href 16 "\t\treturn null;"}} } },
54
- content: [
55
- "\t\tif (isEnoent(err)) return null;",
56
- "\t\tthrow err;"
57
- ]
58
- }]
59
- }
60
- ```
61
- </example>
62
-
63
- <example name="replace whole block including closing brace">
64
- Replace the entire body of `alpha`, including its closing `}`. `end` **MUST** be {{href 7 "}"}} because `content` includes `}`.
65
-
66
- ```
67
- {
68
- edits: [{
69
- path: "a.ts",
70
- loc: { range: { pos: {{href 6 "\tlog();"}}, end: {{href 7 "}"}} } },
71
- content: [
72
- "\tvalidate();",
73
- "\tlog();",
74
- "}"
75
- ]
76
- }]
77
- }
78
- ```
79
-
80
- **Wrong**: `end: {{href 6 "\tlog();"}}` with the same content — line 7 (`}`) survives AND content emits `}`, producing two closing braces.
81
- </example>
82
-
83
- <example name="replace one line">
47
+ `{edits:[{path:"a.ts",loc:{range:{pos:{{href 15 "\t\tconsole.error(err);"}},end:{{href 16 "\t\treturn null;"}}}},content:["\t\tif (isEnoent(err)) return null;","\t\tthrow err;"]}]}`
48
+ # Replace whole block including closing brace
49
+ Replace `alpha`'s entire body including the closing `}`. `end` **MUST** be {{href 7 "}"}} because `content` includes `}`.
50
+ `{edits:[{path:"a.ts",loc:{range:{pos:{{href 6 "\tlog();"}},end:{{href 7 "}"}}}},content:["\tvalidate();","\tlog();","}"]}]}`
51
+ **Wrong**: `end: {{href 6 "\tlog();"}}` — line 7 (`}`) survives AND content emits `}`, producing two closing braces.
52
+ # Replace one line
84
53
  Single-line replace uses `pos == end`.
85
-
86
- ```
87
- {
88
- edits: [{
89
- path: "a.ts",
90
- loc: { range: { pos: {{href 2 "const timeout = 5000;"}}, end: {{href 2 "const timeout = 5000;"}} } },
91
- content: ["const timeout = 30_000;"]
92
- }]
93
- }
94
- ```
95
- </example>
96
-
97
- <example name="delete a range">
98
- ```
99
- {
100
- edits: [{
101
- path: "a.ts",
102
- loc: { range: { pos: {{href 10 "\t// TODO: remove after migration"}}, end: {{href 11 "\tlegacy();"}} } },
103
- content: null
104
- }]
105
- }
106
- ```
107
- </example>
108
-
109
- <example name="insert before sibling">
54
+ `{edits:[{path:"a.ts",loc:{range:{pos:{{href 2 "const timeout = 5000;"}},end:{{href 2 "const timeout = 5000;"}}}},content:["const timeout = 30_000;"]}]}`
55
+ # Delete a range
56
+ `{edits:[{path:"a.ts",loc:{range:{pos:{{href 10 "\t// TODO: remove after migration"}},end:{{href 11 "\tlegacy();"}}}},content:null}]}`
57
+ # Insert before a sibling
110
58
  When adding a sibling declaration, prefer `prepend` on the next declaration.
111
-
112
- ```
113
- {
114
- edits: [{
115
- path: "a.ts",
116
- loc: { prepend: {{href 9 "function beta() {"}} },
117
- content: [
118
- "function gamma() {",
119
- "\tvalidate();",
120
- "}",
121
- ""
122
- ]
123
- }]
124
- }
125
- ```
126
- </example>
59
+ `{edits:[{path:"a.ts",loc:{prepend:{{href 9 "function beta() {"}}},content:["function gamma() {","\tvalidate();","}",""]}]}`
127
60
  </examples>
128
61
 
129
62
  <critical>
130
- - Make the minimum exact edit. Do not rewrite nearby code unless the range requires it.
131
- - Copy anchors exactly as `N#ID` from the latest `read` output.
63
+ - Make the minimum exact edit.
64
+ - Copy the full anchors exactly as shown by `read/grep` (for example `160sr`, not just `sr`).
132
65
  - `range` requires both `pos` and `end`.
133
66
  - **Closing-delimiter check**: when your replacement `content` ends with a closing delimiter (`}`, `*/`, `)`, `]`), compare it against the line immediately after `end` in the file. If they match, extend `end` to include that line — otherwise the original delimiter survives and `content` adds a second copy.
134
67
  - For a range, replace only the body or the whole range — don't split range boundaries.
@@ -1,4 +1,4 @@
1
- Generates or edits images using Gemini image models.
1
+ Generates or edits images using the configured image provider.
2
2
 
3
3
  <instructions>
4
4
  - You **MUST** provide a single detailed `subject` prompt for image generation or editing.
@@ -12,12 +12,12 @@ Inspects an image file with a vision-capable model and returns compact text anal
12
12
  </instruction>
13
13
 
14
14
  <examples>
15
- - OCR with strict formatting:
16
- - `{"path":"screenshots/error.png","question":"Extract all visible text verbatim. Return as bullet list in reading order."}`
17
- - Screenshot debugging:
18
- - `{"path":"screenshots/settings.png","question":"Identify the likely cause of the disabled Save button. Return: (1) observations, (2) likely cause, (3) confidence."}`
19
- - Scene/object question:
20
- - `{"path":"photos/shelf.jpg","question":"List all clearly visible product labels and their shelf positions (top/middle/bottom). If unreadable, say unreadable."}`
15
+ # OCR with strict formatting
16
+ `{"path":"screenshots/error.png","question":"Extract all visible text verbatim. Return as bullet list in reading order."}`
17
+ # Screenshot debugging
18
+ `{"path":"screenshots/settings.png","question":"Identify the likely cause of the disabled Save button. Return: (1) observations, (2) likely cause, (3) confidence."}`
19
+ # Scene/object question
20
+ `{"path":"photos/shelf.jpg","question":"List all clearly visible product labels and their shelf positions (top/middle/bottom). If unreadable, say unreadable."}`
21
21
  </examples>
22
22
 
23
23
  <output>
@@ -36,4 +36,4 @@ Interacts with Language Server Protocol servers for code intelligence.
36
36
  - You **MUST** use `lsp` for symbol-aware operations (rename, find references, go to definition/implementation, code actions) whenever a language server is available — it is safer and more accurate than text-based alternatives.
37
37
  - You **MUST NOT** perform cross-file renames with `ast_edit`, `sed`, `rsed`, or manual edits when `lsp` `rename` can do it. Text-based renames miss shadowing, re-exports, and usages in other files.
38
38
  - Prefer `lsp` `code_actions` for imports, quick-fixes, and refactors the language server already knows how to apply.
39
- </critical>
39
+ </critical>