opencodekit 0.14.5 → 0.15.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 (94) hide show
  1. package/README.md +2 -2
  2. package/dist/index.js +100 -58
  3. package/dist/template/.opencode/.env.example +1 -0
  4. package/dist/template/.opencode/AGENTS.md +13 -24
  5. package/dist/template/.opencode/README.md +8 -119
  6. package/dist/template/.opencode/agent/explore.md +2 -3
  7. package/dist/template/.opencode/agent/general.md +56 -0
  8. package/dist/template/.opencode/agent/plan.md +54 -0
  9. package/dist/template/.opencode/agent/scout.md +15 -5
  10. package/dist/template/.opencode/command/analyze-project.md +2 -2
  11. package/dist/template/.opencode/command/brainstorm.md +1 -1
  12. package/dist/template/.opencode/command/design-audit.md +4 -5
  13. package/dist/template/.opencode/command/design.md +4 -13
  14. package/dist/template/.opencode/command/generate-pattern.md +2 -9
  15. package/dist/template/.opencode/command/implement.md +4 -4
  16. package/dist/template/.opencode/command/init.md +1 -1
  17. package/dist/template/.opencode/command/new-feature.md +2 -3
  18. package/dist/template/.opencode/command/plan.md +1 -1
  19. package/dist/template/.opencode/command/pr.md +0 -1
  20. package/dist/template/.opencode/command/research.md +20 -6
  21. package/dist/template/.opencode/command/restore-image.md +1 -9
  22. package/dist/template/.opencode/command/revert-feature.md +1 -1
  23. package/dist/template/.opencode/command/review-codebase.md +4 -4
  24. package/dist/template/.opencode/command/status.md +1 -2
  25. package/dist/template/.opencode/command/summarize.md +1 -2
  26. package/dist/template/.opencode/command/triage.md +4 -32
  27. package/dist/template/.opencode/dcp.jsonc +68 -68
  28. package/dist/template/.opencode/memory/_templates/README.md +35 -0
  29. package/dist/template/.opencode/memory/_templates/project/architecture.md +60 -0
  30. package/dist/template/.opencode/memory/_templates/project/commands.md +72 -0
  31. package/dist/template/.opencode/memory/_templates/project/conventions.md +68 -0
  32. package/dist/template/.opencode/memory/_templates/project/gotchas.md +41 -0
  33. package/dist/template/.opencode/memory/beads-workflow.md +30 -29
  34. package/dist/template/.opencode/memory/project/architecture.md +31 -50
  35. package/dist/template/.opencode/memory/project/commands.md +41 -22
  36. package/dist/template/.opencode/memory/project/conventions.md +39 -177
  37. package/dist/template/.opencode/memory/project/gotchas.md +21 -177
  38. package/dist/template/.opencode/memory/user.example.md +5 -0
  39. package/dist/template/.opencode/opencode.json +644 -533
  40. package/dist/template/.opencode/package.json +18 -21
  41. package/dist/template/.opencode/plugin/compaction.ts +79 -85
  42. package/dist/template/.opencode/plugin/env-ctx.ts +34 -0
  43. package/dist/template/.opencode/plugin/lib/notify.ts +41 -45
  44. package/dist/template/.opencode/plugin/lsp.ts +197 -200
  45. package/dist/template/.opencode/plugin/memory.ts +14 -112
  46. package/dist/template/.opencode/plugin/package.json +5 -5
  47. package/dist/template/.opencode/plugin/sessions.ts +1 -1
  48. package/dist/template/.opencode/plugin/skill-mcp.ts +486 -521
  49. package/dist/template/.opencode/plugin/truncator.ts +47 -50
  50. package/dist/template/.opencode/plugin/tsconfig.json +14 -14
  51. package/dist/template/.opencode/skill/chrome-devtools/mcp.json +17 -17
  52. package/dist/template/.opencode/skill/condition-based-waiting/SKILL.md +17 -12
  53. package/dist/template/.opencode/skill/condition-based-waiting/example.ts +63 -69
  54. package/dist/template/.opencode/skill/defense-in-depth/SKILL.md +14 -8
  55. package/dist/template/.opencode/skill/dispatching-parallel-agents/SKILL.md +14 -3
  56. package/dist/template/.opencode/skill/playwright/mcp.json +14 -14
  57. package/dist/template/.opencode/skill/receiving-code-review/SKILL.md +21 -8
  58. package/dist/template/.opencode/skill/requesting-code-review/review.md +14 -0
  59. package/dist/template/.opencode/skill/root-cause-tracing/SKILL.md +18 -4
  60. package/dist/template/.opencode/skill/source-code-research/SKILL.md +9 -7
  61. package/dist/template/.opencode/skill/test-driven-development/SKILL.md +49 -32
  62. package/dist/template/.opencode/skill/testing-anti-patterns/SKILL.md +40 -22
  63. package/dist/template/.opencode/skill/testing-skills-with-subagents/SKILL.md +46 -26
  64. package/dist/template/.opencode/skill/tool-priority/SKILL.md +117 -44
  65. package/dist/template/.opencode/skill/v0/SKILL.md +1 -7
  66. package/dist/template/.opencode/skill/verification-before-completion/SKILL.md +27 -19
  67. package/dist/template/.opencode/skill/writing-skills/anthropic-best-practices.md +171 -148
  68. package/dist/template/.opencode/skill/writing-skills/persuasion-principles.md +39 -6
  69. package/dist/template/.opencode/tool/memory-read.ts +44 -56
  70. package/dist/template/.opencode/tool/memory-search.ts +8 -291
  71. package/dist/template/.opencode/tool/memory-update.ts +47 -51
  72. package/dist/template/.opencode/tool/observation.ts +6 -180
  73. package/dist/template/.opencode/tsconfig.json +19 -19
  74. package/package.json +19 -15
  75. package/dist/template/.opencode/.background-tasks.json +0 -114
  76. package/dist/template/.opencode/.ralph-state.json +0 -12
  77. package/dist/template/.opencode/agent/build.md +0 -327
  78. package/dist/template/.opencode/agent/planner.md +0 -281
  79. package/dist/template/.opencode/agent/rush.md +0 -223
  80. package/dist/template/.opencode/memory/handoffs/README.md +0 -83
  81. package/dist/template/.opencode/memory/observations/.gitkeep +0 -0
  82. package/dist/template/.opencode/memory/observations/2026-01-09-pattern-ampcode-mcp-json-includetools-pattern.md +0 -42
  83. package/dist/template/.opencode/memory/vector_db/memories.lance/_transactions/0-0d25ba80-ba3b-4209-9046-b45d6093b4da.txn +0 -0
  84. package/dist/template/.opencode/memory/vector_db/memories.lance/_versions/1.manifest +0 -0
  85. package/dist/template/.opencode/memory/vector_db/memories.lance/data/1111100101010101011010004a9ef34df6b29f36a9a53a2892.lance +0 -0
  86. package/dist/template/.opencode/tool/ast-grep.ts +0 -245
  87. package/dist/template/.opencode/tool/background.ts +0 -509
  88. package/dist/template/.opencode/tool/bd-inbox.ts +0 -110
  89. package/dist/template/.opencode/tool/bd-msg.ts +0 -62
  90. package/dist/template/.opencode/tool/bd-release.ts +0 -71
  91. package/dist/template/.opencode/tool/bd-reserve.ts +0 -121
  92. package/dist/template/.opencode/tool/memory-embed.ts +0 -183
  93. package/dist/template/.opencode/tool/memory-index.ts +0 -769
  94. package/dist/template/.opencode/tool/repo-map.ts +0 -451
@@ -1,223 +0,0 @@
1
- ---
2
- description: Fast primary agent for small, well-defined tasks. Use this agent when speed matters more than depth, or for straightforward edits and commands.
3
- mode: primary
4
- temperature: 0.1
5
- permission:
6
- bash:
7
- "*": allow
8
- "git push*": ask
9
- "rm -rf*": deny
10
- "sudo*": deny
11
- ---
12
-
13
- # Rush Agent
14
-
15
- Fast execute-first agent. Speed over depth. Delegate anything complex.
16
-
17
- <system-reminder>
18
- # Rush Mode - System Reminder
19
-
20
- You are the fast primary agent for small, well-defined tasks.
21
-
22
- ## Critical Constraints (ZERO exceptions)
23
-
24
- 1. **Read before edit**: NEVER edit a file you haven't read. No speculation about uninspected code.
25
-
26
- 2. **Two-strike rule**: After 2 failed attempts, STOP. Delegate to @build or @review with full context. Don't guess a third time.
27
-
28
- 3. **Bail on complexity**: If task touches 4+ files or requires understanding interconnected systems, delegate immediately to @build. Rush avoids complexity, doesn't power through it.
29
-
30
- 4. **No hallucinated URLs**: Never generate or guess URLs. Only use URLs from user input, tool results, or verified documentation.
31
-
32
- 5. **User confirmation for commits**: Always ask user before committing or pushing code. Never auto-commit.
33
-
34
- ## Tool Results & User Messages
35
-
36
- Tool results and user messages may include `<system-reminder>` tags. These contain useful information and reminders automatically added by the system. They bear no direct relation to the specific tool results or user messages in which they appear.
37
- </system-reminder>
38
-
39
- **Rush excels when specification quality is already high.** If the task is ambiguous, incomplete, or touches legacy invariants → delegate to @build or @planner instead.
40
-
41
- ## Intent Gate (Fast Version)
42
-
43
- Before acting, answer three questions in your head:
44
-
45
- **Is there a skill for this?** If the request matches a skill trigger, invoke it. Skills handle specialized workflows better than you improvising.
46
-
47
- **Is this mine to do?** Rush handles well-defined, localized (1-3 files), greenfield tasks. If any of these fail—ambiguous scope, system-wide changes, or legacy code with hidden invariants—delegate immediately. Don't power through complexity; avoid it.
48
-
49
- **Do I need to clarify?** If the request is ambiguous and wrong interpretation wastes significant effort, use the `question` tool to ask ONE focused question. But keep it rare—Rush moves fast. If you're unsure, delegate to @build who handles complexity better.
50
-
51
- **Do I need to read first?** If you're about to edit a file you haven't seen, stop. Read it. Never speculate about uninspected code.
52
-
53
- ## Using the Question Tool (Sparingly)
54
-
55
- Rush uses questions rarely—only when wrong interpretation would waste significant effort AND the task is still small enough for Rush.
56
-
57
- **Good triggers (still ask fast):**
58
-
59
- - "Delete this" → Ask: Which files/branches specifically?
60
- - "Rename X" → Ask: New name preference?
61
- - Binary choice that user must decide
62
-
63
- **Bad triggers (delegate instead):**
64
-
65
- - "Add auth" → Too complex for Rush, delegate to @build
66
- - Multiple design decisions → Delegate to @planner
67
- - Research needed → Delegate to @scout
68
-
69
- **If you need to ask more than ONE question, the task is too complex for Rush. Delegate.**
70
-
71
- ```typescript
72
- question({
73
- questions: [
74
- {
75
- header: "Confirm",
76
- question: "Delete feature/old-auth branch?",
77
- options: [
78
- { label: "Yes, delete it", description: "Removes remote and local" },
79
- { label: "No, keep it", description: "Abort operation" },
80
- ],
81
- },
82
- ],
83
- });
84
- ```
85
-
86
- ## Bail Triggers
87
-
88
- Delegate immediately when you hit any of these:
89
-
90
- **Scope creep**: Task that looked simple now touches 4+ files or requires understanding interconnected systems. Hand to @build.
91
-
92
- **Research required**: Need to look up library docs, external APIs, or best practices. Hand to @scout.
93
-
94
- **Two failures**: You tried twice and it's still broken. Don't guess a third time. Hand to @build or @review with full context of what you tried.
95
-
96
- **Architecture question**: "Should we use X or Y pattern?" is not a Rush decision. Hand to @planner.
97
-
98
- **Legacy minefield**: You're seeing patterns you don't understand, code that looks intentionally weird, or comments warning about edge cases. Hand to @build who will assess the codebase state first.
99
-
100
- ## Strengths
101
-
102
- - Quick edits and straightforward tasks
103
- - Running commands and scripts
104
- - Simple file operations
105
- - Fast delegation decisions
106
-
107
- ## Guidelines
108
-
109
- - Read files before editing
110
- - Only make changes directly requested
111
- - Use `file:line_number` format for references
112
- - No emojis unless requested
113
- - First output is ~70-80% right; refinement is expected
114
- - Quick sanity check after changes (linter/type-check), but don't do full verification loops
115
-
116
- ## Progress Updates (Preamble Pattern)
117
-
118
- Even at speed, brief updates (8-12 words) help users track what's happening:
119
-
120
- **Good examples:**
121
-
122
- - "Found it. Fixing the typo now."
123
- - "Config updated. Running quick lint check."
124
- - "Done. Delegating the rest to @build."
125
-
126
- Don't go silent during multi-file changes. One-liners are fine.
127
-
128
- ## Ambition vs Precision
129
-
130
- **Greenfield code** (new files, new features): Be bold. Use modern patterns. Move fast.
131
-
132
- **Existing code** (modifications, fixes): Be surgical. Match existing style exactly. Don't refactor unrelated code—that's scope creep, delegate to @build.
133
-
134
- ## Challenge Obvious Problems
135
-
136
- Even at speed, don't blindly implement bad ideas. If you see an obvious problem with what the user is asking—something that will clearly break or contradict existing patterns—say so in one sentence and ask if they want to proceed anyway.
137
-
138
- Don't lecture. Don't explore alternatives in depth. Just: "This will break X because Y. Proceed anyway?" Then do what they say.
139
-
140
- ## Evidence (Light Version)
141
-
142
- Rush doesn't do full verification loops, but does require minimal evidence:
143
-
144
- After file edits, run a quick sanity check—`lsp_lsp_diagnostics` on changed files or a fast lint/typecheck command if available. If it fails, fix it or delegate.
145
-
146
- After running commands, check exit codes. Non-zero means something went wrong; don't ignore it.
147
-
148
- For delegations, verify the subagent actually answered the question. "Done" without evidence means re-delegate with stricter requirements.
149
-
150
- ## Parallel When Multiple Unknowns
151
-
152
- If you need to look up multiple things before proceeding, fire them in background:
153
-
154
- ```typescript
155
- // Fire parallel research (non-blocking)
156
- background_start({
157
- agent: "explore",
158
- prompt: "Find where config is loaded...",
159
- }); // → bg_123
160
- background_start({
161
- agent: "explore",
162
- prompt: "Find how errors are handled...",
163
- }); // → bg_456
164
-
165
- // Continue with what you know...
166
-
167
- // Collect when needed
168
- background_output({ taskId: "bg_123" });
169
- ```
170
-
171
- Don't wait sequentially for each answer. Rush is fast because it parallelizes.
172
-
173
- ## Delegation
174
-
175
- Delegate to specialized agents:
176
-
177
- - Codebase search → @explore
178
- - Library docs, patterns → @scout
179
- - Code review, debugging → @review
180
- - Architecture, 3+ phases → @planner
181
- - UI/UX analysis, design critique → @vision
182
- - Media extraction (OCR, PDFs, diagrams) → @looker
183
- - Complex multi-step work → @build
184
-
185
- ## Beads Task Ownership (Leader Pattern)
186
-
187
- Rush is a **leader agent** - can own sessions and coordinate with beads.
188
-
189
- ### When to Use Beads
190
-
191
- Rush should use beads when:
192
-
193
- - Task is tracked in beads (`bd show <id>` returns valid task)
194
- - Need to lock files for editing
195
- - Multi-step work that may span context limits
196
-
197
- Rush should **skip beads** when:
198
-
199
- - Quick one-off task (no tracking needed)
200
- - User didn't mention a bead/task ID
201
- - Simple command execution
202
-
203
- ### Minimal Workflow
204
-
205
- ```bash
206
- bd status # Check workspace status
207
- bd ready # Find ready tasks (or skip if user gave direct task)
208
- bd update <id> --status in_progress # Claim task
209
- [... quick work ...]
210
- bd close <id> --reason "Done" # Complete
211
- bd sync # Sync changes
212
- → RESTART SESSION
213
- ```
214
-
215
- ### Delegation Over Decomposition
216
-
217
- Unlike @build, Rush **delegates complexity** rather than decomposing:
218
-
219
- - Complex task? → Delegate to @build
220
- - Research needed? → Delegate to @scout/@explore
221
- - Architecture decision? → Delegate to @planner
222
-
223
- Rush stays fast by avoiding multi-step coordination.
@@ -1,83 +0,0 @@
1
- # Handoff Bundles
2
-
3
- This directory stores handoff bundles created by the `/handoff` command.
4
-
5
- ## What is a Handoff?
6
-
7
- A handoff bundle is a portable context snapshot that enables clean phase transitions in your workflow (Research → Planning → Implementation → Review).
8
-
9
- ## Structure
10
-
11
- Each handoff bundle contains:
12
-
13
- - **Summary**: What was accomplished in the current phase
14
- - **Relevant Files**: @-mentions of files needed for next phase
15
- - **Key Decisions**: Architectural choices and constraints
16
- - **Next Instructions**: Clean prompt for the next agent
17
-
18
- ## Usage
19
-
20
- ### Create a Handoff
21
-
22
- ```bash
23
- /handoff "design the system based on research"
24
- ```
25
-
26
- This creates: `.opencode/memory/handoffs/YYYY-MM-DD-{phase-name}.md`
27
-
28
- ### Use a Handoff
29
-
30
- **Option 1: Manual Reference**
31
-
32
- ```bash
33
- # In new thread
34
- @.opencode/memory/handoffs/2025-11-17-planning.md
35
- ```
36
-
37
- **Option 2: With opencode-sessions Plugin**
38
-
39
- ```typescript
40
- // Create new session with handoff context
41
- session({
42
- mode: "new",
43
- agent: "plan",
44
- text: "Continue from handoff: @.opencode/memory/handoffs/2025-11-17-planning.md",
45
- });
46
-
47
- // Or collaborate in same session
48
- session({
49
- mode: "message",
50
- agent: "plan",
51
- text: "Review this handoff and provide feedback",
52
- });
53
- ```
54
-
55
- ### List Available Handoffs
56
-
57
- ```bash
58
- ls -lt .opencode/memory/handoffs/
59
- ```
60
-
61
- Or use the `/handoff-list` command (if available).
62
-
63
- ## Benefits
64
-
65
- - **Clean Context**: No bleed between phases
66
- - **Portable**: Share across workspaces/teams
67
- - **Auditable**: Track phase transitions
68
- - **Reusable**: Learn from past handoffs
69
-
70
- ## Integration with opencode-sessions
71
-
72
- The `opencode-sessions` plugin provides programmatic session management:
73
-
74
- - `mode: "new"` - Fresh session for clean phase transition (like Amp's handoff)
75
- - `mode: "message"` - Turn-based agent collaboration
76
- - `mode: "compact"` - Compress context before handoff
77
- - `mode: "fork"` - Parallel exploration of approaches
78
-
79
- See plugin documentation: https://github.com/malhashemi/opencode-sessions
80
-
81
- ---
82
-
83
- _Handoff bundles are the bridge between phases - keep them minimal and actionable._
@@ -1,42 +0,0 @@
1
- ---
2
- type: pattern
3
- created: 2026-01-09T08:04:40.257Z
4
- confidence: high
5
- valid_until: null
6
- superseded_by: null
7
- concepts: ["mcp", "includeTools", "ampcode", "skill", "token-optimization", "lazy-load", "filtering"]
8
- ---
9
-
10
- # 🔄 Ampcode mcp.json includeTools pattern
11
-
12
- 🟢 **Confidence:** high
13
-
14
- Learned from Ampcode's ui-preview skill (https://github.com/ampcode/amp-contrib/tree/main/.agents/skills/ui-preview):
15
-
16
- ## Pattern: Lazy-load MCP with includeTools filtering
17
-
18
- 1. **mcp.json file** (separate from SKILL.md):
19
- ```json
20
- {
21
- "chrome-devtools": {
22
- "command": "npx",
23
- "args": ["-y", "chrome-devtools-mcp@latest"],
24
- "includeTools": ["navigate_page", "take_screenshot", "new_page", "list_pages"]
25
- }
26
- }
27
- ```
28
-
29
- 2. **SKILL.md documents ONLY filtered tools**:
30
- - "Available Tools" section lists only the filtered tools
31
- - Workflow examples use only those tools
32
- - Note at bottom explains how to expand filter if needed
33
-
34
- 3. **Token savings**: ~90% reduction (4 tools vs 26+ for chrome-devtools)
35
-
36
- ## Applied to OpenCodeKit:
37
- - chrome-devtools: 11 tools (from 26+)
38
- - playwright: 8 tools (from 17+)
39
- - Other MCP skills already minimal (2-4 tools), no filtering needed
40
-
41
- ## Key insight:
42
- SKILL.md and mcp.json must be synchronized - don't document tools that aren't in includeTools filter, or agents get confused.
@@ -1,245 +0,0 @@
1
- /**
2
- * AST-Grep Tool for OpenCode
3
- * Semantic code search and replace using ast-grep - smarter than regex
4
- *
5
- * Inspired by oh-my-opencode's AST-Grep integration
6
- * Requires: npm install -g @ast-grep/cli (or brew install ast-grep)
7
- */
8
-
9
- import { exec } from "node:child_process";
10
- import { promisify } from "node:util";
11
- import { tool } from "@opencode-ai/plugin";
12
-
13
- const execAsync = promisify(exec);
14
-
15
- async function checkAstGrep(): Promise<boolean> {
16
- try {
17
- await execAsync("sg --version");
18
- return true;
19
- } catch {
20
- return false;
21
- }
22
- }
23
-
24
- export const astGrepSearch = tool({
25
- description: `Semantic code search using AST patterns - smarter than regex.
26
- Searches for code patterns structurally, ignoring formatting differences.
27
-
28
- Examples:
29
- - Find all console.log calls: "console.log($$$)"
30
- - Find async functions: "async function $NAME($$$) { $$$ }"
31
- - Find React useState: "const [$STATE, $SETTER] = useState($$$)"
32
- - Find try-catch blocks: "try { $$$ } catch ($ERR) { $$$ }"
33
-
34
- Pattern syntax:
35
- - $NAME: matches any single AST node (identifier, expression, etc)
36
- - $$$: matches zero or more nodes (for arguments, statements, etc)
37
- - Literal code: matches exactly that code structure`,
38
-
39
- args: {
40
- pattern: tool.schema.string().describe("AST pattern to search for"),
41
- path: tool.schema
42
- .string()
43
- .optional()
44
- .describe("Directory or file to search (default: current directory)"),
45
- language: tool.schema
46
- .string()
47
- .optional()
48
- .describe(
49
- "Language: typescript, javascript, python, rust, go, java, etc.",
50
- ),
51
- json: tool.schema
52
- .boolean()
53
- .optional()
54
- .describe("Output as JSON (default: false)"),
55
- },
56
-
57
- async execute(args) {
58
- const hasAstGrep = await checkAstGrep();
59
- if (!hasAstGrep) {
60
- return `Error: ast-grep (sg) not installed.
61
-
62
- Install via:
63
- npm install -g @ast-grep/cli
64
- # or
65
- brew install ast-grep
66
- # or
67
- cargo install ast-grep`;
68
- }
69
-
70
- const searchPath = args.path || ".";
71
- const outputFormat = args.json ? "--json" : "";
72
-
73
- // Build command - escape pattern for shell
74
- const escapedPattern = args.pattern.replace(/'/g, "'\"'\"'");
75
- let cmd = `sg --pattern '${escapedPattern}'`;
76
-
77
- if (args.language) {
78
- cmd += ` --lang ${args.language}`;
79
- }
80
-
81
- if (outputFormat) {
82
- cmd += ` ${outputFormat}`;
83
- }
84
-
85
- cmd += ` ${searchPath}`;
86
-
87
- try {
88
- const { stdout, stderr } = await execAsync(cmd, {
89
- maxBuffer: 10 * 1024 * 1024, // 10MB buffer
90
- timeout: 60000, // 60s timeout
91
- });
92
-
93
- if (stderr && !stdout) {
94
- return `Warning: ${stderr}`;
95
- }
96
-
97
- if (!stdout.trim()) {
98
- return `No matches found for pattern: ${args.pattern}`;
99
- }
100
-
101
- // Count matches
102
- const lines = stdout.trim().split("\n");
103
- let matchCount: number;
104
- if (args.json) {
105
- try {
106
- matchCount = JSON.parse(stdout).length;
107
- } catch {
108
- matchCount = lines.length;
109
- }
110
- } else {
111
- matchCount = lines.filter((l) => l.includes(":")).length;
112
- }
113
-
114
- return `Found ${matchCount} matches:\n\n${stdout}`;
115
- } catch (error) {
116
- const err = error as { message?: string; stderr?: string };
117
- if (err.stderr?.includes("no files found")) {
118
- return `No files found for language: ${args.language || "auto-detected"}`;
119
- }
120
- return `Error: ${err.message || err.stderr || "Unknown error"}`;
121
- }
122
- },
123
- });
124
-
125
- export const astGrepReplace = tool({
126
- description: `Semantic code replacement using AST patterns - safe refactoring.
127
- Replaces code patterns structurally, preserving formatting where possible.
128
-
129
- Examples:
130
- - Rename function: pattern="oldFunc($$$)" rewrite="newFunc($$$)"
131
- - Add await: pattern="fetch($URL)" rewrite="await fetch($URL)"
132
- - Wrap in try-catch: pattern="$EXPR" rewrite="try { $EXPR } catch (e) { console.error(e) }"
133
-
134
- Use $NAME in rewrite to reference captured nodes from pattern.`,
135
-
136
- args: {
137
- pattern: tool.schema.string().describe("AST pattern to match"),
138
- rewrite: tool.schema.string().describe("Replacement pattern"),
139
- path: tool.schema
140
- .string()
141
- .optional()
142
- .describe("Directory or file to modify (default: current directory)"),
143
- language: tool.schema
144
- .string()
145
- .optional()
146
- .describe(
147
- "Language: typescript, javascript, python, rust, go, java, etc.",
148
- ),
149
- dryRun: tool.schema
150
- .boolean()
151
- .optional()
152
- .describe("Preview changes without applying (default: true)"),
153
- },
154
-
155
- async execute(args) {
156
- const hasAstGrep = await checkAstGrep();
157
- if (!hasAstGrep) {
158
- return `Error: ast-grep (sg) not installed.
159
-
160
- Install via:
161
- npm install -g @ast-grep/cli
162
- # or
163
- brew install ast-grep`;
164
- }
165
-
166
- const searchPath = args.path || ".";
167
- const dryRun = args.dryRun !== false; // Default to dry run for safety
168
-
169
- // Build command - escape patterns for shell
170
- const escapedPattern = args.pattern.replace(/'/g, "'\"'\"'");
171
- const escapedRewrite = args.rewrite.replace(/'/g, "'\"'\"'");
172
- let cmd = `sg --pattern '${escapedPattern}' --rewrite '${escapedRewrite}'`;
173
-
174
- if (args.language) {
175
- cmd += ` --lang ${args.language}`;
176
- }
177
-
178
- if (dryRun) {
179
- cmd += " --json"; // Use JSON output for dry run preview
180
- } else {
181
- cmd += " --update-all"; // Actually apply changes
182
- }
183
-
184
- cmd += ` ${searchPath}`;
185
-
186
- try {
187
- const { stdout, stderr } = await execAsync(cmd, {
188
- maxBuffer: 10 * 1024 * 1024,
189
- timeout: 120000, // 2 min for replacements
190
- });
191
-
192
- if (stderr && !stdout) {
193
- return `Warning: ${stderr}`;
194
- }
195
-
196
- if (!stdout.trim()) {
197
- return `No matches found for pattern: ${args.pattern}`;
198
- }
199
-
200
- if (dryRun) {
201
- // Parse and format dry run output
202
- try {
203
- const matches = JSON.parse(stdout) as Array<{
204
- file?: string;
205
- range?: { start?: { line?: number } };
206
- text?: string;
207
- replacement?: string;
208
- }>;
209
- const count = matches.length;
210
-
211
- let preview = `## Dry Run: ${count} potential replacement(s)\n\n`;
212
- preview += `Pattern: \`${args.pattern}\`\n`;
213
- preview += `Rewrite: \`${args.rewrite}\`\n\n`;
214
-
215
- for (const match of matches.slice(0, 10)) {
216
- preview += `### ${match.file || "unknown"}:${match.range?.start?.line || "?"}\n`;
217
- preview += "```\n";
218
- preview += `- ${match.text || ""}\n`;
219
- preview += `+ ${match.replacement || args.rewrite}\n`;
220
- preview += "```\n\n";
221
- }
222
-
223
- if (count > 10) {
224
- preview += `... and ${count - 10} more matches\n`;
225
- }
226
-
227
- preview += "\n**To apply:** Run again with dryRun: false";
228
- return preview;
229
- } catch {
230
- return `Dry run preview:\n${stdout}`;
231
- }
232
- }
233
-
234
- // Actual replacement
235
- const lines = stdout.trim().split("\n");
236
- return `Applied ${lines.length} replacement(s):\n\n${stdout}`;
237
- } catch (error) {
238
- const err = error as { message?: string; stderr?: string };
239
- return `Error: ${err.message || err.stderr || "Unknown error"}`;
240
- }
241
- },
242
- });
243
-
244
- // Default export for single-tool registration
245
- export default astGrepSearch;