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,23 +1,20 @@
1
1
  {
2
- "name": "opencode",
3
- "version": "1.0.0",
4
- "description": "Opencode plugin",
5
- "type": "module",
6
- "main": "index.js",
7
- "scripts": {
8
- "type-check": "tsc --noEmit"
9
- },
10
- "keywords": [],
11
- "author": "",
12
- "license": "ISC",
13
- "dependencies": {
14
- "@lancedb/lancedb": "^0.23.0",
15
- "@opencode-ai/plugin": "1.1.12",
16
- "@opencode-ai/sdk": "^1.1.8",
17
- "openai": "^6.15.0"
18
- },
19
- "devDependencies": {
20
- "@types/node": "^25.0.3",
21
- "typescript": "^5.9.3"
22
- }
2
+ "name": "opencode",
3
+ "version": "1.0.0",
4
+ "description": "Opencode plugin",
5
+ "keywords": [],
6
+ "license": "ISC",
7
+ "author": "",
8
+ "type": "module",
9
+ "main": "index.js",
10
+ "scripts": {
11
+ "type-check": "tsc --noEmit"
12
+ },
13
+ "dependencies": {
14
+ "@opencode-ai/plugin": "1.1.14"
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^25.0.3",
18
+ "typescript": "^5.9.3"
19
+ }
23
20
  }
@@ -20,89 +20,83 @@
20
20
  import type { Plugin } from "@opencode-ai/plugin";
21
21
 
22
22
  export const CompactionPlugin: Plugin = async ({ $, directory }) => {
23
- const MEMORY_DIR = `${directory}/.opencode/memory`;
24
- const HANDOFF_DIR = `${MEMORY_DIR}/handoffs`;
25
-
26
- return {
27
- "experimental.session.compacting": async (input, output) => {
28
- // 1. Load session context (CONTINUITY.md pattern) - HIGHEST PRIORITY
29
- let sessionContext = "";
30
- try {
31
- const sessionFile = `${MEMORY_DIR}/session-context.md`;
32
- const content = await $`cat ${sessionFile} 2>/dev/null`.text();
33
- if (content.trim()) {
34
- sessionContext = `\n## Session Continuity (Compaction-Safe)\n${content}`;
35
- }
36
- } catch {
37
- // No session context yet
38
- }
39
-
40
- // 2. Load project memory files
41
- let memoryContext = "";
42
- try {
43
- const memoryFiles =
44
- await $`find ${MEMORY_DIR}/project -name '*.md' -type f 2>/dev/null | head -10`.quiet();
45
- if (memoryFiles.stdout) {
46
- const files = memoryFiles.stdout.toString().trim().split("\n");
47
- for (const file of files) {
48
- const content = await $`cat ${file}`.text();
49
- if (content.trim() && !content.includes("<!-- ")) {
50
- const name = file.split("/").pop()?.replace(".md", "");
51
- memoryContext += `\n## Project ${name}\n${content}`;
52
- }
53
- }
54
- }
55
- } catch {
56
- // Memory dir doesn't exist or other error
57
- }
58
-
59
- // 3. Inject beads in-progress state
60
- let beadsContext = "";
61
- try {
62
- const result =
63
- await $`cd ${directory} && bd list --status in_progress --json 2>/dev/null`.quiet();
64
- if (result.stdout) {
65
- const inProgress = JSON.parse(result.stdout.toString());
66
- if (inProgress.length > 0) {
67
- beadsContext = `\n## Active Beads (In Progress)\n${inProgress.map((b: { id: string; title: string }) => `- ${b.id}: ${b.title}`).join("\n")}`;
68
- }
69
- }
70
- } catch {
71
- // Beads not available, skip
72
- }
73
-
74
- // 4. Load most recent handoff file (session continuity)
75
- let handoffContext = "";
76
- try {
77
- const result =
78
- await $`ls -t ${HANDOFF_DIR}/*.md 2>/dev/null | head -1`.quiet();
79
- if (result.stdout) {
80
- const handoffPath = result.stdout.toString().trim();
81
- if (handoffPath) {
82
- const handoffContent = await $`cat ${handoffPath}`.text();
83
- handoffContext = `\n## Previous Session Handoff\n\n${handoffContent}\n\n**IMPORTANT**: Resume work from where previous session left off.`;
84
- }
85
- }
86
- } catch {
87
- // No handoff files, skip
88
- }
89
-
90
- // Inject all context - session context FIRST (most important)
91
- const allContext = [
92
- sessionContext,
93
- beadsContext,
94
- handoffContext,
95
- memoryContext,
96
- ]
97
- .filter(Boolean)
98
- .join("\n");
99
-
100
- if (allContext) {
101
- output.context.push(`## Session Context\n${allContext}\n`);
102
- }
103
-
104
- // Append workflow-specific rules to OpenCode's default prompt
105
- output.prompt = `${output.prompt}
23
+ const MEMORY_DIR = `${directory}/.opencode/memory`;
24
+ const HANDOFF_DIR = `${MEMORY_DIR}/handoffs`;
25
+
26
+ return {
27
+ "experimental.session.compacting": async (input, output) => {
28
+ // 1. Load session context (CONTINUITY.md pattern) - HIGHEST PRIORITY
29
+ let sessionContext = "";
30
+ try {
31
+ const sessionFile = `${MEMORY_DIR}/session-context.md`;
32
+ const content = await $`cat ${sessionFile} 2>/dev/null`.text();
33
+ if (content.trim()) {
34
+ sessionContext = `\n## Session Continuity (Compaction-Safe)\n${content}`;
35
+ }
36
+ } catch {
37
+ // No session context yet
38
+ }
39
+
40
+ // 2. Load project memory files
41
+ let memoryContext = "";
42
+ try {
43
+ const memoryFiles =
44
+ await $`find ${MEMORY_DIR}/project -name '*.md' -type f 2>/dev/null | head -10`.quiet();
45
+ if (memoryFiles.stdout) {
46
+ const files = memoryFiles.stdout.toString().trim().split("\n");
47
+ for (const file of files) {
48
+ const content = await $`cat ${file}`.text();
49
+ if (content.trim() && !content.includes("<!-- ")) {
50
+ const name = file.split("/").pop()?.replace(".md", "");
51
+ memoryContext += `\n## Project ${name}\n${content}`;
52
+ }
53
+ }
54
+ }
55
+ } catch {
56
+ // Memory dir doesn't exist or other error
57
+ }
58
+
59
+ // 3. Inject beads in-progress state
60
+ let beadsContext = "";
61
+ try {
62
+ const result =
63
+ await $`cd ${directory} && bd list --status in_progress --json 2>/dev/null`.quiet();
64
+ if (result.stdout) {
65
+ const inProgress = JSON.parse(result.stdout.toString());
66
+ if (inProgress.length > 0) {
67
+ beadsContext = `\n## Active Beads (In Progress)\n${inProgress.map((b: { id: string; title: string }) => `- ${b.id}: ${b.title}`).join("\n")}`;
68
+ }
69
+ }
70
+ } catch {
71
+ // Beads not available, skip
72
+ }
73
+
74
+ // 4. Load most recent handoff file (session continuity)
75
+ let handoffContext = "";
76
+ try {
77
+ const result = await $`ls -t ${HANDOFF_DIR}/*.md 2>/dev/null | head -1`.quiet();
78
+ if (result.stdout) {
79
+ const handoffPath = result.stdout.toString().trim();
80
+ if (handoffPath) {
81
+ const handoffContent = await $`cat ${handoffPath}`.text();
82
+ handoffContext = `\n## Previous Session Handoff\n\n${handoffContent}\n\n**IMPORTANT**: Resume work from where previous session left off.`;
83
+ }
84
+ }
85
+ } catch {
86
+ // No handoff files, skip
87
+ }
88
+
89
+ // Inject all context - session context FIRST (most important)
90
+ const allContext = [sessionContext, beadsContext, handoffContext, memoryContext]
91
+ .filter(Boolean)
92
+ .join("\n");
93
+
94
+ if (allContext) {
95
+ output.context.push(`## Session Context\n${allContext}\n`);
96
+ }
97
+
98
+ // Append workflow-specific rules to OpenCode's default prompt
99
+ output.prompt = `${output.prompt}
106
100
 
107
101
  ## Additional Rules for This Workflow
108
102
 
@@ -147,6 +141,6 @@ If you discover:
147
141
  - PRESERVE: File paths (file:line_number), user constraints, decisions, UNCONFIRMED items
148
142
  - DROP: Failed attempts, superseded info, verbose tool outputs, exploration dead-ends
149
143
  `;
150
- },
151
- };
144
+ },
145
+ };
152
146
  };
@@ -0,0 +1,34 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+
3
+ const session_set = new Set<string>();
4
+ const cwd = process.cwd();
5
+ const env_ctx = `
6
+ <environment_context>
7
+ <cwd>${cwd}</cwd>
8
+ </environment_context>
9
+ `.trim();
10
+
11
+ export const EnvironmentContextPlugin: Plugin = async () => {
12
+ return {
13
+ async "chat.message"(_input, output) {
14
+ const { message } = output;
15
+ const sessionID = message?.sessionID;
16
+ if (!sessionID) return;
17
+
18
+ if (session_set.has(sessionID)) {
19
+ return;
20
+ }
21
+
22
+ output.parts.unshift({
23
+ id: `env-ctx-${Date.now()}`,
24
+ messageID: message.id,
25
+ sessionID,
26
+ type: "text",
27
+ text: env_ctx,
28
+ synthetic: true,
29
+ });
30
+
31
+ session_set.add(sessionID);
32
+ },
33
+ };
34
+ };
@@ -10,15 +10,15 @@ let _isWSL: boolean | null = null;
10
10
  * Check if running in WSL (cached)
11
11
  */
12
12
  export function isWSL(): boolean {
13
- if (_isWSL !== null) return _isWSL;
14
- try {
15
- const fs = require("node:fs");
16
- const release = fs.readFileSync("/proc/version", "utf8").toLowerCase();
17
- _isWSL = release.includes("microsoft") || release.includes("wsl");
18
- } catch {
19
- _isWSL = false;
20
- }
21
- return _isWSL ?? false;
13
+ if (_isWSL !== null) return _isWSL;
14
+ try {
15
+ const fs = require("node:fs");
16
+ const release = fs.readFileSync("/proc/version", "utf8").toLowerCase();
17
+ _isWSL = release.includes("microsoft") || release.includes("wsl");
18
+ } catch {
19
+ _isWSL = false;
20
+ }
21
+ return _isWSL ?? false;
22
22
  }
23
23
 
24
24
  /**
@@ -27,59 +27,55 @@ export function isWSL(): boolean {
27
27
  * @param title - Notification title
28
28
  * @param message - Notification body
29
29
  */
30
- export async function notify(
31
- $: any,
32
- title: string,
33
- message: string,
34
- ): Promise<void> {
35
- const platform = process.platform;
36
- const safeTitle = title || "OpenCode";
37
- const safeMessage = message || "";
30
+ export async function notify($: any, title: string, message: string): Promise<void> {
31
+ const platform = process.platform;
32
+ const safeTitle = title || "OpenCode";
33
+ const safeMessage = message || "";
38
34
 
39
- try {
40
- if (platform === "darwin") {
41
- await $`osascript -e ${`display notification "${safeMessage}" with title "${safeTitle}"`}`;
42
- } else if (platform === "linux") {
43
- if (isWSL()) {
44
- // WSL: try notify-send, fail silently
45
- await $`notify-send ${safeTitle} ${safeMessage}`.catch(() => {});
46
- } else {
47
- await $`notify-send ${safeTitle} ${safeMessage}`;
48
- }
49
- } else if (platform === "win32") {
50
- // Windows: PowerShell toast (fire and forget)
51
- await $`powershell -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('${safeMessage}', '${safeTitle}')"`.catch(
52
- () => {},
53
- );
54
- }
55
- } catch {
56
- // Notifications are best-effort, never throw
57
- }
35
+ try {
36
+ if (platform === "darwin") {
37
+ await $`osascript -e ${`display notification "${safeMessage}" with title "${safeTitle}"`}`;
38
+ } else if (platform === "linux") {
39
+ if (isWSL()) {
40
+ // WSL: try notify-send, fail silently
41
+ await $`notify-send ${safeTitle} ${safeMessage}`.catch(() => {});
42
+ } else {
43
+ await $`notify-send ${safeTitle} ${safeMessage}`;
44
+ }
45
+ } else if (platform === "win32") {
46
+ // Windows: PowerShell toast (fire and forget)
47
+ await $`powershell -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('${safeMessage}', '${safeTitle}')"`.catch(
48
+ () => {},
49
+ );
50
+ }
51
+ } catch {
52
+ // Notifications are best-effort, never throw
53
+ }
58
54
  }
59
55
 
60
56
  /**
61
57
  * Threshold configuration for context monitoring
62
58
  */
63
59
  export const THRESHOLDS = {
64
- MODERATE: 70,
65
- URGENT: 85,
66
- CRITICAL: 95,
60
+ MODERATE: 70,
61
+ URGENT: 85,
62
+ CRITICAL: 95,
67
63
  } as const;
68
64
 
69
65
  /**
70
66
  * Token statistics from session events
71
67
  */
72
68
  export interface TokenStats {
73
- used: number;
74
- limit: number;
75
- percentage?: number;
69
+ used: number;
70
+ limit: number;
71
+ percentage?: number;
76
72
  }
77
73
 
78
74
  /**
79
75
  * Calculate context percentage from token stats
80
76
  */
81
77
  export function getContextPercentage(stats: TokenStats): number {
82
- if (stats.percentage) return stats.percentage;
83
- if (stats.limit > 0) return Math.round((stats.used / stats.limit) * 100);
84
- return 0;
78
+ if (stats.percentage) return stats.percentage;
79
+ if (stats.limit > 0) return Math.round((stats.used / stats.limit) * 100);
80
+ return 0;
85
81
  }