opencodekit 0.6.7 → 0.8.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.
- package/dist/index.js +654 -651
- package/dist/template/.opencode/AGENTS.md +97 -13
- package/dist/template/.opencode/README.md +18 -16
- package/dist/template/.opencode/command/accessibility-check.md +1 -1
- package/dist/template/.opencode/command/analyze-mockup.md +1 -1
- package/dist/template/.opencode/command/analyze-project.md +11 -9
- package/dist/template/.opencode/command/brainstorm.md +1 -1
- package/dist/template/.opencode/command/commit.md +1 -1
- package/dist/template/.opencode/command/create.md +16 -2
- package/dist/template/.opencode/command/design-audit.md +1 -1
- package/dist/template/.opencode/command/design.md +1 -1
- package/dist/template/.opencode/command/finish.md +20 -8
- package/dist/template/.opencode/command/fix-ci.md +14 -9
- package/dist/template/.opencode/command/fix-types.md +6 -11
- package/dist/template/.opencode/command/fix-ui.md +1 -1
- package/dist/template/.opencode/command/fix.md +1 -1
- package/dist/template/.opencode/command/handoff.md +8 -6
- package/dist/template/.opencode/command/implement.md +33 -3
- package/dist/template/.opencode/command/import-plan.md +27 -14
- package/dist/template/.opencode/command/integration-test.md +7 -3
- package/dist/template/.opencode/command/issue.md +10 -9
- package/dist/template/.opencode/command/new-feature.md +6 -6
- package/dist/template/.opencode/command/plan.md +5 -5
- package/dist/template/.opencode/command/pr.md +4 -4
- package/dist/template/.opencode/command/research-and-implement.md +2 -2
- package/dist/template/.opencode/command/research-ui.md +1 -1
- package/dist/template/.opencode/command/research.md +3 -5
- package/dist/template/.opencode/command/resume.md +4 -2
- package/dist/template/.opencode/command/revert-feature.md +7 -7
- package/dist/template/.opencode/command/review-codebase.md +1 -1
- package/dist/template/.opencode/command/skill-create.md +4 -4
- package/dist/template/.opencode/command/skill-optimize.md +4 -4
- package/dist/template/.opencode/command/status.md +4 -4
- package/dist/template/.opencode/command/ui-review.md +2 -2
- package/dist/template/.opencode/dcp.jsonc +20 -2
- package/dist/template/.opencode/opencode.json +496 -491
- package/dist/template/.opencode/package.json +20 -20
- package/dist/template/.opencode/plugin/beads.ts +667 -0
- package/dist/template/.opencode/plugin/compaction.ts +80 -0
- package/dist/template/.opencode/skill/beads/SKILL.md +419 -0
- package/dist/template/.opencode/skill/beads/references/BOUNDARIES.md +218 -0
- package/dist/template/.opencode/skill/beads/references/DEPENDENCIES.md +130 -0
- package/dist/template/.opencode/skill/beads/references/RESUMABILITY.md +180 -0
- package/dist/template/.opencode/skill/beads/references/WORKFLOWS.md +222 -0
- package/dist/template/.opencode/skill/brainstorming/SKILL.md +2 -2
- package/dist/template/.opencode/skill/executing-plans/SKILL.md +1 -1
- package/dist/template/.opencode/skill/sharing-skills/SKILL.md +13 -4
- package/dist/template/.opencode/skill/subagent-driven-development/SKILL.md +1 -1
- package/dist/template/.opencode/skill/systematic-debugging/SKILL.md +2 -2
- package/dist/template/.opencode/skill/using-git-worktrees/SKILL.md +27 -18
- package/dist/template/.opencode/skill/{using-superpowers → using-skills}/SKILL.md +6 -3
- package/dist/template/.opencode/skill/writing-plans/SKILL.md +3 -3
- package/dist/template/.opencode/skill/writing-skills/SKILL.md +2 -2
- package/package.json +2 -1
- package/dist/template/.opencode/memory/handoffs/2025-12-27T103000Z.md +0 -76
- package/dist/template/.opencode/plugin/skill.ts +0 -275
- package/dist/template/.opencode/skill/systematic-debugging/CREATION-LOG.md +0 -119
- package/dist/template/.opencode/skill/systematic-debugging/test-academic.md +0 -14
- package/dist/template/.opencode/skill/systematic-debugging/test-pressure-1.md +0 -58
- package/dist/template/.opencode/skill/systematic-debugging/test-pressure-2.md +0 -68
- package/dist/template/.opencode/skill/systematic-debugging/test-pressure-3.md +0 -69
- package/dist/template/.opencode/skill/testing-skills-with-subagents/examples/CLAUDE_MD_TESTING.md +0 -189
|
@@ -27,23 +27,23 @@ ls -d worktrees 2>/dev/null # Alternative
|
|
|
27
27
|
|
|
28
28
|
**If found:** Use that directory. If both exist, `.worktrees` wins.
|
|
29
29
|
|
|
30
|
-
### 2. Check
|
|
30
|
+
### 2. Check AGENTS.md
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
grep -i "worktree.*director"
|
|
33
|
+
grep -i "worktree.*director" AGENTS.md 2>/dev/null
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
**If preference specified:** Use it without asking.
|
|
37
37
|
|
|
38
38
|
### 3. Ask User
|
|
39
39
|
|
|
40
|
-
If no directory exists and no
|
|
40
|
+
If no directory exists and no AGENTS.md preference:
|
|
41
41
|
|
|
42
42
|
```
|
|
43
43
|
No worktree directory found. Where should I create worktrees?
|
|
44
44
|
|
|
45
45
|
1. .worktrees/ (project-local, hidden)
|
|
46
|
-
2. ~/.
|
|
46
|
+
2. ~/.opencode/worktrees/<project-name>/ (global location)
|
|
47
47
|
|
|
48
48
|
Which would you prefer?
|
|
49
49
|
```
|
|
@@ -62,13 +62,14 @@ grep -q "^\.worktrees/$" .gitignore || grep -q "^worktrees/$" .gitignore
|
|
|
62
62
|
**If NOT in .gitignore:**
|
|
63
63
|
|
|
64
64
|
Per Jesse's rule "Fix broken things immediately":
|
|
65
|
+
|
|
65
66
|
1. Add appropriate line to .gitignore
|
|
66
67
|
2. Commit the change
|
|
67
68
|
3. Proceed with worktree creation
|
|
68
69
|
|
|
69
70
|
**Why critical:** Prevents accidentally committing worktree contents to repository.
|
|
70
71
|
|
|
71
|
-
### For Global Directory (~/.
|
|
72
|
+
### For Global Directory (~/.opencode/worktrees)
|
|
72
73
|
|
|
73
74
|
No .gitignore verification needed - outside project entirely.
|
|
74
75
|
|
|
@@ -88,8 +89,8 @@ case $LOCATION in
|
|
|
88
89
|
.worktrees|worktrees)
|
|
89
90
|
path="$LOCATION/$BRANCH_NAME"
|
|
90
91
|
;;
|
|
91
|
-
~/.
|
|
92
|
-
path="~/.
|
|
92
|
+
~/.opencode/worktrees/*)
|
|
93
|
+
path="~/.opencode/worktrees/$project/$BRANCH_NAME"
|
|
93
94
|
;;
|
|
94
95
|
esac
|
|
95
96
|
|
|
@@ -143,31 +144,35 @@ Ready to implement <feature-name>
|
|
|
143
144
|
|
|
144
145
|
## Quick Reference
|
|
145
146
|
|
|
146
|
-
| Situation
|
|
147
|
-
|
|
148
|
-
| `.worktrees/` exists
|
|
149
|
-
| `worktrees/` exists
|
|
150
|
-
| Both exist
|
|
151
|
-
| Neither exists
|
|
147
|
+
| Situation | Action |
|
|
148
|
+
| --------------------------- | --------------------------- |
|
|
149
|
+
| `.worktrees/` exists | Use it (verify .gitignore) |
|
|
150
|
+
| `worktrees/` exists | Use it (verify .gitignore) |
|
|
151
|
+
| Both exist | Use `.worktrees/` |
|
|
152
|
+
| Neither exists | Check AGENTS.md → Ask user |
|
|
152
153
|
| Directory not in .gitignore | Add it immediately + commit |
|
|
153
|
-
| Tests fail during baseline
|
|
154
|
-
| No package.json/Cargo.toml
|
|
154
|
+
| Tests fail during baseline | Report failures + ask |
|
|
155
|
+
| No package.json/Cargo.toml | Skip dependency install |
|
|
155
156
|
|
|
156
157
|
## Common Mistakes
|
|
157
158
|
|
|
158
159
|
**Skipping .gitignore verification**
|
|
160
|
+
|
|
159
161
|
- **Problem:** Worktree contents get tracked, pollute git status
|
|
160
162
|
- **Fix:** Always grep .gitignore before creating project-local worktree
|
|
161
163
|
|
|
162
164
|
**Assuming directory location**
|
|
165
|
+
|
|
163
166
|
- **Problem:** Creates inconsistency, violates project conventions
|
|
164
|
-
- **Fix:** Follow priority: existing >
|
|
167
|
+
- **Fix:** Follow priority: existing > AGENTS.md > ask
|
|
165
168
|
|
|
166
169
|
**Proceeding with failing tests**
|
|
170
|
+
|
|
167
171
|
- **Problem:** Can't distinguish new bugs from pre-existing issues
|
|
168
172
|
- **Fix:** Report failures, get explicit permission to proceed
|
|
169
173
|
|
|
170
174
|
**Hardcoding setup commands**
|
|
175
|
+
|
|
171
176
|
- **Problem:** Breaks on projects using different tools
|
|
172
177
|
- **Fix:** Auto-detect from project files (package.json, etc.)
|
|
173
178
|
|
|
@@ -190,14 +195,16 @@ Ready to implement auth feature
|
|
|
190
195
|
## Red Flags
|
|
191
196
|
|
|
192
197
|
**Never:**
|
|
198
|
+
|
|
193
199
|
- Create worktree without .gitignore verification (project-local)
|
|
194
200
|
- Skip baseline test verification
|
|
195
201
|
- Proceed with failing tests without asking
|
|
196
202
|
- Assume directory location when ambiguous
|
|
197
|
-
- Skip
|
|
203
|
+
- Skip AGENTS.md check
|
|
198
204
|
|
|
199
205
|
**Always:**
|
|
200
|
-
|
|
206
|
+
|
|
207
|
+
- Follow directory priority: existing > AGENTS.md > ask
|
|
201
208
|
- Verify .gitignore for project-local
|
|
202
209
|
- Auto-detect and run project setup
|
|
203
210
|
- Verify clean test baseline
|
|
@@ -205,9 +212,11 @@ Ready to implement auth feature
|
|
|
205
212
|
## Integration
|
|
206
213
|
|
|
207
214
|
**Called by:**
|
|
215
|
+
|
|
208
216
|
- **brainstorming** (Phase 4) - REQUIRED when design is approved and implementation follows
|
|
209
217
|
- Any skill needing isolated workspace
|
|
210
218
|
|
|
211
219
|
**Pairs with:**
|
|
220
|
+
|
|
212
221
|
- **finishing-a-development-branch** - REQUIRED for cleanup after work complete
|
|
213
222
|
- **executing-plans** or **subagent-driven-development** - Work happens in this worktree
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: using-
|
|
2
|
+
name: using-skills
|
|
3
3
|
description: Use when starting any conversation - establishes mandatory workflows for finding and using skills, including using Skill tool before announcing usage, following brainstorming before coding, and creating TodoWrite todos for checklists
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -53,6 +53,7 @@ If a skill for your task exists, you must use it or you will fail at your task.
|
|
|
53
53
|
If a skill has a checklist, YOU MUST create TodoWrite todos for EACH item.
|
|
54
54
|
|
|
55
55
|
**Don't:**
|
|
56
|
+
|
|
56
57
|
- Work through checklist mentally
|
|
57
58
|
- Skip creating todos "to save time"
|
|
58
59
|
- Batch multiple items into one todo
|
|
@@ -66,6 +67,7 @@ Before using a skill, announce that you are using it.
|
|
|
66
67
|
"I'm using [Skill Name] to [what you're doing]."
|
|
67
68
|
|
|
68
69
|
**Examples:**
|
|
70
|
+
|
|
69
71
|
- "I'm using the brainstorming skill to refine your idea into a design."
|
|
70
72
|
- "I'm using the test-driven-development skill to implement this feature."
|
|
71
73
|
|
|
@@ -92,9 +94,10 @@ Your human partner's specific instructions describe WHAT to do, not HOW.
|
|
|
92
94
|
## Summary
|
|
93
95
|
|
|
94
96
|
**Starting any task:**
|
|
97
|
+
|
|
95
98
|
1. If relevant skill exists → Use the skill
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
2. Announce you're using it
|
|
100
|
+
3. Follow what it says
|
|
98
101
|
|
|
99
102
|
**Skill has checklist?** TodoWrite for every item.
|
|
100
103
|
|
|
@@ -34,7 +34,7 @@ Assume they are a skilled developer, but know almost nothing about our toolset o
|
|
|
34
34
|
```markdown
|
|
35
35
|
# [Feature Name] Implementation Plan
|
|
36
36
|
|
|
37
|
-
> **For Claude:** REQUIRED SUB-SKILL: Use
|
|
37
|
+
> **For Claude:** REQUIRED SUB-SKILL: Use skill({ name: "executing-plans" }) to implement this plan task-by-task.
|
|
38
38
|
|
|
39
39
|
**Goal:** [One sentence describing what this builds]
|
|
40
40
|
|
|
@@ -111,11 +111,11 @@ After saving the plan, offer execution choice:
|
|
|
111
111
|
**Which approach?"**
|
|
112
112
|
|
|
113
113
|
**If Subagent-Driven chosen:**
|
|
114
|
-
- **REQUIRED SUB-SKILL:** Use
|
|
114
|
+
- **REQUIRED SUB-SKILL:** Use skill({ name: "subagent-driven-development" })
|
|
115
115
|
- Stay in this session
|
|
116
116
|
- Fresh subagent per task + code review
|
|
117
117
|
|
|
118
118
|
**If Parallel Session chosen:**
|
|
119
119
|
- Guide them to open new session in worktree
|
|
120
|
-
- **REQUIRED SUB-SKILL:** New session uses
|
|
120
|
+
- **REQUIRED SUB-SKILL:** New session uses skill({ name: "executing-plans" })
|
|
121
121
|
```
|
|
@@ -282,7 +282,7 @@ wc -w skills/path/SKILL.md
|
|
|
282
282
|
|
|
283
283
|
Use skill name only, with explicit requirement markers:
|
|
284
284
|
|
|
285
|
-
- ✅ Good: `**REQUIRED SUB-SKILL:** Use
|
|
285
|
+
- ✅ Good: `**REQUIRED SUB-SKILL:** Use skill({ name: "test-driven-development" })`
|
|
286
286
|
- ✅ Good: `**REQUIRED BACKGROUND:** You MUST understand systematic-debugging`
|
|
287
287
|
- ❌ Bad: `See skills/testing/test-driven-development` (unclear if required)
|
|
288
288
|
- ❌ Bad: `@skills/testing/test-driven-development/SKILL.md` (force-loads, burns context)
|
|
@@ -568,7 +568,7 @@ Run same scenarios WITH skill. Agent should now comply.
|
|
|
568
568
|
|
|
569
569
|
Agent found new rationalization? Add explicit counter. Re-test until bulletproof.
|
|
570
570
|
|
|
571
|
-
**REQUIRED SUB-SKILL:** Use
|
|
571
|
+
**REQUIRED SUB-SKILL:** Use skill({ name: "testing-skills-with-subagents" }) for the complete testing methodology:
|
|
572
572
|
|
|
573
573
|
- How to write pressure scenarios
|
|
574
574
|
- Pressure types (time, sunk cost, authority, exhaustion)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencodekit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "CLI tool for bootstrapping and managing OpenCodeKit projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@clack/prompts": "^0.7.0",
|
|
37
37
|
"@opencode-ai/plugin": "^1.0.141",
|
|
38
|
+
"beads-village": "^1.3.3",
|
|
38
39
|
"cac": "^6.7.14",
|
|
39
40
|
"cli-table3": "^0.6.5",
|
|
40
41
|
"ora": "^9.0.0",
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# Handoff: test-handoff-plugin
|
|
2
|
-
|
|
3
|
-
**Created:** 2025-12-27T10:30:00Z
|
|
4
|
-
**Agent:** build
|
|
5
|
-
|
|
6
|
-
## Provenance
|
|
7
|
-
|
|
8
|
-
| Key | Value |
|
|
9
|
-
| ------ | --------------------------------------------------- |
|
|
10
|
-
| Repo | git@github.com:opencodekit/opencodekit-template.git |
|
|
11
|
-
| Branch | main |
|
|
12
|
-
| Commit | ae38a95f899300419e9b17030268cedc60ebb44f |
|
|
13
|
-
| Clean | no |
|
|
14
|
-
|
|
15
|
-
## Session Context
|
|
16
|
-
|
|
17
|
-
**Current Session:** testing handoff plugin
|
|
18
|
-
**Token Usage:** ~50k estimated
|
|
19
|
-
|
|
20
|
-
Next session can load context with:
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
read_session("last", project="current")
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Progress
|
|
27
|
-
|
|
28
|
-
### Completed
|
|
29
|
-
|
|
30
|
-
- [x] Released v0.6.4 (version bump, changelog, tag, GitHub release)
|
|
31
|
-
- [x] Reviewed Agent-Skills-for-Context-Engineering repo (verdict: mostly theory, not worth stealing)
|
|
32
|
-
- [x] Reviewed Karpathy's hn-time-capsule (verdict: useful patterns)
|
|
33
|
-
- [x] Created handoff plugin (`plugin/handoff.ts`)
|
|
34
|
-
- [x] Updated `/handoff` command to instruct Ctrl+K
|
|
35
|
-
|
|
36
|
-
### In Progress
|
|
37
|
-
|
|
38
|
-
- [ ] Testing handoff plugin - verifying it injects context on compaction
|
|
39
|
-
|
|
40
|
-
### Remaining
|
|
41
|
-
|
|
42
|
-
- [ ] Commit new handoff plugin and updated command
|
|
43
|
-
- [ ] Test full flow: handoff → Ctrl+K → new session with context
|
|
44
|
-
|
|
45
|
-
## Context
|
|
46
|
-
|
|
47
|
-
### Key Files
|
|
48
|
-
|
|
49
|
-
- `.opencode/plugin/handoff.ts` - New plugin that injects handoff on compaction
|
|
50
|
-
- `.opencode/command/handoff.md` - Updated to tell user to press Ctrl+K
|
|
51
|
-
- `.opencode/plugin/compactor.ts` - Reference for plugin structure
|
|
52
|
-
|
|
53
|
-
### Decisions Made
|
|
54
|
-
|
|
55
|
-
- Use `experimental.session.compacting` hook to inject handoff context
|
|
56
|
-
- Only inject handoffs < 1 hour old to prevent stale context
|
|
57
|
-
- Search both `.opencode/memory/handoffs/` and `.beads/artifacts/` for handoffs
|
|
58
|
-
|
|
59
|
-
### Blockers/Issues
|
|
60
|
-
|
|
61
|
-
- OpenCode lacks `session.start` hook (Issue #5409) - can't auto-navigate to new session
|
|
62
|
-
- Workaround: User must manually press Ctrl+K after /handoff
|
|
63
|
-
|
|
64
|
-
## Resume Instructions
|
|
65
|
-
|
|
66
|
-
1. Commit the new handoff plugin and updated command
|
|
67
|
-
2. Test the full flow: run /handoff, press Ctrl+K, verify context injected
|
|
68
|
-
3. If working, consider adding to v0.6.5 release
|
|
69
|
-
|
|
70
|
-
**Recommended:** Start next session with `/resume test-handoff-plugin` to auto-load this handoff + previous session context.
|
|
71
|
-
|
|
72
|
-
## Artifacts
|
|
73
|
-
|
|
74
|
-
- spec.md: missing
|
|
75
|
-
- research.md: missing
|
|
76
|
-
- plan.md: missing
|
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skills plugin for OpenCode.ai
|
|
3
|
-
*
|
|
4
|
-
* Provides custom tools for loading and discovering skills.
|
|
5
|
-
* Skills are loaded on-demand via use_skill tool, not auto-injected.
|
|
6
|
-
*
|
|
7
|
-
* OpenCode Official Skill Locations:
|
|
8
|
-
* - Project skills: .opencode/skill/
|
|
9
|
-
* - Personal skills: ~/.opencode/skill/
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import fs from "fs";
|
|
13
|
-
import os from "os";
|
|
14
|
-
import path from "path";
|
|
15
|
-
import { type Plugin, tool } from "@opencode-ai/plugin";
|
|
16
|
-
|
|
17
|
-
interface SkillResolution {
|
|
18
|
-
skillFile: string;
|
|
19
|
-
sourceType: "project" | "personal";
|
|
20
|
-
skillPath: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface SkillInfo {
|
|
24
|
-
path: string;
|
|
25
|
-
skillFile: string;
|
|
26
|
-
name: string;
|
|
27
|
-
description: string;
|
|
28
|
-
sourceType: "project" | "personal";
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
interface Frontmatter {
|
|
32
|
-
name: string;
|
|
33
|
-
description: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// ============================================
|
|
37
|
-
// Skills Core Functions
|
|
38
|
-
// ============================================
|
|
39
|
-
|
|
40
|
-
function extractFrontmatter(filePath: string): Frontmatter {
|
|
41
|
-
try {
|
|
42
|
-
const content = fs.readFileSync(filePath, "utf8");
|
|
43
|
-
const lines = content.split("\n");
|
|
44
|
-
|
|
45
|
-
let inFrontmatter = false;
|
|
46
|
-
let name = "";
|
|
47
|
-
let description = "";
|
|
48
|
-
|
|
49
|
-
for (const line of lines) {
|
|
50
|
-
if (line.trim() === "---") {
|
|
51
|
-
if (inFrontmatter) break;
|
|
52
|
-
inFrontmatter = true;
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (inFrontmatter) {
|
|
57
|
-
const match = line.match(/^(\w+):\s*(.*)$/);
|
|
58
|
-
if (match) {
|
|
59
|
-
const [, key, value] = match;
|
|
60
|
-
if (key === "name") name = value.trim();
|
|
61
|
-
if (key === "description") description = value.trim();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return { name, description };
|
|
67
|
-
} catch {
|
|
68
|
-
return { name: "", description: "" };
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function findSkillsInDir(
|
|
73
|
-
dir: string,
|
|
74
|
-
sourceType: "project" | "personal",
|
|
75
|
-
maxDepth = 3,
|
|
76
|
-
): SkillInfo[] {
|
|
77
|
-
const skills: SkillInfo[] = [];
|
|
78
|
-
|
|
79
|
-
if (!fs.existsSync(dir)) return skills;
|
|
80
|
-
|
|
81
|
-
function recurse(currentDir: string, depth: number) {
|
|
82
|
-
if (depth > maxDepth) return;
|
|
83
|
-
|
|
84
|
-
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
85
|
-
|
|
86
|
-
for (const entry of entries) {
|
|
87
|
-
const fullPath = path.join(currentDir, entry.name);
|
|
88
|
-
|
|
89
|
-
if (entry.isDirectory()) {
|
|
90
|
-
const skillFile = path.join(fullPath, "SKILL.md");
|
|
91
|
-
if (fs.existsSync(skillFile)) {
|
|
92
|
-
const { name, description } = extractFrontmatter(skillFile);
|
|
93
|
-
skills.push({
|
|
94
|
-
path: fullPath,
|
|
95
|
-
skillFile,
|
|
96
|
-
name: name || entry.name,
|
|
97
|
-
description: description || "",
|
|
98
|
-
sourceType,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
recurse(fullPath, depth + 1);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
recurse(dir, 0);
|
|
107
|
-
return skills;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function stripFrontmatter(content: string): string {
|
|
111
|
-
const lines = content.split("\n");
|
|
112
|
-
let inFrontmatter = false;
|
|
113
|
-
let frontmatterEnded = false;
|
|
114
|
-
const contentLines: string[] = [];
|
|
115
|
-
|
|
116
|
-
for (const line of lines) {
|
|
117
|
-
if (line.trim() === "---") {
|
|
118
|
-
if (inFrontmatter) {
|
|
119
|
-
frontmatterEnded = true;
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
inFrontmatter = true;
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (frontmatterEnded || !inFrontmatter) {
|
|
127
|
-
contentLines.push(line);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return contentLines.join("\n").trim();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// ============================================
|
|
135
|
-
// Plugin Export
|
|
136
|
-
// ============================================
|
|
137
|
-
|
|
138
|
-
export const SkillsPlugin: Plugin = async ({ client, directory }) => {
|
|
139
|
-
const homeDir = os.homedir();
|
|
140
|
-
const projectSkillsDir = path.join(directory, ".opencode/skill");
|
|
141
|
-
const personalSkillsDir = path.join(homeDir, ".opencode/skill");
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
tool: {
|
|
145
|
-
use_skill: tool({
|
|
146
|
-
description:
|
|
147
|
-
"Load and read a specific skill to guide your work. Skills contain proven workflows, mandatory processes, and expert techniques.",
|
|
148
|
-
args: {
|
|
149
|
-
skill_name: tool.schema
|
|
150
|
-
.string()
|
|
151
|
-
.describe(
|
|
152
|
-
'Name of skill to load (e.g., "brainstorming", "my-custom-skill", or "project:my-skill")',
|
|
153
|
-
),
|
|
154
|
-
},
|
|
155
|
-
execute: async (
|
|
156
|
-
args: { skill_name: string },
|
|
157
|
-
context: { sessionID: string },
|
|
158
|
-
) => {
|
|
159
|
-
const { skill_name } = args;
|
|
160
|
-
|
|
161
|
-
// Resolve with priority: project > personal
|
|
162
|
-
const forceProject = skill_name.startsWith("project:");
|
|
163
|
-
const actualSkillName = forceProject
|
|
164
|
-
? skill_name.replace(/^project:/, "")
|
|
165
|
-
: skill_name;
|
|
166
|
-
|
|
167
|
-
let resolved: SkillResolution | null = null;
|
|
168
|
-
|
|
169
|
-
// Try project skills first
|
|
170
|
-
if (forceProject) {
|
|
171
|
-
const projectSkillFile = path.join(
|
|
172
|
-
projectSkillsDir,
|
|
173
|
-
actualSkillName,
|
|
174
|
-
"SKILL.md",
|
|
175
|
-
);
|
|
176
|
-
if (fs.existsSync(projectSkillFile)) {
|
|
177
|
-
resolved = {
|
|
178
|
-
skillFile: projectSkillFile,
|
|
179
|
-
sourceType: "project",
|
|
180
|
-
skillPath: actualSkillName,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Fall back to personal resolution
|
|
186
|
-
if (!resolved && !forceProject) {
|
|
187
|
-
const personalSkillFile = path.join(
|
|
188
|
-
personalSkillsDir,
|
|
189
|
-
skill_name,
|
|
190
|
-
"SKILL.md",
|
|
191
|
-
);
|
|
192
|
-
if (fs.existsSync(personalSkillFile)) {
|
|
193
|
-
resolved = {
|
|
194
|
-
skillFile: personalSkillFile,
|
|
195
|
-
sourceType: "personal",
|
|
196
|
-
skillPath: skill_name,
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (!resolved) {
|
|
202
|
-
return `Error: Skill "${skill_name}" not found.\n\nRun find_skills to see available skills.`;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const fullContent = fs.readFileSync(resolved.skillFile, "utf8");
|
|
206
|
-
const { name, description } = extractFrontmatter(resolved.skillFile);
|
|
207
|
-
const content = stripFrontmatter(fullContent);
|
|
208
|
-
const skillDirectory = path.dirname(resolved.skillFile);
|
|
209
|
-
|
|
210
|
-
const skillHeader = `# ${name || skill_name}
|
|
211
|
-
# ${description || ""}
|
|
212
|
-
# Supporting tools and docs are in ${skillDirectory}
|
|
213
|
-
# ============================================`;
|
|
214
|
-
|
|
215
|
-
// Insert as user message with noReply for persistence across compaction
|
|
216
|
-
try {
|
|
217
|
-
await client.session.prompt({
|
|
218
|
-
path: { id: context.sessionID },
|
|
219
|
-
body: {
|
|
220
|
-
noReply: true,
|
|
221
|
-
parts: [
|
|
222
|
-
{
|
|
223
|
-
type: "text",
|
|
224
|
-
text: `Loading skill: ${name || skill_name}`,
|
|
225
|
-
},
|
|
226
|
-
{ type: "text", text: `${skillHeader}\n\n${content}` },
|
|
227
|
-
],
|
|
228
|
-
},
|
|
229
|
-
});
|
|
230
|
-
} catch {
|
|
231
|
-
// Fallback: return content directly if message insertion fails
|
|
232
|
-
return `${skillHeader}\n\n${content}`;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return `Launching skill: ${name || skill_name}`;
|
|
236
|
-
},
|
|
237
|
-
}),
|
|
238
|
-
|
|
239
|
-
find_skills: tool({
|
|
240
|
-
description:
|
|
241
|
-
"List all available skills in project and personal skill libraries.",
|
|
242
|
-
args: {},
|
|
243
|
-
execute: async () => {
|
|
244
|
-
const projectSkills = findSkillsInDir(projectSkillsDir, "project", 3);
|
|
245
|
-
const personalSkills = findSkillsInDir(
|
|
246
|
-
personalSkillsDir,
|
|
247
|
-
"personal",
|
|
248
|
-
3,
|
|
249
|
-
);
|
|
250
|
-
|
|
251
|
-
const allSkills = [...projectSkills, ...personalSkills];
|
|
252
|
-
|
|
253
|
-
if (allSkills.length === 0) {
|
|
254
|
-
return `No skills found. Add project skills to .opencode/skill/ or personal skills to ~/.opencode/skill/`;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
let output = "Available skills:\n\n";
|
|
258
|
-
|
|
259
|
-
for (const skill of allSkills) {
|
|
260
|
-
const namespace = skill.sourceType === "project" ? "project:" : "";
|
|
261
|
-
const skillName = skill.name || path.basename(skill.path);
|
|
262
|
-
|
|
263
|
-
output += `${namespace}${skillName}\n`;
|
|
264
|
-
if (skill.description) {
|
|
265
|
-
output += ` ${skill.description}\n`;
|
|
266
|
-
}
|
|
267
|
-
output += ` Directory: ${skill.path}\n\n`;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return output;
|
|
271
|
-
},
|
|
272
|
-
}),
|
|
273
|
-
},
|
|
274
|
-
};
|
|
275
|
-
};
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
# Creation Log: Systematic Debugging Skill
|
|
2
|
-
|
|
3
|
-
Reference example of extracting, structuring, and bulletproofing a critical skill.
|
|
4
|
-
|
|
5
|
-
## Source Material
|
|
6
|
-
|
|
7
|
-
Extracted debugging framework from `/Users/jesse/.claude/CLAUDE.md`:
|
|
8
|
-
- 4-phase systematic process (Investigation → Pattern Analysis → Hypothesis → Implementation)
|
|
9
|
-
- Core mandate: ALWAYS find root cause, NEVER fix symptoms
|
|
10
|
-
- Rules designed to resist time pressure and rationalization
|
|
11
|
-
|
|
12
|
-
## Extraction Decisions
|
|
13
|
-
|
|
14
|
-
**What to include:**
|
|
15
|
-
- Complete 4-phase framework with all rules
|
|
16
|
-
- Anti-shortcuts ("NEVER fix symptom", "STOP and re-analyze")
|
|
17
|
-
- Pressure-resistant language ("even if faster", "even if I seem in a hurry")
|
|
18
|
-
- Concrete steps for each phase
|
|
19
|
-
|
|
20
|
-
**What to leave out:**
|
|
21
|
-
- Project-specific context
|
|
22
|
-
- Repetitive variations of same rule
|
|
23
|
-
- Narrative explanations (condensed to principles)
|
|
24
|
-
|
|
25
|
-
## Structure Following skill-creation/SKILL.md
|
|
26
|
-
|
|
27
|
-
1. **Rich when_to_use** - Included symptoms and anti-patterns
|
|
28
|
-
2. **Type: technique** - Concrete process with steps
|
|
29
|
-
3. **Keywords** - "root cause", "symptom", "workaround", "debugging", "investigation"
|
|
30
|
-
4. **Flowchart** - Decision point for "fix failed" → re-analyze vs add more fixes
|
|
31
|
-
5. **Phase-by-phase breakdown** - Scannable checklist format
|
|
32
|
-
6. **Anti-patterns section** - What NOT to do (critical for this skill)
|
|
33
|
-
|
|
34
|
-
## Bulletproofing Elements
|
|
35
|
-
|
|
36
|
-
Framework designed to resist rationalization under pressure:
|
|
37
|
-
|
|
38
|
-
### Language Choices
|
|
39
|
-
- "ALWAYS" / "NEVER" (not "should" / "try to")
|
|
40
|
-
- "even if faster" / "even if I seem in a hurry"
|
|
41
|
-
- "STOP and re-analyze" (explicit pause)
|
|
42
|
-
- "Don't skip past" (catches the actual behavior)
|
|
43
|
-
|
|
44
|
-
### Structural Defenses
|
|
45
|
-
- **Phase 1 required** - Can't skip to implementation
|
|
46
|
-
- **Single hypothesis rule** - Forces thinking, prevents shotgun fixes
|
|
47
|
-
- **Explicit failure mode** - "IF your first fix doesn't work" with mandatory action
|
|
48
|
-
- **Anti-patterns section** - Shows exactly what shortcuts look like
|
|
49
|
-
|
|
50
|
-
### Redundancy
|
|
51
|
-
- Root cause mandate in overview + when_to_use + Phase 1 + implementation rules
|
|
52
|
-
- "NEVER fix symptom" appears 4 times in different contexts
|
|
53
|
-
- Each phase has explicit "don't skip" guidance
|
|
54
|
-
|
|
55
|
-
## Testing Approach
|
|
56
|
-
|
|
57
|
-
Created 4 validation tests following skills/meta/testing-skills-with-subagents:
|
|
58
|
-
|
|
59
|
-
### Test 1: Academic Context (No Pressure)
|
|
60
|
-
- Simple bug, no time pressure
|
|
61
|
-
- **Result:** Perfect compliance, complete investigation
|
|
62
|
-
|
|
63
|
-
### Test 2: Time Pressure + Obvious Quick Fix
|
|
64
|
-
- User "in a hurry", symptom fix looks easy
|
|
65
|
-
- **Result:** Resisted shortcut, followed full process, found real root cause
|
|
66
|
-
|
|
67
|
-
### Test 3: Complex System + Uncertainty
|
|
68
|
-
- Multi-layer failure, unclear if can find root cause
|
|
69
|
-
- **Result:** Systematic investigation, traced through all layers, found source
|
|
70
|
-
|
|
71
|
-
### Test 4: Failed First Fix
|
|
72
|
-
- Hypothesis doesn't work, temptation to add more fixes
|
|
73
|
-
- **Result:** Stopped, re-analyzed, formed new hypothesis (no shotgun)
|
|
74
|
-
|
|
75
|
-
**All tests passed.** No rationalizations found.
|
|
76
|
-
|
|
77
|
-
## Iterations
|
|
78
|
-
|
|
79
|
-
### Initial Version
|
|
80
|
-
- Complete 4-phase framework
|
|
81
|
-
- Anti-patterns section
|
|
82
|
-
- Flowchart for "fix failed" decision
|
|
83
|
-
|
|
84
|
-
### Enhancement 1: TDD Reference
|
|
85
|
-
- Added link to skills/testing/test-driven-development
|
|
86
|
-
- Note explaining TDD's "simplest code" ≠ debugging's "root cause"
|
|
87
|
-
- Prevents confusion between methodologies
|
|
88
|
-
|
|
89
|
-
## Final Outcome
|
|
90
|
-
|
|
91
|
-
Bulletproof skill that:
|
|
92
|
-
- ✅ Clearly mandates root cause investigation
|
|
93
|
-
- ✅ Resists time pressure rationalization
|
|
94
|
-
- ✅ Provides concrete steps for each phase
|
|
95
|
-
- ✅ Shows anti-patterns explicitly
|
|
96
|
-
- ✅ Tested under multiple pressure scenarios
|
|
97
|
-
- ✅ Clarifies relationship to TDD
|
|
98
|
-
- ✅ Ready for use
|
|
99
|
-
|
|
100
|
-
## Key Insight
|
|
101
|
-
|
|
102
|
-
**Most important bulletproofing:** Anti-patterns section showing exact shortcuts that feel justified in the moment. When Claude thinks "I'll just add this one quick fix", seeing that exact pattern listed as wrong creates cognitive friction.
|
|
103
|
-
|
|
104
|
-
## Usage Example
|
|
105
|
-
|
|
106
|
-
When encountering a bug:
|
|
107
|
-
1. Load skill: skills/debugging/systematic-debugging
|
|
108
|
-
2. Read overview (10 sec) - reminded of mandate
|
|
109
|
-
3. Follow Phase 1 checklist - forced investigation
|
|
110
|
-
4. If tempted to skip - see anti-pattern, stop
|
|
111
|
-
5. Complete all phases - root cause found
|
|
112
|
-
|
|
113
|
-
**Time investment:** 5-10 minutes
|
|
114
|
-
**Time saved:** Hours of symptom-whack-a-mole
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
*Created: 2025-10-03*
|
|
119
|
-
*Purpose: Reference example for skill extraction and bulletproofing*
|