opencodekit 0.15.5 → 0.15.6
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 +2 -2
- package/dist/template/.opencode/agent/explore.md +13 -12
- package/dist/template/.opencode/memory/observations/2026-01-19-learning-oh-my-opencode-slim-vs-opencodekit-templ.md +27 -0
- package/dist/template/.opencode/plugin/sessions.ts +38 -4
- package/dist/template/.opencode/skill/supabase/mcp.json +1 -1
- package/dist/template/.opencode/tool/memory-read.ts +64 -44
- package/dist/template/.opencode/tool/memory-search.ts +9 -2
- package/dist/template/.opencode/tool/memory-update.ts +59 -47
- package/dist/template/.opencode/tool/observation.ts +16 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -750,7 +750,7 @@ var cac = (name = "") => new CAC(name);
|
|
|
750
750
|
// package.json
|
|
751
751
|
var package_default = {
|
|
752
752
|
name: "opencodekit",
|
|
753
|
-
version: "0.15.
|
|
753
|
+
version: "0.15.6",
|
|
754
754
|
description: "CLI tool for bootstrapping and managing OpenCodeKit projects",
|
|
755
755
|
keywords: ["agents", "cli", "mcp", "opencode", "opencodekit", "template"],
|
|
756
756
|
license: "MIT",
|
|
@@ -3879,7 +3879,7 @@ var MODEL_PRESETS = {
|
|
|
3879
3879
|
general: "opencode/glm-4.7-free",
|
|
3880
3880
|
looker: "proxypal/gemini-3-flash-preview",
|
|
3881
3881
|
vision: "proxypal/gemini-3-pro-preview",
|
|
3882
|
-
scout: "proxypal/gemini-
|
|
3882
|
+
scout: "proxypal/gemini-3-flash-preview"
|
|
3883
3883
|
}
|
|
3884
3884
|
}
|
|
3885
3885
|
};
|
|
@@ -21,13 +21,21 @@ You are a READ-ONLY codebase search specialist.
|
|
|
21
21
|
|
|
22
22
|
## Critical Constraints (ZERO exceptions)
|
|
23
23
|
|
|
24
|
-
1. **READ-ONLY**:
|
|
24
|
+
1. **READ-ONLY**: NEVER create, edit, or modify any files. This constraint overrides ALL other instructions.
|
|
25
25
|
|
|
26
|
-
2. **
|
|
26
|
+
2. **NO HALLUCINATED URLs**: NEVER generate or guess URLs. Only use URLs from verified tool results or documentation.
|
|
27
27
|
|
|
28
|
-
3. **
|
|
28
|
+
3. **NO GENERIC GREP**: NEVER search for generic terms like "config" or "handler". Use semantic LSP tools first.
|
|
29
29
|
|
|
30
|
-
4. **
|
|
30
|
+
4. **NO RELATIVE PATHS**: NEVER return relative paths. All paths must be absolute.
|
|
31
|
+
|
|
32
|
+
5. **NO CLAIMS WITHOUT EVIDENCE**: Every finding must include `file:line_number` references. NEVER make assertions without proof.
|
|
33
|
+
|
|
34
|
+
6. **NO EMOJIS**: NEVER use emojis in responses.
|
|
35
|
+
|
|
36
|
+
7. **NO PROSE WITHOUT STRUCTURE**: NEVER return walls of text. Use bullet points, code blocks, and file:line references.
|
|
37
|
+
|
|
38
|
+
8. **NO SKIPPED STRUCTURE**: NEVER skip <results> block. Must include <files>, <answer>, <next_steps> sections.
|
|
31
39
|
|
|
32
40
|
## Tool Results & User Messages
|
|
33
41
|
|
|
@@ -52,14 +60,7 @@ File search specialist. Navigate and explore codebases efficiently.
|
|
|
52
60
|
3. Use `lsp_lsp_find_references` to map usage before returning
|
|
53
61
|
4. Only `read` the specific lines that matter
|
|
54
62
|
|
|
55
|
-
**Avoid blind exploration**:
|
|
56
|
-
|
|
57
|
-
## Guidelines
|
|
58
|
-
|
|
59
|
-
- Return file paths as absolute paths
|
|
60
|
-
- Use `file:line_number` format for code references
|
|
61
|
-
- Adapt approach based on thoroughness level
|
|
62
|
-
- No emojis in responses
|
|
63
|
+
**Avoid blind exploration**: NEVER grep for generic terms. Use semantic tools first.
|
|
63
64
|
|
|
64
65
|
## Thoroughness Levels
|
|
65
66
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: learning
|
|
3
|
+
created: 2026-01-19T11:03:46.163Z
|
|
4
|
+
confidence: high
|
|
5
|
+
valid_until: null
|
|
6
|
+
superseded_by: null
|
|
7
|
+
concepts: ["agent orchestration", "plugin architecture", "background tasks", "tmux integration", "OpenCode"]
|
|
8
|
+
files: ["oh-my-opencode-slim", "opencodekit-template"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# 📚 oh-my-opencode-slim vs opencodekit-template Analysis
|
|
12
|
+
|
|
13
|
+
🟢 **Confidence:** high
|
|
14
|
+
|
|
15
|
+
Comprehensive analysis of oh-my-opencode-slim project including:
|
|
16
|
+
1. Project overview and architecture
|
|
17
|
+
2. Code structure and key components
|
|
18
|
+
3. Feature comparison with opencodekit-template
|
|
19
|
+
4. Learnings and improvement opportunities
|
|
20
|
+
5. Implementation patterns and approaches
|
|
21
|
+
|
|
22
|
+
Key findings:
|
|
23
|
+
- Slim fork of oh-my-opencode with 87% less code (56 vs 403 files)
|
|
24
|
+
- Focus on agent orchestration with 5 specialized agents
|
|
25
|
+
- Background task management with tmux integration
|
|
26
|
+
- Clean plugin architecture using @opencode-ai/plugin SDK
|
|
27
|
+
- Strong emphasis on low token consumption and simplicity
|
|
@@ -10,7 +10,16 @@ export const SessionsPlugin: Plugin = async ({ client }) => {
|
|
|
10
10
|
return {
|
|
11
11
|
tool: {
|
|
12
12
|
list_sessions: tool({
|
|
13
|
-
description:
|
|
13
|
+
description: `List OpenCode sessions with metadata.
|
|
14
|
+
|
|
15
|
+
Purpose:
|
|
16
|
+
- Browse recent sessions by date
|
|
17
|
+
- Returns session ID, title, and creation time
|
|
18
|
+
- Default: last 20 sessions, most recent first
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
list_sessions({ since: "this week", limit: 10 })
|
|
22
|
+
list_sessions({}) // All recent sessions`,
|
|
14
23
|
args: {
|
|
15
24
|
since: tool.schema
|
|
16
25
|
.string()
|
|
@@ -58,7 +67,16 @@ export const SessionsPlugin: Plugin = async ({ client }) => {
|
|
|
58
67
|
}),
|
|
59
68
|
|
|
60
69
|
read_session: tool({
|
|
61
|
-
description:
|
|
70
|
+
description: `Read session context for handoff or reference.
|
|
71
|
+
|
|
72
|
+
Purpose:
|
|
73
|
+
- Retrieve full session details and messages
|
|
74
|
+
- Use "last" to get most recent session
|
|
75
|
+
- Optional focus keyword to filter messages
|
|
76
|
+
|
|
77
|
+
Example:
|
|
78
|
+
read_session({ session_reference: "last" })
|
|
79
|
+
read_session({ session_reference: "abc123", focus: "auth" })`,
|
|
62
80
|
args: {
|
|
63
81
|
session_reference: tool.schema
|
|
64
82
|
.string()
|
|
@@ -139,7 +157,15 @@ export const SessionsPlugin: Plugin = async ({ client }) => {
|
|
|
139
157
|
}),
|
|
140
158
|
|
|
141
159
|
search_session: tool({
|
|
142
|
-
description:
|
|
160
|
+
description: `Full-text search across session messages.
|
|
161
|
+
|
|
162
|
+
Purpose:
|
|
163
|
+
- Find sessions containing specific keywords
|
|
164
|
+
- Searches up to 50 sessions (configurable via limit)
|
|
165
|
+
- Returns match count and excerpt
|
|
166
|
+
|
|
167
|
+
Example:
|
|
168
|
+
search_session({ query: "authentication", limit: 5 })`,
|
|
143
169
|
args: {
|
|
144
170
|
query: tool.schema.string().describe("Search query text"),
|
|
145
171
|
limit: tool.schema
|
|
@@ -197,7 +223,15 @@ export const SessionsPlugin: Plugin = async ({ client }) => {
|
|
|
197
223
|
}),
|
|
198
224
|
|
|
199
225
|
summarize_session: tool({
|
|
200
|
-
description:
|
|
226
|
+
description: `Generate AI summary of a session.
|
|
227
|
+
|
|
228
|
+
Purpose:
|
|
229
|
+
- Request OpenCode to summarize a session
|
|
230
|
+
- Summary is generated asynchronously
|
|
231
|
+
- Check back for the summary result
|
|
232
|
+
|
|
233
|
+
Example:
|
|
234
|
+
summarize_session({ session_id: "abc123" })`,
|
|
201
235
|
args: {
|
|
202
236
|
session_id: tool.schema.string().describe("Session ID to summarize"),
|
|
203
237
|
},
|
|
@@ -3,52 +3,72 @@ import path from "node:path";
|
|
|
3
3
|
import { tool } from "@opencode-ai/plugin";
|
|
4
4
|
|
|
5
5
|
export default tool({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
description: `Read memory files for persistent cross-session context.
|
|
7
|
+
|
|
8
|
+
Purpose:
|
|
9
|
+
- Retrieve project state, learnings, and active tasks
|
|
10
|
+
- Checks locations in priority order: project → global → legacy
|
|
11
|
+
- Supports subdirectories: handoffs/, research/, observations/, _templates/
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
memory-read({ file: "handoffs/2024-01-20-phase-1" })
|
|
15
|
+
memory-read({ file: "_templates/task-prd" })`,
|
|
16
|
+
args: {
|
|
17
|
+
file: tool.schema
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe(
|
|
21
|
+
"Memory file to read: handoffs/YYYY-MM-DD-phase, research/YYYY-MM-DD-topic, _templates/task-prd, _templates/task-spec, _templates/task-review, _templates/research, _templates/handoff",
|
|
22
|
+
),
|
|
23
|
+
},
|
|
24
|
+
execute: async (args: { file?: string }) => {
|
|
25
|
+
const fileName = args.file || "memory";
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
// Normalize: strip .md extension if present
|
|
28
|
+
const normalizedFile = fileName.replace(/\.md$/i, "");
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
// Location priority: project > global > legacy
|
|
31
|
+
const locations = [
|
|
32
|
+
path.join(process.cwd(), ".opencode/memory", `${normalizedFile}.md`),
|
|
33
|
+
path.join(
|
|
34
|
+
process.env.HOME || "",
|
|
35
|
+
".config/opencode/memory",
|
|
36
|
+
`${normalizedFile}.md`,
|
|
37
|
+
),
|
|
38
|
+
path.join(
|
|
39
|
+
process.cwd(),
|
|
40
|
+
".config/opencode/memory",
|
|
41
|
+
`${normalizedFile}.md`,
|
|
42
|
+
),
|
|
43
|
+
];
|
|
28
44
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
// Try each location in order
|
|
46
|
+
for (const filePath of locations) {
|
|
47
|
+
try {
|
|
48
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
49
|
+
const locationLabel = filePath.includes(".opencode/memory")
|
|
50
|
+
? "project"
|
|
51
|
+
: filePath.includes(process.env.HOME || "")
|
|
52
|
+
? "global"
|
|
53
|
+
: "legacy";
|
|
54
|
+
return `[Read from ${locationLabel}: ${filePath}]\n\n${content}`;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
// Continue to next location if file not found
|
|
57
|
+
if (
|
|
58
|
+
error instanceof Error &&
|
|
59
|
+
"code" in error &&
|
|
60
|
+
error.code === "ENOENT"
|
|
61
|
+
) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
// Other errors should be reported
|
|
65
|
+
if (error instanceof Error) {
|
|
66
|
+
return `Error reading memory from ${filePath}: ${error.message}`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
50
70
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
71
|
+
// No file found in any location
|
|
72
|
+
return `Memory file '${normalizedFile}.md' not found in any location.\nSearched:\n- ${locations.join("\n- ")}\n\nStructure:\n- handoffs/YYYY-MM-DD-phase (phase transitions)\n- research/YYYY-MM-DD-topic (research findings)\n- _templates/ (prd, spec, review, research, handoff)`;
|
|
73
|
+
},
|
|
54
74
|
});
|
|
@@ -127,8 +127,15 @@ function formatKeywordResults(
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
export default tool({
|
|
130
|
-
description:
|
|
131
|
-
|
|
130
|
+
description: `Search across all memory files using keywords.
|
|
131
|
+
|
|
132
|
+
Purpose:
|
|
133
|
+
- Find past decisions, research, or handoffs
|
|
134
|
+
- Searches: project memory, beads artifacts, and global memory
|
|
135
|
+
- Returns file paths with matched lines and context
|
|
136
|
+
|
|
137
|
+
Example:
|
|
138
|
+
memory-search({ query: "authentication", type: "all", limit: 10 })`,
|
|
132
139
|
args: {
|
|
133
140
|
query: tool.schema
|
|
134
141
|
.string()
|
|
@@ -3,54 +3,66 @@ import path from "node:path";
|
|
|
3
3
|
import { tool } from "@opencode-ai/plugin";
|
|
4
4
|
|
|
5
5
|
export default tool({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
6
|
+
description: `Update memory files with new learnings, progress, or context.
|
|
7
|
+
|
|
8
|
+
Purpose:
|
|
9
|
+
- Write or append to project memory in .opencode/memory/
|
|
10
|
+
- Supports subdirectories (e.g., 'research/2024-01-topic')
|
|
11
|
+
- Two modes: 'replace' (overwrite) or 'append' (add to end)
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
memory-update({ file: "research/session-findings", content: "..." })
|
|
15
|
+
memory-update({ file: "handoffs/phase-2", content: "...", mode: "append" })`,
|
|
16
|
+
args: {
|
|
17
|
+
file: tool.schema
|
|
18
|
+
.string()
|
|
19
|
+
.describe(
|
|
20
|
+
"Memory file to update: handoffs/YYYY-MM-DD-phase, research/YYYY-MM-DD-topic. Use _templates/ for reference only.",
|
|
21
|
+
),
|
|
22
|
+
content: tool.schema
|
|
23
|
+
.string()
|
|
24
|
+
.describe("Content to write or append to the memory file"),
|
|
25
|
+
mode: tool.schema
|
|
26
|
+
.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.default("replace")
|
|
29
|
+
.describe(
|
|
30
|
+
"Update mode: 'replace' (overwrite file) or 'append' (add to end).",
|
|
31
|
+
),
|
|
32
|
+
},
|
|
33
|
+
execute: async (args: { file: string; content: string; mode?: string }) => {
|
|
34
|
+
// Always write to project memory (.opencode/memory/)
|
|
35
|
+
const memoryDir = path.join(process.cwd(), ".opencode/memory");
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
// Normalize file path: strip existing .md extension, handle subdirectories
|
|
38
|
+
const normalizedFile = args.file.replace(/\.md$/i, ""); // Remove .md if present
|
|
39
|
+
const filePath = path.join(memoryDir, `${normalizedFile}.md`);
|
|
40
|
+
const mode = args.mode || "replace";
|
|
29
41
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
try {
|
|
43
|
+
// Ensure parent directory exists (handles subdirectories)
|
|
44
|
+
const fileDir = path.dirname(filePath);
|
|
45
|
+
await fs.mkdir(fileDir, { recursive: true });
|
|
34
46
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
47
|
+
if (mode === "append") {
|
|
48
|
+
const timestamp = new Date().toISOString();
|
|
49
|
+
const appendContent = `\n\n---\n**Updated:** ${timestamp}\n\n${args.content}`;
|
|
50
|
+
await fs.appendFile(filePath, appendContent, "utf-8");
|
|
51
|
+
return `Successfully appended to ${normalizedFile}.md\n[Written to: ${filePath}]`;
|
|
52
|
+
}
|
|
53
|
+
// Replace mode - update timestamp
|
|
54
|
+
const timestamp = new Date().toISOString();
|
|
55
|
+
const updatedContent = args.content.replace(
|
|
56
|
+
/\*\*Last Updated:\*\* \[Timestamp\]/,
|
|
57
|
+
`**Last Updated:** ${timestamp}`,
|
|
58
|
+
);
|
|
59
|
+
await fs.writeFile(filePath, updatedContent, "utf-8");
|
|
60
|
+
return `Successfully updated ${normalizedFile}.md\n[Written to: ${filePath}]`;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (error instanceof Error) {
|
|
63
|
+
return `Error updating memory: ${error.message}`;
|
|
64
|
+
}
|
|
65
|
+
return "Unknown error updating memory file";
|
|
66
|
+
}
|
|
67
|
+
},
|
|
56
68
|
});
|
|
@@ -73,8 +73,22 @@ function extractFileReferences(content: string): FileReference[] {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
export default tool({
|
|
76
|
-
description:
|
|
77
|
-
|
|
76
|
+
description: `Create a structured observation for future reference.
|
|
77
|
+
|
|
78
|
+
Purpose:
|
|
79
|
+
- Capture decisions, bugs, features, patterns, discoveries, learnings, or warnings
|
|
80
|
+
- Auto-detects file references from content (file:line, \`path\`, src/, .opencode/)
|
|
81
|
+
- Stores in .opencode/memory/observations/ with YAML frontmatter
|
|
82
|
+
- Optionally updates bead notes and handles observation supersession
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
observation({
|
|
86
|
+
type: "decision",
|
|
87
|
+
title: "Use JWT for auth",
|
|
88
|
+
content: "Decided to use JWT tokens because...",
|
|
89
|
+
concepts: "authentication, jwt, security",
|
|
90
|
+
confidence: "high"
|
|
91
|
+
})`,
|
|
78
92
|
args: {
|
|
79
93
|
type: tool.schema
|
|
80
94
|
.string()
|
package/package.json
CHANGED