opencodekit 0.18.5 → 0.18.7
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 +107 -53
- package/dist/template/.opencode/AGENTS.md +9 -7
- package/dist/template/.opencode/agent/explore.md +25 -28
- package/dist/template/.opencode/command/ship.md +7 -5
- package/dist/template/.opencode/dcp.jsonc +71 -81
- package/dist/template/.opencode/memory/project/gotchas.md +3 -3
- package/dist/template/.opencode/memory.db +0 -0
- package/dist/template/.opencode/memory.db-shm +0 -0
- package/dist/template/.opencode/memory.db-wal +0 -0
- package/dist/template/.opencode/opencode.json +1 -1
- package/dist/template/.opencode/package.json +1 -1
- package/dist/template/.opencode/pnpm-lock.yaml +71 -0
- package/dist/template/.opencode/skill/compaction/SKILL.md +19 -48
- package/dist/template/.opencode/skill/context-engineering/SKILL.md +1 -1
- package/dist/template/.opencode/skill/context-management/SKILL.md +16 -26
- package/dist/template/.opencode/skill/executing-plans/SKILL.md +155 -138
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { cac } from "cac";
|
|
4
4
|
import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
|
-
import { basename, dirname, join, relative
|
|
5
|
+
import { basename, dirname, join, relative } from "node:path";
|
|
6
6
|
import * as p from "@clack/prompts";
|
|
7
7
|
import color from "picocolors";
|
|
8
8
|
import { z } from "zod";
|
|
@@ -18,11 +18,35 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
18
18
|
|
|
19
19
|
//#endregion
|
|
20
20
|
//#region package.json
|
|
21
|
-
var version = "0.18.
|
|
21
|
+
var version = "0.18.7";
|
|
22
22
|
|
|
23
23
|
//#endregion
|
|
24
24
|
//#region src/utils/errors.ts
|
|
25
25
|
/**
|
|
26
|
+
* Resolve the .opencode directory path.
|
|
27
|
+
* Handles two cases:
|
|
28
|
+
* 1. Standard project: cwd has .opencode/ subdirectory
|
|
29
|
+
* 2. Global config dir: cwd IS the opencode config dir (has opencode.json directly)
|
|
30
|
+
* Returns null if neither case applies.
|
|
31
|
+
*/
|
|
32
|
+
function resolveOpencodePath() {
|
|
33
|
+
const nested = join(process.cwd(), ".opencode");
|
|
34
|
+
if (existsSync(nested)) return nested;
|
|
35
|
+
if (existsSync(join(process.cwd(), "opencode.json"))) return process.cwd();
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolve opencode path or show "not initialized" error and return null.
|
|
40
|
+
*/
|
|
41
|
+
function requireOpencodePath() {
|
|
42
|
+
const resolved = resolveOpencodePath();
|
|
43
|
+
if (!resolved) {
|
|
44
|
+
notInitialized();
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return resolved;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
26
50
|
* Display a styled error message with optional fix suggestion
|
|
27
51
|
*/
|
|
28
52
|
function showError(message, fix) {
|
|
@@ -79,7 +103,8 @@ const InitOptionsSchema = z.object({
|
|
|
79
103
|
yes: z.boolean().optional().default(false),
|
|
80
104
|
backup: z.boolean().optional().default(false),
|
|
81
105
|
prune: z.boolean().optional().default(false),
|
|
82
|
-
pruneAll: z.boolean().optional().default(false)
|
|
106
|
+
pruneAll: z.boolean().optional().default(false),
|
|
107
|
+
projectOnly: z.boolean().optional().default(false)
|
|
83
108
|
});
|
|
84
109
|
const UpgradeOptionsSchema = z.object({
|
|
85
110
|
force: z.boolean().optional().default(false),
|
|
@@ -192,11 +217,8 @@ function parseAction(schema, action) {
|
|
|
192
217
|
//#region src/commands/agent.ts
|
|
193
218
|
async function agentCommand(action) {
|
|
194
219
|
const validatedAction = parseAction(AgentActionSchema, action);
|
|
195
|
-
const opencodePath =
|
|
196
|
-
if (!
|
|
197
|
-
notInitialized();
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
220
|
+
const opencodePath = requireOpencodePath();
|
|
221
|
+
if (!opencodePath) return;
|
|
200
222
|
const agentPath = join(opencodePath, "agent");
|
|
201
223
|
switch (validatedAction) {
|
|
202
224
|
case "list":
|
|
@@ -473,11 +495,8 @@ async function removeAgent(agentPath, agentNameArg) {
|
|
|
473
495
|
//#region src/commands/command.ts
|
|
474
496
|
async function commandCommand(action) {
|
|
475
497
|
const validatedAction = parseAction(CommandActionSchema, action);
|
|
476
|
-
const opencodePath =
|
|
477
|
-
if (!
|
|
478
|
-
notInitialized();
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
498
|
+
const opencodePath = requireOpencodePath();
|
|
499
|
+
if (!opencodePath) return;
|
|
481
500
|
const commandDir = join(opencodePath, "command");
|
|
482
501
|
switch (validatedAction) {
|
|
483
502
|
case "list":
|
|
@@ -982,12 +1001,9 @@ async function getAgentsFromServer() {
|
|
|
982
1001
|
return fetchFromServer("/agent");
|
|
983
1002
|
}
|
|
984
1003
|
async function configCommand(action) {
|
|
985
|
-
const opencodePath =
|
|
1004
|
+
const opencodePath = requireOpencodePath();
|
|
1005
|
+
if (!opencodePath) return;
|
|
986
1006
|
const configPath = join(opencodePath, "opencode.json");
|
|
987
|
-
if (!existsSync(opencodePath)) {
|
|
988
|
-
notInitialized();
|
|
989
|
-
return;
|
|
990
|
-
}
|
|
991
1007
|
if (!existsSync(configPath)) {
|
|
992
1008
|
showError("opencode.json not found", "ock init --force");
|
|
993
1009
|
return;
|
|
@@ -2758,6 +2774,34 @@ const EXCLUDED_FILES = [
|
|
|
2758
2774
|
"pnpm-lock.yaml"
|
|
2759
2775
|
];
|
|
2760
2776
|
const PRESERVE_USER_DIRS = ["memory/project", "context"];
|
|
2777
|
+
const SHARED_CONFIG_DIRS = [
|
|
2778
|
+
"agent",
|
|
2779
|
+
"command",
|
|
2780
|
+
"skill",
|
|
2781
|
+
"tool"
|
|
2782
|
+
];
|
|
2783
|
+
/**
|
|
2784
|
+
* Detect if global config has any of the shared dirs populated.
|
|
2785
|
+
* Returns null if no global config or no shared dirs found.
|
|
2786
|
+
*/
|
|
2787
|
+
function detectGlobalConfig() {
|
|
2788
|
+
const globalDir = getGlobalConfigDir();
|
|
2789
|
+
if (!existsSync(globalDir)) return null;
|
|
2790
|
+
const coveredDirs = SHARED_CONFIG_DIRS.filter((d) => {
|
|
2791
|
+
const dirPath = join(globalDir, d);
|
|
2792
|
+
if (!existsSync(dirPath)) return false;
|
|
2793
|
+
try {
|
|
2794
|
+
return readdirSync(dirPath).filter((e) => !e.startsWith(".")).length > 0;
|
|
2795
|
+
} catch {
|
|
2796
|
+
return false;
|
|
2797
|
+
}
|
|
2798
|
+
});
|
|
2799
|
+
if (coveredDirs.length === 0) return null;
|
|
2800
|
+
return {
|
|
2801
|
+
dir: globalDir,
|
|
2802
|
+
coveredDirs
|
|
2803
|
+
};
|
|
2804
|
+
}
|
|
2761
2805
|
/**
|
|
2762
2806
|
* Get the global OpenCode config directory based on OS.
|
|
2763
2807
|
* - macOS/Linux: ~/.config/opencode/ (respects XDG_CONFIG_HOME)
|
|
@@ -2801,10 +2845,25 @@ async function copyDir(src, dest) {
|
|
|
2801
2845
|
else writeFileSync(destPath, readFileSync(srcPath, "utf-8"));
|
|
2802
2846
|
}
|
|
2803
2847
|
}
|
|
2804
|
-
async function copyOpenCodeOnly(templateRoot, targetDir) {
|
|
2848
|
+
async function copyOpenCodeOnly(templateRoot, targetDir, skipDirs) {
|
|
2805
2849
|
const opencodeSrc = join(templateRoot, ".opencode");
|
|
2806
2850
|
const opencodeDest = join(targetDir, ".opencode");
|
|
2807
2851
|
if (!existsSync(opencodeSrc)) return false;
|
|
2852
|
+
if (skipDirs && skipDirs.length > 0) {
|
|
2853
|
+
const skipSet = new Set(skipDirs);
|
|
2854
|
+
mkdirSync(opencodeDest, { recursive: true });
|
|
2855
|
+
for (const entry of readdirSync(opencodeSrc, { withFileTypes: true })) {
|
|
2856
|
+
if (EXCLUDED_DIRS.includes(entry.name)) continue;
|
|
2857
|
+
if (!entry.isDirectory() && EXCLUDED_FILES.includes(entry.name)) continue;
|
|
2858
|
+
if (entry.isSymbolicLink()) continue;
|
|
2859
|
+
if (entry.isDirectory() && skipSet.has(entry.name)) continue;
|
|
2860
|
+
const srcPath = join(opencodeSrc, entry.name);
|
|
2861
|
+
const destPath = join(opencodeDest, entry.name);
|
|
2862
|
+
if (entry.isDirectory()) await copyDir(srcPath, destPath);
|
|
2863
|
+
else writeFileSync(destPath, readFileSync(srcPath, "utf-8"));
|
|
2864
|
+
}
|
|
2865
|
+
return true;
|
|
2866
|
+
}
|
|
2808
2867
|
await copyDir(opencodeSrc, opencodeDest);
|
|
2809
2868
|
return true;
|
|
2810
2869
|
}
|
|
@@ -3100,18 +3159,36 @@ async function initCommand(rawOptions = {}) {
|
|
|
3100
3159
|
}
|
|
3101
3160
|
projectName = name || projectName;
|
|
3102
3161
|
}
|
|
3162
|
+
let skipDirs = [];
|
|
3163
|
+
if (!options.global) {
|
|
3164
|
+
const globalConfig = detectGlobalConfig();
|
|
3165
|
+
if (globalConfig && options.projectOnly) {
|
|
3166
|
+
skipDirs = globalConfig.coveredDirs;
|
|
3167
|
+
p.log.info(`Using global config from ${color.cyan(globalConfig.dir)}`);
|
|
3168
|
+
p.log.info(`Skipping: ${skipDirs.map((d) => color.dim(d)).join(", ")}`);
|
|
3169
|
+
} else if (globalConfig && !options.yes) {
|
|
3170
|
+
p.log.info(`Global config found at ${color.cyan(globalConfig.dir)}`);
|
|
3171
|
+
p.log.info(`Available globally: ${globalConfig.coveredDirs.map((d) => color.green(d)).join(", ")}`);
|
|
3172
|
+
const useGlobal = await p.confirm({
|
|
3173
|
+
message: "Skip these (use global config)? Only project-scope files will be created locally.",
|
|
3174
|
+
initialValue: true
|
|
3175
|
+
});
|
|
3176
|
+
if (!p.isCancel(useGlobal) && useGlobal) skipDirs = globalConfig.coveredDirs;
|
|
3177
|
+
} else if (globalConfig && options.yes) p.log.info(`Global config found at ${color.cyan(globalConfig.dir)} — use ${color.bold("--project-only")} to skip shared dirs`);
|
|
3178
|
+
}
|
|
3103
3179
|
const s = p.spinner();
|
|
3104
3180
|
if (mode === "scaffold") {
|
|
3105
3181
|
s.start("Scaffolding project");
|
|
3106
3182
|
mkdirSync(targetDir, { recursive: true });
|
|
3107
3183
|
} else if (mode === "add-config") s.start("Adding OpenCodeKit");
|
|
3108
3184
|
else s.start("Reinitializing");
|
|
3109
|
-
if (!await copyOpenCodeOnly(templateRoot, targetDir)) {
|
|
3185
|
+
if (!await copyOpenCodeOnly(templateRoot, targetDir, skipDirs)) {
|
|
3110
3186
|
s.stop("Failed");
|
|
3111
3187
|
p.outro(color.red("Template copy failed"));
|
|
3112
3188
|
process.exit(1);
|
|
3113
3189
|
}
|
|
3114
3190
|
s.stop("Done");
|
|
3191
|
+
if (skipDirs.length > 0) p.log.info(`Project-only init: skipped ${skipDirs.map((d) => color.dim(d)).join(", ")} (using global config)`);
|
|
3115
3192
|
const restoredFileCount = finalizeInstalledFiles(targetDir, getPackageVersion$1(), preservedFiles);
|
|
3116
3193
|
if (restoredFileCount > 0) p.log.info(`Preserved ${restoredFileCount} user memory files (memory/project/)`);
|
|
3117
3194
|
if (options.free) {
|
|
@@ -3280,11 +3357,8 @@ async function initCommand(rawOptions = {}) {
|
|
|
3280
3357
|
//#region src/commands/skill.ts
|
|
3281
3358
|
async function skillCommand(action) {
|
|
3282
3359
|
const validatedAction = parseAction(SkillActionSchema, action);
|
|
3283
|
-
const opencodePath =
|
|
3284
|
-
if (!
|
|
3285
|
-
notInitialized();
|
|
3286
|
-
return;
|
|
3287
|
-
}
|
|
3360
|
+
const opencodePath = requireOpencodePath();
|
|
3361
|
+
if (!opencodePath) return;
|
|
3288
3362
|
const skillDir = join(opencodePath, "skill");
|
|
3289
3363
|
switch (validatedAction) {
|
|
3290
3364
|
case "list":
|
|
@@ -3684,12 +3758,9 @@ function findUpgradeOrphans(installedFiles, templateFiles) {
|
|
|
3684
3758
|
async function upgradeCommand(rawOptions = {}) {
|
|
3685
3759
|
const options = parseOptions(UpgradeOptionsSchema, rawOptions);
|
|
3686
3760
|
if (process.argv.includes("--quiet")) return;
|
|
3687
|
-
const opencodeDir =
|
|
3761
|
+
const opencodeDir = requireOpencodePath();
|
|
3762
|
+
if (!opencodeDir) return;
|
|
3688
3763
|
const manifest = loadManifest(opencodeDir);
|
|
3689
|
-
if (!existsSync(opencodeDir)) {
|
|
3690
|
-
notInitialized();
|
|
3691
|
-
return;
|
|
3692
|
-
}
|
|
3693
3764
|
p.intro(color.bgCyan(color.black(" Upgrade ")));
|
|
3694
3765
|
const versionInfo = await checkVersion(opencodeDir);
|
|
3695
3766
|
console.log();
|
|
@@ -4120,11 +4191,8 @@ function displayChecks(checks) {
|
|
|
4120
4191
|
async function statusCommand() {
|
|
4121
4192
|
if (process.argv.includes("--quiet")) return;
|
|
4122
4193
|
const cwd = process.cwd();
|
|
4123
|
-
const opencodeDir =
|
|
4124
|
-
if (!
|
|
4125
|
-
notInitialized();
|
|
4126
|
-
return;
|
|
4127
|
-
}
|
|
4194
|
+
const opencodeDir = requireOpencodePath();
|
|
4195
|
+
if (!opencodeDir) return;
|
|
4128
4196
|
const projectName = basename(cwd);
|
|
4129
4197
|
p.intro(color.bgCyan(color.black(` ${projectName} `)));
|
|
4130
4198
|
const agentDir = join(opencodeDir, "agent");
|
|
@@ -4163,14 +4231,6 @@ async function statusCommand() {
|
|
|
4163
4231
|
|
|
4164
4232
|
//#endregion
|
|
4165
4233
|
//#region src/commands/patch.ts
|
|
4166
|
-
function getOpencodeDir() {
|
|
4167
|
-
const opencodeDir = join(resolve("."), ".opencode");
|
|
4168
|
-
if (!existsSync(opencodeDir)) {
|
|
4169
|
-
notInitialized();
|
|
4170
|
-
return null;
|
|
4171
|
-
}
|
|
4172
|
-
return opencodeDir;
|
|
4173
|
-
}
|
|
4174
4234
|
function listPatches(opencodeDir) {
|
|
4175
4235
|
const metadata = loadPatchMetadata(opencodeDir);
|
|
4176
4236
|
const entries = Object.entries(metadata.patches);
|
|
@@ -4399,7 +4459,7 @@ function togglePatch(opencodeDir, disable) {
|
|
|
4399
4459
|
}
|
|
4400
4460
|
}
|
|
4401
4461
|
async function patchCommand(action) {
|
|
4402
|
-
const opencodeDir =
|
|
4462
|
+
const opencodeDir = requireOpencodePath();
|
|
4403
4463
|
if (!opencodeDir) return;
|
|
4404
4464
|
const validatedAction = parseAction(PatchActionSchema, action);
|
|
4405
4465
|
if (!validatedAction) {
|
|
@@ -5416,7 +5476,7 @@ function stripAnsi(str) {
|
|
|
5416
5476
|
//#region src/tui/hooks/useData.ts
|
|
5417
5477
|
function loadProjectData() {
|
|
5418
5478
|
const cwd = process.cwd();
|
|
5419
|
-
const opencodeDir = join(cwd, ".opencode");
|
|
5479
|
+
const opencodeDir = resolveOpencodePath() ?? join(cwd, ".opencode");
|
|
5420
5480
|
const projectName = basename(cwd);
|
|
5421
5481
|
const agentDir = join(opencodeDir, "agent");
|
|
5422
5482
|
let agents = [];
|
|
@@ -5445,9 +5505,6 @@ function loadProjectData() {
|
|
|
5445
5505
|
mcpServers
|
|
5446
5506
|
};
|
|
5447
5507
|
}
|
|
5448
|
-
function isInitialized() {
|
|
5449
|
-
return existsSync(join(process.cwd(), ".opencode"));
|
|
5450
|
-
}
|
|
5451
5508
|
|
|
5452
5509
|
//#endregion
|
|
5453
5510
|
//#region src/tui/index.ts
|
|
@@ -5455,10 +5512,7 @@ function isInitialized() {
|
|
|
5455
5512
|
* Launch the TUI dashboard with interactive navigation.
|
|
5456
5513
|
*/
|
|
5457
5514
|
async function launchTUI() {
|
|
5458
|
-
if (!
|
|
5459
|
-
notInitialized();
|
|
5460
|
-
return;
|
|
5461
|
-
}
|
|
5515
|
+
if (!requireOpencodePath()) return;
|
|
5462
5516
|
await mainMenu();
|
|
5463
5517
|
}
|
|
5464
5518
|
async function mainMenu() {
|
|
@@ -5561,7 +5615,7 @@ const cli = cac("ock");
|
|
|
5561
5615
|
cli.option("--verbose", "Enable verbose logging");
|
|
5562
5616
|
cli.option("--quiet", "Suppress all output");
|
|
5563
5617
|
cli.version(`${packageVersion}`);
|
|
5564
|
-
cli.command("init", "Initialize OpenCodeKit in current directory").option("--force", "Reinitialize even if already exists").option("--beads", "Also initialize .beads/ for multi-agent coordination").option("--global", "Install to global OpenCode config (~/.config/opencode/)").option("--free", "Use free models (default)").option("--recommend", "Use recommended premium models").option("-y, --yes", "Skip prompts, use defaults (for CI)").option("--backup", "Backup existing .opencode before overwriting").option("--prune", "Manually select orphan files to delete").option("--prune-all", "Auto-delete all orphan files").action(initCommand);
|
|
5618
|
+
cli.command("init", "Initialize OpenCodeKit in current directory").option("--force", "Reinitialize even if already exists").option("--beads", "Also initialize .beads/ for multi-agent coordination").option("--global", "Install to global OpenCode config (~/.config/opencode/)").option("--free", "Use free models (default)").option("--recommend", "Use recommended premium models").option("-y, --yes", "Skip prompts, use defaults (for CI)").option("--backup", "Backup existing .opencode before overwriting").option("--prune", "Manually select orphan files to delete").option("--prune-all", "Auto-delete all orphan files").option("--project-only", "Only init project-scope files (skip if global config has agents/skills/commands/tools)").action(initCommand);
|
|
5565
5619
|
cli.command("agent [action]", "Manage agents (list, add, view)").action(async (action) => {
|
|
5566
5620
|
if (!action) {
|
|
5567
5621
|
console.log("\nUsage: ock agent <action>\n");
|
|
@@ -201,19 +201,21 @@ For major tracked work:
|
|
|
201
201
|
| Phase | Target | Action |
|
|
202
202
|
| ----------------- | ------- | ------------------------------------------ |
|
|
203
203
|
| Starting work | <50k | Load only essential AGENTS.md + task spec |
|
|
204
|
-
| Mid-task | 50-100k |
|
|
205
|
-
| Approaching limit | >100k | Aggressive
|
|
204
|
+
| Mid-task | 50-100k | Compress completed phases, keep active files |
|
|
205
|
+
| Approaching limit | >100k | Aggressive compression, sweep stale noise |
|
|
206
206
|
| Near capacity | >150k | Session restart with handoff |
|
|
207
207
|
|
|
208
|
-
###
|
|
208
|
+
### DCP Commands
|
|
209
209
|
|
|
210
|
-
- `
|
|
211
|
-
- `
|
|
210
|
+
- `/dcp context` — Show current context health and pressure
|
|
211
|
+
- `/dcp compress` — Compress completed conversation ranges (primary tool)
|
|
212
|
+
- `/dcp sweep` — Remove stale/noisy content according to DCP rules
|
|
213
|
+
- `/dcp stats` — Inspect pruning/compression activity
|
|
212
214
|
|
|
213
215
|
### Rules
|
|
214
216
|
|
|
215
|
-
1. **
|
|
216
|
-
2. **Batch
|
|
217
|
+
1. **Compress at phase boundaries** — not during active edits
|
|
218
|
+
2. **Batch cleanup** — use `/dcp sweep` for stale noise, not ad-hoc deletion
|
|
217
219
|
3. **Protected content** — AGENTS.md, .opencode/, .beads/, config files
|
|
218
220
|
|
|
219
221
|
---
|
|
@@ -11,6 +11,9 @@ tools:
|
|
|
11
11
|
memory-update: false
|
|
12
12
|
observation: false
|
|
13
13
|
question: false
|
|
14
|
+
websearch: false
|
|
15
|
+
webfetch: false
|
|
16
|
+
codesearch: false
|
|
14
17
|
---
|
|
15
18
|
|
|
16
19
|
You are OpenCode, the best coding agent on the planet.
|
|
@@ -19,8 +22,6 @@ You are OpenCode, the best coding agent on the planet.
|
|
|
19
22
|
|
|
20
23
|
**Purpose**: Read-only codebase cartographer — you map terrain, you don't build on it.
|
|
21
24
|
|
|
22
|
-
> _"Agency is knowing where the levers are before you pull them."_
|
|
23
|
-
|
|
24
25
|
## Identity
|
|
25
26
|
|
|
26
27
|
You are a read-only codebase explorer. You output concise, evidence-backed findings with absolute paths only.
|
|
@@ -29,45 +30,41 @@ You are a read-only codebase explorer. You output concise, evidence-backed findi
|
|
|
29
30
|
|
|
30
31
|
Find relevant files, symbols, and usage paths quickly for the caller.
|
|
31
32
|
|
|
32
|
-
##
|
|
33
|
+
## Tools — Use These for Local Code Search
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
| Tool | Use For | Example |
|
|
36
|
+
|------|---------|--------|
|
|
37
|
+
| `grep` | Find text/regex patterns in files | `grep(pattern: "PatchEntry", include: "*.ts")` |
|
|
38
|
+
| `glob` | Find files by name/pattern | `glob(pattern: "src/**/*.ts")` |
|
|
39
|
+
| `lsp` (goToDefinition) | Jump to symbol definition | `lsp(operation: "goToDefinition", filePath: "...", line: N, character: N)` |
|
|
40
|
+
| `lsp` (findReferences) | Find all usages of a symbol | `lsp(operation: "findReferences", ...)` |
|
|
41
|
+
| `lsp` (hover) | Get type info and docs | `lsp(operation: "hover", ...)` |
|
|
42
|
+
| `read` | Read file content | `read(filePath: "src/utils/patch.ts")` |
|
|
35
43
|
|
|
36
|
-
|
|
37
|
-
skill({ name: "code-navigation" });
|
|
38
|
-
```
|
|
44
|
+
**NEVER** use `websearch`, `webfetch`, or `codesearch` — those search the internet, not your project.
|
|
39
45
|
|
|
40
46
|
## Rules
|
|
41
47
|
|
|
42
48
|
- Never modify files — read-only is a hard constraint
|
|
43
49
|
- Return absolute paths in final output
|
|
44
50
|
- Cite `file:line` evidence whenever possible
|
|
45
|
-
-
|
|
46
|
-
-
|
|
51
|
+
- **Always start with `grep` or `glob`** to locate files and symbols — do NOT read directories to browse
|
|
52
|
+
- Use LSP for precise navigation after finding candidate locations
|
|
53
|
+
- Stop when you can answer with concrete evidence
|
|
47
54
|
|
|
48
|
-
##
|
|
55
|
+
## Navigation Patterns
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
- **Cite evidence**: Every finding needs file:line reference
|
|
57
|
+
1. **Search first, read second**: `grep` to find where a symbol lives, then `read` only that section
|
|
58
|
+
2. **Don't re-read**: If you already read a file, reference what you learned — don't read it again
|
|
59
|
+
3. **Follow the chain**: definition → usages → callers via LSP findReferences
|
|
60
|
+
4. **Target ≤3 tool calls per symbol**: grep → read section → done
|
|
55
61
|
|
|
56
62
|
## Workflow
|
|
57
63
|
|
|
58
|
-
1.
|
|
59
|
-
2.
|
|
60
|
-
3.
|
|
61
|
-
4.
|
|
62
|
-
5. Return findings + next steps
|
|
63
|
-
|
|
64
|
-
## Thoroughness Levels
|
|
65
|
-
|
|
66
|
-
| Level | Scope | Use When |
|
|
67
|
-
| --------------- | ----------------------------- | ------------------------------------------ |
|
|
68
|
-
| `quick` | 1-3 files, direct answer | Simple lookups, known symbol names |
|
|
69
|
-
| `medium` | 3-6 files, include call paths | Understanding feature flow |
|
|
70
|
-
| `very thorough` | Dependency map + edge cases | Complex refactor prep, architecture review |
|
|
64
|
+
1. `grep` or `glob` to discover candidate files
|
|
65
|
+
2. `lsp` goToDefinition/findReferences for precise symbol navigation
|
|
66
|
+
3. `read` only the relevant sections (use offset/limit)
|
|
67
|
+
4. Return findings with file:line evidence
|
|
71
68
|
|
|
72
69
|
## Output
|
|
73
70
|
|
|
@@ -75,13 +75,15 @@ ls .beads/artifacts/$ARGUMENTS/
|
|
|
75
75
|
|
|
76
76
|
If `plan.md` exists with dependency graph:
|
|
77
77
|
|
|
78
|
-
1. **
|
|
79
|
-
2. **
|
|
80
|
-
3. **
|
|
81
|
-
|
|
78
|
+
1. **Load skill:** `skill({ name: "executing-plans" })`
|
|
79
|
+
2. **Parse waves** from dependency graph section
|
|
80
|
+
3. **Execute wave-by-wave:**
|
|
81
|
+
- Single-task wave → execute directly (no subagent overhead)
|
|
82
|
+
- Multi-task wave → dispatch parallel `task({ subagent_type: "general" })` subagents, one per task
|
|
83
|
+
4. **Review after each wave** — run verification gates, report, wait for feedback
|
|
82
84
|
5. **Continue** until all waves complete
|
|
83
85
|
|
|
84
|
-
**Parallel safety:** Only tasks within same wave run in parallel. Tasks in Wave N+1 wait for Wave N.
|
|
86
|
+
**Parallel safety:** Only tasks within same wave run in parallel. Tasks must NOT share files. Tasks in Wave N+1 wait for Wave N.
|
|
85
87
|
|
|
86
88
|
### Phase 3A: PRD Task Loop (Sequential Fallback)
|
|
87
89
|
|
|
@@ -1,83 +1,73 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"supersedeWrites": {
|
|
74
|
-
"enabled": true,
|
|
75
|
-
},
|
|
76
|
-
// Purge error inputs after N turns
|
|
77
|
-
"purgeErrors": {
|
|
78
|
-
"enabled": true,
|
|
79
|
-
"turns": 4,
|
|
80
|
-
"protectedTools": [],
|
|
81
|
-
},
|
|
82
|
-
},
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/Opencode-DCP/opencode-dynamic-context-pruning/master/dcp.schema.json",
|
|
3
|
+
"enabled": true,
|
|
4
|
+
"debug": false,
|
|
5
|
+
// "minimal" shows prune activity without noise; "detailed" shows token counts
|
|
6
|
+
"pruneNotification": "detailed",
|
|
7
|
+
// "chat" (in-conversation) or "toast" (system notification)
|
|
8
|
+
"pruneNotificationType": "toast",
|
|
9
|
+
// Commands: /dcp context, /dcp stats, /dcp sweep, /dcp decompress, /dcp recompress
|
|
10
|
+
"commands": {
|
|
11
|
+
"enabled": true,
|
|
12
|
+
// Protect these from /dcp sweep
|
|
13
|
+
"protectedTools": ["observation", "memory-update", "memory-search"]
|
|
14
|
+
},
|
|
15
|
+
"turnProtection": {
|
|
16
|
+
"enabled": true,
|
|
17
|
+
"turns": 4
|
|
18
|
+
},
|
|
19
|
+
// Protected file patterns - never auto-prune reads of these files
|
|
20
|
+
"protectedFilePatterns": [
|
|
21
|
+
"**/.env*",
|
|
22
|
+
"**/AGENTS.md",
|
|
23
|
+
"**/.opencode/**",
|
|
24
|
+
"**/.beads/**",
|
|
25
|
+
"**/package.json",
|
|
26
|
+
"**/tsconfig.json",
|
|
27
|
+
"**/biome.json"
|
|
28
|
+
],
|
|
29
|
+
"compress": {
|
|
30
|
+
// v2.2.x beta: compress is the primary context management tool
|
|
31
|
+
"permission": "allow",
|
|
32
|
+
"showCompression": false,
|
|
33
|
+
"maxContextLimit": "80%",
|
|
34
|
+
"minContextLimit": 30000,
|
|
35
|
+
"flatSchema": false,
|
|
36
|
+
"protectUserMessages": true,
|
|
37
|
+
"protectedTools": [
|
|
38
|
+
"write",
|
|
39
|
+
"edit",
|
|
40
|
+
"memory-*",
|
|
41
|
+
"observation",
|
|
42
|
+
"skill",
|
|
43
|
+
"skill_mcp",
|
|
44
|
+
"task",
|
|
45
|
+
"batch",
|
|
46
|
+
"todowrite",
|
|
47
|
+
"todoread",
|
|
48
|
+
"tilth_*"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
// v2.2.5-beta0: experimental subagent support
|
|
52
|
+
"experimental": {
|
|
53
|
+
"allowSubAgents": true
|
|
54
|
+
},
|
|
55
|
+
// Auto strategies - TOP LEVEL, not under tools
|
|
56
|
+
"strategies": {
|
|
57
|
+
// Dedup = zero LLM cost, high impact - always enable
|
|
58
|
+
"deduplication": {
|
|
59
|
+
"enabled": true,
|
|
60
|
+
"protectedTools": []
|
|
61
|
+
},
|
|
62
|
+
// Supersede writes = zero cost, removes redundant write inputs after read
|
|
63
|
+
"supersedeWrites": {
|
|
64
|
+
"enabled": true
|
|
65
|
+
},
|
|
66
|
+
// Purge error inputs after N turns
|
|
67
|
+
"purgeErrors": {
|
|
68
|
+
"enabled": true,
|
|
69
|
+
"turns": 4,
|
|
70
|
+
"protectedTools": []
|
|
71
|
+
}
|
|
72
|
+
}
|
|
83
73
|
}
|
|
@@ -38,10 +38,10 @@ The edit tool (`str_replace`) is the #1 source of failures in LLM coding. Models
|
|
|
38
38
|
|
|
39
39
|
### Context Hygiene
|
|
40
40
|
|
|
41
|
-
-
|
|
42
|
-
-
|
|
41
|
+
- Compress completed work phases before moving on
|
|
42
|
+
- Use `/dcp sweep` after a closed phase to remove stale noise
|
|
43
43
|
- Token budget: <50k start → 50-100k mid → >150k restart session
|
|
44
|
-
- Subagent outputs can leak tokens —
|
|
44
|
+
- Subagent outputs can leak tokens — compress completed phases and sweep stale subagent noise
|
|
45
45
|
|
|
46
46
|
## OpenCode Config
|
|
47
47
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|