opencodekit 0.14.6 → 0.15.1
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/README.md +2 -2
- package/dist/index.js +435 -57
- package/dist/template/.opencode/.env.example +1 -0
- package/dist/template/.opencode/AGENTS.md +13 -24
- package/dist/template/.opencode/README.md +8 -119
- package/dist/template/.opencode/agent/explore.md +2 -3
- package/dist/template/.opencode/agent/general.md +56 -0
- package/dist/template/.opencode/agent/plan.md +54 -0
- package/dist/template/.opencode/agent/scout.md +15 -5
- package/dist/template/.opencode/command/analyze-project.md +2 -2
- package/dist/template/.opencode/command/brainstorm.md +1 -1
- package/dist/template/.opencode/command/design-audit.md +4 -5
- package/dist/template/.opencode/command/design.md +4 -13
- package/dist/template/.opencode/command/generate-pattern.md +2 -9
- package/dist/template/.opencode/command/implement.md +4 -4
- package/dist/template/.opencode/command/init.md +1 -1
- package/dist/template/.opencode/command/new-feature.md +2 -3
- package/dist/template/.opencode/command/plan.md +1 -1
- package/dist/template/.opencode/command/pr.md +0 -1
- package/dist/template/.opencode/command/research.md +20 -6
- package/dist/template/.opencode/command/restore-image.md +1 -9
- package/dist/template/.opencode/command/revert-feature.md +1 -1
- package/dist/template/.opencode/command/review-codebase.md +4 -4
- package/dist/template/.opencode/command/status.md +1 -2
- package/dist/template/.opencode/command/summarize.md +1 -2
- package/dist/template/.opencode/command/triage.md +4 -32
- package/dist/template/.opencode/dcp.jsonc +68 -68
- package/dist/template/.opencode/memory/_templates/README.md +35 -0
- package/dist/template/.opencode/memory/_templates/project/architecture.md +60 -0
- package/dist/template/.opencode/memory/_templates/project/commands.md +72 -0
- package/dist/template/.opencode/memory/_templates/project/conventions.md +68 -0
- package/dist/template/.opencode/memory/_templates/project/gotchas.md +41 -0
- package/dist/template/.opencode/memory/beads-workflow.md +30 -29
- package/dist/template/.opencode/memory/project/architecture.md +31 -50
- package/dist/template/.opencode/memory/project/commands.md +41 -22
- package/dist/template/.opencode/memory/project/conventions.md +39 -177
- package/dist/template/.opencode/memory/project/gotchas.md +21 -177
- package/dist/template/.opencode/memory/user.example.md +5 -0
- package/dist/template/.opencode/opencode.json +628 -579
- package/dist/template/.opencode/package.json +18 -21
- package/dist/template/.opencode/plugin/compaction.ts +79 -85
- package/dist/template/.opencode/plugin/env-ctx.ts +19 -19
- package/dist/template/.opencode/plugin/lib/notify.ts +41 -45
- package/dist/template/.opencode/plugin/lsp.ts +197 -200
- package/dist/template/.opencode/plugin/memory.ts +14 -112
- package/dist/template/.opencode/plugin/package.json +5 -5
- package/dist/template/.opencode/plugin/sessions.ts +1 -1
- package/dist/template/.opencode/plugin/skill-mcp.ts +486 -521
- package/dist/template/.opencode/plugin/truncator.ts +47 -50
- package/dist/template/.opencode/plugin/tsconfig.json +14 -14
- package/dist/template/.opencode/skill/chrome-devtools/mcp.json +17 -17
- package/dist/template/.opencode/skill/condition-based-waiting/SKILL.md +17 -12
- package/dist/template/.opencode/skill/condition-based-waiting/example.ts +63 -69
- package/dist/template/.opencode/skill/defense-in-depth/SKILL.md +14 -8
- package/dist/template/.opencode/skill/dispatching-parallel-agents/SKILL.md +14 -3
- package/dist/template/.opencode/skill/playwright/mcp.json +14 -14
- package/dist/template/.opencode/skill/receiving-code-review/SKILL.md +21 -8
- package/dist/template/.opencode/skill/requesting-code-review/review.md +14 -0
- package/dist/template/.opencode/skill/root-cause-tracing/SKILL.md +18 -4
- package/dist/template/.opencode/skill/source-code-research/SKILL.md +9 -7
- package/dist/template/.opencode/skill/test-driven-development/SKILL.md +49 -32
- package/dist/template/.opencode/skill/testing-anti-patterns/SKILL.md +40 -22
- package/dist/template/.opencode/skill/testing-skills-with-subagents/SKILL.md +46 -26
- package/dist/template/.opencode/skill/tool-priority/SKILL.md +117 -44
- package/dist/template/.opencode/skill/v0/SKILL.md +1 -7
- package/dist/template/.opencode/skill/verification-before-completion/SKILL.md +27 -19
- package/dist/template/.opencode/skill/writing-skills/anthropic-best-practices.md +171 -148
- package/dist/template/.opencode/skill/writing-skills/persuasion-principles.md +39 -6
- package/dist/template/.opencode/tool/memory-read.ts +44 -56
- package/dist/template/.opencode/tool/memory-search.ts +8 -291
- package/dist/template/.opencode/tool/memory-update.ts +47 -51
- package/dist/template/.opencode/tool/observation.ts +6 -180
- package/dist/template/.opencode/tsconfig.json +19 -19
- package/package.json +19 -15
- package/dist/template/.opencode/.background-tasks.json +0 -114
- package/dist/template/.opencode/.ralph-state.json +0 -12
- package/dist/template/.opencode/agent/build.md +0 -327
- package/dist/template/.opencode/agent/ninja.md +0 -351
- package/dist/template/.opencode/agent/planner.md +0 -281
- package/dist/template/.opencode/agent/rush.md +0 -223
- package/dist/template/.opencode/memory/handoffs/README.md +0 -83
- package/dist/template/.opencode/memory/observations/.gitkeep +0 -0
- package/dist/template/.opencode/memory/observations/2026-01-09-pattern-ampcode-mcp-json-includetools-pattern.md +0 -42
- package/dist/template/.opencode/memory/vector_db/memories.lance/_transactions/0-0d25ba80-ba3b-4209-9046-b45d6093b4da.txn +0 -0
- package/dist/template/.opencode/memory/vector_db/memories.lance/_versions/1.manifest +0 -0
- package/dist/template/.opencode/memory/vector_db/memories.lance/data/1111100101010101011010004a9ef34df6b29f36a9a53a2892.lance +0 -0
- package/dist/template/.opencode/tool/ast-grep.ts +0 -245
- package/dist/template/.opencode/tool/background.ts +0 -509
- package/dist/template/.opencode/tool/bd-inbox.ts +0 -110
- package/dist/template/.opencode/tool/bd-msg.ts +0 -62
- package/dist/template/.opencode/tool/bd-release.ts +0 -71
- package/dist/template/.opencode/tool/bd-reserve.ts +0 -121
- package/dist/template/.opencode/tool/memory-embed.ts +0 -183
- package/dist/template/.opencode/tool/memory-index.ts +0 -769
- package/dist/template/.opencode/tool/repo-map.ts +0 -451
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ create test.txt with "Hello OpenCodeKit"
|
|
|
65
65
|
```
|
|
66
66
|
build (Primary Orchestrator - 70% of work)
|
|
67
67
|
├→ @rush (Fast agent for simple tasks)
|
|
68
|
-
├→ @
|
|
68
|
+
├→ @plan (Complex planning ≥3 phases)
|
|
69
69
|
├→ @review (Code review + security + debugging)
|
|
70
70
|
├→ @scout (External research, library docs, GitHub patterns)
|
|
71
71
|
├→ @explore (Fast codebase search)
|
|
@@ -175,7 +175,7 @@ Need speed over depth?
|
|
|
175
175
|
✓ → @rush (fast agent, same capabilities)
|
|
176
176
|
|
|
177
177
|
Complex task (≥3 phases)?
|
|
178
|
-
✓ → @
|
|
178
|
+
✓ → @plan (creates implementation plan)
|
|
179
179
|
|
|
180
180
|
Need research?
|
|
181
181
|
✓ → @scout (library docs + GitHub patterns)
|
package/dist/index.js
CHANGED
|
@@ -750,21 +750,24 @@ var cac = (name = "") => new CAC(name);
|
|
|
750
750
|
// package.json
|
|
751
751
|
var package_default = {
|
|
752
752
|
name: "opencodekit",
|
|
753
|
-
version: "0.
|
|
753
|
+
version: "0.15.1",
|
|
754
754
|
description: "CLI tool for bootstrapping and managing OpenCodeKit projects",
|
|
755
|
-
|
|
755
|
+
keywords: ["agents", "cli", "mcp", "opencode", "opencodekit", "template"],
|
|
756
|
+
license: "MIT",
|
|
757
|
+
author: "OpenCodeKit",
|
|
756
758
|
repository: {
|
|
757
759
|
type: "git",
|
|
758
760
|
url: "git+https://github.com/opencodekit/opencodekit-template.git"
|
|
759
761
|
},
|
|
760
|
-
publishConfig: {
|
|
761
|
-
access: "public",
|
|
762
|
-
registry: "https://registry.npmjs.org"
|
|
763
|
-
},
|
|
764
762
|
bin: {
|
|
765
763
|
ock: "dist/index.js"
|
|
766
764
|
},
|
|
767
765
|
files: ["dist", "README.md"],
|
|
766
|
+
type: "module",
|
|
767
|
+
publishConfig: {
|
|
768
|
+
access: "public",
|
|
769
|
+
registry: "https://registry.npmjs.org"
|
|
770
|
+
},
|
|
768
771
|
scripts: {
|
|
769
772
|
dev: "bun run src/index.ts",
|
|
770
773
|
build: "bun run build.ts && mkdir -p dist/template && rsync -av --exclude=node_modules --exclude=dist --exclude=.git --exclude=coverage --exclude=.next --exclude=.turbo --exclude=logs --exclude=package-lock.json .opencode/ dist/template/.opencode/",
|
|
@@ -773,14 +776,10 @@ var package_default = {
|
|
|
773
776
|
typecheck: "tsc --noEmit",
|
|
774
777
|
test: "bun test",
|
|
775
778
|
"test:watch": "bun test --watch",
|
|
776
|
-
lint: "
|
|
777
|
-
"lint:fix": "
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
author: "OpenCodeKit",
|
|
781
|
-
license: "MIT",
|
|
782
|
-
engines: {
|
|
783
|
-
bun: ">=1.3.2"
|
|
779
|
+
lint: "oxlint .",
|
|
780
|
+
"lint:fix": "oxlint --fix .",
|
|
781
|
+
format: "oxfmt",
|
|
782
|
+
"format:check": "oxfmt --check"
|
|
784
783
|
},
|
|
785
784
|
dependencies: {
|
|
786
785
|
"@clack/prompts": "^0.7.0",
|
|
@@ -792,7 +791,7 @@ var package_default = {
|
|
|
792
791
|
"cli-table3": "^0.6.5",
|
|
793
792
|
ora: "^9.0.0",
|
|
794
793
|
picocolors: "^1.1.1",
|
|
795
|
-
"solid-js": "
|
|
794
|
+
"solid-js": "1.9.9",
|
|
796
795
|
zod: "^3.25.76"
|
|
797
796
|
},
|
|
798
797
|
devDependencies: {
|
|
@@ -800,8 +799,13 @@ var package_default = {
|
|
|
800
799
|
"@biomejs/biome": "^1.9.4",
|
|
801
800
|
"@types/bun": "latest",
|
|
802
801
|
"@types/node": "^22.19.5",
|
|
802
|
+
oxfmt: "^0.23.0",
|
|
803
|
+
oxlint: "^1.38.0",
|
|
803
804
|
typescript: "^5.9.3"
|
|
804
805
|
},
|
|
806
|
+
engines: {
|
|
807
|
+
bun: ">=1.3.2"
|
|
808
|
+
},
|
|
805
809
|
trustedDependencies: ["@beads/bd"]
|
|
806
810
|
};
|
|
807
811
|
|
|
@@ -2762,7 +2766,7 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2762
2766
|
}
|
|
2763
2767
|
f2.success("Fetched models from models.dev");
|
|
2764
2768
|
const localProviders = config.provider || {};
|
|
2765
|
-
const
|
|
2769
|
+
const _configuredProviderIds = new Set(Object.keys(localProviders));
|
|
2766
2770
|
const allProviders = Object.values(modelsDevData);
|
|
2767
2771
|
const quickOptions = [];
|
|
2768
2772
|
quickOptions.push({
|
|
@@ -2929,7 +2933,7 @@ async function editAgentModel(configPath) {
|
|
|
2929
2933
|
config.agent = {};
|
|
2930
2934
|
}
|
|
2931
2935
|
const serverAgents = await getAgentsFromServer();
|
|
2932
|
-
const
|
|
2936
|
+
const _serverData = await getProvidersFromServer();
|
|
2933
2937
|
let agentNames = [];
|
|
2934
2938
|
const agentInfoMap = new Map;
|
|
2935
2939
|
if (serverAgents && serverAgents.length > 0) {
|
|
@@ -2943,7 +2947,7 @@ async function editAgentModel(configPath) {
|
|
|
2943
2947
|
});
|
|
2944
2948
|
}
|
|
2945
2949
|
} else {
|
|
2946
|
-
agentNames = Object.keys(config.agent)
|
|
2950
|
+
agentNames = Object.keys(config.agent);
|
|
2947
2951
|
for (const name of agentNames) {
|
|
2948
2952
|
const agent = config.agent[name];
|
|
2949
2953
|
agentInfoMap.set(name, {
|
|
@@ -3763,6 +3767,8 @@ import {
|
|
|
3763
3767
|
mkdirSync as mkdirSync3,
|
|
3764
3768
|
readFileSync as readFileSync4,
|
|
3765
3769
|
readdirSync as readdirSync3,
|
|
3770
|
+
renameSync,
|
|
3771
|
+
rmSync,
|
|
3766
3772
|
writeFileSync as writeFileSync4
|
|
3767
3773
|
} from "node:fs";
|
|
3768
3774
|
import { homedir, platform } from "node:os";
|
|
@@ -3849,6 +3855,139 @@ async function copyOpenCodeOnly(templateRoot, targetDir) {
|
|
|
3849
3855
|
await copyDir(opencodeSrc, opencodeDest);
|
|
3850
3856
|
return true;
|
|
3851
3857
|
}
|
|
3858
|
+
var MODEL_PRESETS = {
|
|
3859
|
+
free: {
|
|
3860
|
+
model: "opencode/minimax-m2.1-free",
|
|
3861
|
+
agents: {
|
|
3862
|
+
build: "opencode/minimax-m2.1-free",
|
|
3863
|
+
plan: "opencode/minimax-m2.1-free",
|
|
3864
|
+
review: "opencode/minimax-m2.1-free",
|
|
3865
|
+
explore: "opencode/grok-code",
|
|
3866
|
+
general: "opencode/glm-4.7-free",
|
|
3867
|
+
looker: "opencode/gpt-5-nano",
|
|
3868
|
+
vision: "opencode/gpt-5-nano",
|
|
3869
|
+
scout: "opencode/big-pickle"
|
|
3870
|
+
}
|
|
3871
|
+
},
|
|
3872
|
+
recommend: {
|
|
3873
|
+
model: "proxypal/gemini-claude-opus-4-5-thinking",
|
|
3874
|
+
agents: {
|
|
3875
|
+
build: "proxypal/gemini-claude-opus-4-5-thinking",
|
|
3876
|
+
plan: "proxypal/gemini-3-flash-preview",
|
|
3877
|
+
review: "proxypal/gemini-3-pro-preview",
|
|
3878
|
+
explore: "opencode/grok-code",
|
|
3879
|
+
general: "opencode/glm-4.7-free",
|
|
3880
|
+
looker: "proxypal/gemini-3-flash-preview",
|
|
3881
|
+
vision: "proxypal/gemini-3-pro-preview",
|
|
3882
|
+
scout: "proxypal/gemini-claude-sonnet-4-5"
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
};
|
|
3886
|
+
function applyModelPreset(targetDir, preset) {
|
|
3887
|
+
const configPath = join4(targetDir, ".opencode", "opencode.json");
|
|
3888
|
+
if (!existsSync4(configPath))
|
|
3889
|
+
return;
|
|
3890
|
+
const config = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
3891
|
+
const presetConfig = MODEL_PRESETS[preset];
|
|
3892
|
+
config.model = presetConfig.model;
|
|
3893
|
+
if (config.agent) {
|
|
3894
|
+
for (const [agentName, model] of Object.entries(presetConfig.agents)) {
|
|
3895
|
+
if (config.agent[agentName]) {
|
|
3896
|
+
config.agent[agentName].model = model;
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3900
|
+
writeFileSync4(configPath, JSON.stringify(config, null, 2));
|
|
3901
|
+
}
|
|
3902
|
+
var AGENT_DESCRIPTIONS = {
|
|
3903
|
+
build: "Main coding agent (complex tasks)",
|
|
3904
|
+
plan: "Planning and design agent",
|
|
3905
|
+
review: "Code review and debugging",
|
|
3906
|
+
explore: "Fast codebase search",
|
|
3907
|
+
general: "Quick, simple tasks",
|
|
3908
|
+
looker: "Image/PDF extraction (cheap)",
|
|
3909
|
+
vision: "Visual analysis (quality)",
|
|
3910
|
+
scout: "External research/docs",
|
|
3911
|
+
compaction: "Context summarization"
|
|
3912
|
+
};
|
|
3913
|
+
async function promptCustomModels(targetDir) {
|
|
3914
|
+
const configPath = join4(targetDir, ".opencode", "opencode.json");
|
|
3915
|
+
if (!existsSync4(configPath))
|
|
3916
|
+
return;
|
|
3917
|
+
const config = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
3918
|
+
f2.info(import_picocolors8.default.dim("Enter model IDs (e.g., opencode/grok-code, proxypal/gemini-3-pro-preview)"));
|
|
3919
|
+
f2.info(import_picocolors8.default.dim(`Press Enter to keep current value
|
|
3920
|
+
`));
|
|
3921
|
+
const mainModel = await te({
|
|
3922
|
+
message: "Main session model",
|
|
3923
|
+
placeholder: config.model || "opencode/minimax-m2.1-free",
|
|
3924
|
+
defaultValue: config.model
|
|
3925
|
+
});
|
|
3926
|
+
if (lD(mainModel)) {
|
|
3927
|
+
f2.warn("Cancelled - keeping defaults");
|
|
3928
|
+
return;
|
|
3929
|
+
}
|
|
3930
|
+
if (mainModel) {
|
|
3931
|
+
config.model = mainModel;
|
|
3932
|
+
}
|
|
3933
|
+
const agents = Object.keys(AGENT_DESCRIPTIONS);
|
|
3934
|
+
for (const agent of agents) {
|
|
3935
|
+
if (!config.agent?.[agent])
|
|
3936
|
+
continue;
|
|
3937
|
+
const currentModel = config.agent[agent].model || config.model;
|
|
3938
|
+
const agentModel = await te({
|
|
3939
|
+
message: `${agent} - ${AGENT_DESCRIPTIONS[agent]}`,
|
|
3940
|
+
placeholder: currentModel,
|
|
3941
|
+
defaultValue: currentModel
|
|
3942
|
+
});
|
|
3943
|
+
if (lD(agentModel)) {
|
|
3944
|
+
f2.warn("Cancelled - saving partial config");
|
|
3945
|
+
break;
|
|
3946
|
+
}
|
|
3947
|
+
if (agentModel) {
|
|
3948
|
+
config.agent[agent].model = agentModel;
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
writeFileSync4(configPath, JSON.stringify(config, null, 2));
|
|
3952
|
+
}
|
|
3953
|
+
function getAffectedFiles(dir, prefix = "") {
|
|
3954
|
+
if (!existsSync4(dir))
|
|
3955
|
+
return [];
|
|
3956
|
+
const files = [];
|
|
3957
|
+
for (const entry of readdirSync3(dir, { withFileTypes: true })) {
|
|
3958
|
+
if (EXCLUDED_DIRS.includes(entry.name))
|
|
3959
|
+
continue;
|
|
3960
|
+
const path = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
3961
|
+
if (entry.isDirectory()) {
|
|
3962
|
+
files.push(...getAffectedFiles(join4(dir, entry.name), path));
|
|
3963
|
+
} else {
|
|
3964
|
+
files.push(path);
|
|
3965
|
+
}
|
|
3966
|
+
}
|
|
3967
|
+
return files;
|
|
3968
|
+
}
|
|
3969
|
+
function backupOpenCode(targetDir) {
|
|
3970
|
+
const opencodeDir = join4(targetDir, ".opencode");
|
|
3971
|
+
if (!existsSync4(opencodeDir))
|
|
3972
|
+
return null;
|
|
3973
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
3974
|
+
const backupDir = join4(targetDir, `.opencode.bak-${timestamp}`);
|
|
3975
|
+
renameSync(opencodeDir, backupDir);
|
|
3976
|
+
return backupDir;
|
|
3977
|
+
}
|
|
3978
|
+
function getTemplateFiles(templateRoot) {
|
|
3979
|
+
const opencodeSrc = join4(templateRoot, ".opencode");
|
|
3980
|
+
if (!existsSync4(opencodeSrc))
|
|
3981
|
+
return new Set;
|
|
3982
|
+
return new Set(getAffectedFiles(opencodeSrc));
|
|
3983
|
+
}
|
|
3984
|
+
function findOrphans(targetDir, templateFiles) {
|
|
3985
|
+
const opencodeDir = join4(targetDir, ".opencode");
|
|
3986
|
+
if (!existsSync4(opencodeDir))
|
|
3987
|
+
return [];
|
|
3988
|
+
const existingFiles = getAffectedFiles(opencodeDir);
|
|
3989
|
+
return existingFiles.filter((f3) => !templateFiles.has(f3));
|
|
3990
|
+
}
|
|
3852
3991
|
async function initCommand(options = {}) {
|
|
3853
3992
|
if (process.argv.includes("--quiet"))
|
|
3854
3993
|
return;
|
|
@@ -3898,6 +4037,47 @@ for all OpenCode projects on this machine.`, "Global Installation Complete");
|
|
|
3898
4037
|
$e("Nothing to do");
|
|
3899
4038
|
return;
|
|
3900
4039
|
}
|
|
4040
|
+
if (mode === "already-initialized" && options.force) {
|
|
4041
|
+
const opencodeDir2 = join4(targetDir, ".opencode");
|
|
4042
|
+
const affected = getAffectedFiles(opencodeDir2);
|
|
4043
|
+
if (affected.length > 0 && !options.yes) {
|
|
4044
|
+
f2.warn(`${affected.length} files will be overwritten:`);
|
|
4045
|
+
const preview = affected.slice(0, 10);
|
|
4046
|
+
for (const file of preview) {
|
|
4047
|
+
f2.info(import_picocolors8.default.dim(` .opencode/${file}`));
|
|
4048
|
+
}
|
|
4049
|
+
if (affected.length > 10) {
|
|
4050
|
+
f2.info(import_picocolors8.default.dim(` ... and ${affected.length - 10} more`));
|
|
4051
|
+
}
|
|
4052
|
+
if (!options.backup) {
|
|
4053
|
+
const shouldBackup = await se({
|
|
4054
|
+
message: "Backup existing .opencode before overwriting?",
|
|
4055
|
+
initialValue: true
|
|
4056
|
+
});
|
|
4057
|
+
if (lD(shouldBackup)) {
|
|
4058
|
+
ue("Cancelled");
|
|
4059
|
+
process.exit(0);
|
|
4060
|
+
}
|
|
4061
|
+
if (shouldBackup) {
|
|
4062
|
+
options.backup = true;
|
|
4063
|
+
}
|
|
4064
|
+
}
|
|
4065
|
+
const proceed = await se({
|
|
4066
|
+
message: options.backup ? "Proceed? (existing config will be backed up)" : "Proceed without backup?",
|
|
4067
|
+
initialValue: options.backup
|
|
4068
|
+
});
|
|
4069
|
+
if (lD(proceed) || !proceed) {
|
|
4070
|
+
ue("Cancelled");
|
|
4071
|
+
process.exit(0);
|
|
4072
|
+
}
|
|
4073
|
+
}
|
|
4074
|
+
if (options.backup) {
|
|
4075
|
+
const backupPath = backupOpenCode(targetDir);
|
|
4076
|
+
if (backupPath) {
|
|
4077
|
+
f2.info(`Backed up to ${import_picocolors8.default.cyan(basename2(backupPath))}`);
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
3901
4081
|
const templateRoot = getTemplateRoot();
|
|
3902
4082
|
if (!templateRoot) {
|
|
3903
4083
|
f2.error("Template not found. Please reinstall opencodekit.");
|
|
@@ -3933,6 +4113,51 @@ for all OpenCode projects on this machine.`, "Global Installation Complete");
|
|
|
3933
4113
|
process.exit(1);
|
|
3934
4114
|
}
|
|
3935
4115
|
s.stop("Done");
|
|
4116
|
+
if (options.free) {
|
|
4117
|
+
applyModelPreset(targetDir, "free");
|
|
4118
|
+
f2.info("Applied free model preset");
|
|
4119
|
+
} else if (options.recommend) {
|
|
4120
|
+
applyModelPreset(targetDir, "recommend");
|
|
4121
|
+
f2.info("Applied recommended model preset");
|
|
4122
|
+
} else if (options.yes) {
|
|
4123
|
+
applyModelPreset(targetDir, "free");
|
|
4124
|
+
f2.info("Applied free model preset (default)");
|
|
4125
|
+
} else {
|
|
4126
|
+
const preset = await ie({
|
|
4127
|
+
message: "Choose model preset",
|
|
4128
|
+
options: [
|
|
4129
|
+
{
|
|
4130
|
+
value: "free",
|
|
4131
|
+
label: "Free models",
|
|
4132
|
+
hint: "minimax, glm, grok (no API costs)"
|
|
4133
|
+
},
|
|
4134
|
+
{
|
|
4135
|
+
value: "recommend",
|
|
4136
|
+
label: "Recommended models",
|
|
4137
|
+
hint: "claude-opus, gemini-pro (best quality)"
|
|
4138
|
+
},
|
|
4139
|
+
{
|
|
4140
|
+
value: "custom",
|
|
4141
|
+
label: "Custom",
|
|
4142
|
+
hint: "configure each agent individually"
|
|
4143
|
+
},
|
|
4144
|
+
{
|
|
4145
|
+
value: "skip",
|
|
4146
|
+
label: "Skip",
|
|
4147
|
+
hint: "keep template defaults"
|
|
4148
|
+
}
|
|
4149
|
+
]
|
|
4150
|
+
});
|
|
4151
|
+
if (!lD(preset)) {
|
|
4152
|
+
if (preset === "custom") {
|
|
4153
|
+
await promptCustomModels(targetDir);
|
|
4154
|
+
f2.info("Applied custom model configuration");
|
|
4155
|
+
} else if (preset !== "skip") {
|
|
4156
|
+
applyModelPreset(targetDir, preset);
|
|
4157
|
+
f2.info(`Applied ${preset} model preset`);
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
3936
4161
|
if (options.beads) {
|
|
3937
4162
|
const beadsDir = join4(targetDir, ".beads");
|
|
3938
4163
|
if (!existsSync4(beadsDir)) {
|
|
@@ -3954,7 +4179,94 @@ version: 1
|
|
|
3954
4179
|
f2.info(".beads/ already exists");
|
|
3955
4180
|
}
|
|
3956
4181
|
}
|
|
3957
|
-
|
|
4182
|
+
const opencodeDir = join4(targetDir, ".opencode");
|
|
4183
|
+
if (existsSync4(join4(opencodeDir, "package.json"))) {
|
|
4184
|
+
const installSpinner = de();
|
|
4185
|
+
installSpinner.start("Installing dependencies");
|
|
4186
|
+
try {
|
|
4187
|
+
execSync("bun install", { cwd: opencodeDir, stdio: "ignore" });
|
|
4188
|
+
installSpinner.stop("Dependencies installed");
|
|
4189
|
+
} catch {
|
|
4190
|
+
installSpinner.stop("Failed to install (run manually: cd .opencode && bun install)");
|
|
4191
|
+
}
|
|
4192
|
+
}
|
|
4193
|
+
if (mode === "already-initialized" && options.force && !options.backup) {
|
|
4194
|
+
const templateFiles = getTemplateFiles(templateRoot);
|
|
4195
|
+
const orphans = findOrphans(targetDir, templateFiles);
|
|
4196
|
+
if (orphans.length > 0) {
|
|
4197
|
+
f2.warn(`Found ${orphans.length} orphan files not in template`);
|
|
4198
|
+
if (options.pruneAll) {
|
|
4199
|
+
const pruneSpinner = de();
|
|
4200
|
+
pruneSpinner.start("Removing orphan files");
|
|
4201
|
+
for (const orphan of orphans) {
|
|
4202
|
+
rmSync(join4(opencodeDir, orphan));
|
|
4203
|
+
}
|
|
4204
|
+
pruneSpinner.stop(`Removed ${orphans.length} orphan files`);
|
|
4205
|
+
} else if (options.prune) {
|
|
4206
|
+
const selected = await ae({
|
|
4207
|
+
message: "Select orphan files to delete",
|
|
4208
|
+
options: orphans.map((o2) => ({ value: o2, label: o2 })),
|
|
4209
|
+
required: false
|
|
4210
|
+
});
|
|
4211
|
+
if (!lD(selected) && selected.length > 0) {
|
|
4212
|
+
const pruneSpinner = de();
|
|
4213
|
+
pruneSpinner.start("Deleting files");
|
|
4214
|
+
for (const file of selected) {
|
|
4215
|
+
rmSync(join4(opencodeDir, file));
|
|
4216
|
+
}
|
|
4217
|
+
pruneSpinner.stop(`Deleted ${selected.length} files`);
|
|
4218
|
+
}
|
|
4219
|
+
} else if (!options.yes) {
|
|
4220
|
+
const preview = orphans.slice(0, 5);
|
|
4221
|
+
for (const file of preview) {
|
|
4222
|
+
f2.info(import_picocolors8.default.dim(` .opencode/${file}`));
|
|
4223
|
+
}
|
|
4224
|
+
if (orphans.length > 5) {
|
|
4225
|
+
f2.info(import_picocolors8.default.dim(` ... and ${orphans.length - 5} more`));
|
|
4226
|
+
}
|
|
4227
|
+
const orphanAction = await ie({
|
|
4228
|
+
message: "How to handle orphan files?",
|
|
4229
|
+
options: [
|
|
4230
|
+
{ value: "keep", label: "Keep all", hint: "leave orphan files" },
|
|
4231
|
+
{
|
|
4232
|
+
value: "select",
|
|
4233
|
+
label: "Select",
|
|
4234
|
+
hint: "choose which to delete"
|
|
4235
|
+
},
|
|
4236
|
+
{
|
|
4237
|
+
value: "delete",
|
|
4238
|
+
label: "Delete all",
|
|
4239
|
+
hint: "remove all orphans"
|
|
4240
|
+
}
|
|
4241
|
+
]
|
|
4242
|
+
});
|
|
4243
|
+
if (!lD(orphanAction)) {
|
|
4244
|
+
if (orphanAction === "delete") {
|
|
4245
|
+
const pruneSpinner = de();
|
|
4246
|
+
pruneSpinner.start("Removing orphan files");
|
|
4247
|
+
for (const orphan of orphans) {
|
|
4248
|
+
rmSync(join4(opencodeDir, orphan));
|
|
4249
|
+
}
|
|
4250
|
+
pruneSpinner.stop(`Removed ${orphans.length} orphan files`);
|
|
4251
|
+
} else if (orphanAction === "select") {
|
|
4252
|
+
const selected = await ae({
|
|
4253
|
+
message: "Select orphan files to delete",
|
|
4254
|
+
options: orphans.map((o2) => ({ value: o2, label: o2 })),
|
|
4255
|
+
required: false
|
|
4256
|
+
});
|
|
4257
|
+
if (!lD(selected) && selected.length > 0) {
|
|
4258
|
+
const pruneSpinner = de();
|
|
4259
|
+
pruneSpinner.start("Deleting files");
|
|
4260
|
+
for (const file of selected) {
|
|
4261
|
+
rmSync(join4(opencodeDir, file));
|
|
4262
|
+
}
|
|
4263
|
+
pruneSpinner.stop(`Deleted ${selected.length} files`);
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
3958
4270
|
$e(import_picocolors8.default.green("Ready to code!"));
|
|
3959
4271
|
}
|
|
3960
4272
|
|
|
@@ -3964,14 +4276,7 @@ import { basename as basename4, join as join7 } from "node:path";
|
|
|
3964
4276
|
var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
3965
4277
|
|
|
3966
4278
|
// src/commands/skill.ts
|
|
3967
|
-
import {
|
|
3968
|
-
existsSync as existsSync5,
|
|
3969
|
-
mkdirSync as mkdirSync4,
|
|
3970
|
-
readFileSync as readFileSync5,
|
|
3971
|
-
readdirSync as readdirSync4,
|
|
3972
|
-
rmSync,
|
|
3973
|
-
writeFileSync as writeFileSync5
|
|
3974
|
-
} from "node:fs";
|
|
4279
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync5, readdirSync as readdirSync4, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
3975
4280
|
import { basename as basename3, join as join5 } from "node:path";
|
|
3976
4281
|
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
3977
4282
|
async function skillCommand(action) {
|
|
@@ -4253,7 +4558,7 @@ async function removeSkill(skillDir, skillNameArg) {
|
|
|
4253
4558
|
ue("Cancelled");
|
|
4254
4559
|
return;
|
|
4255
4560
|
}
|
|
4256
|
-
|
|
4561
|
+
rmSync2(skill.path, { recursive: true, force: true });
|
|
4257
4562
|
f2.success(`Removed skill "${skill.name}"`);
|
|
4258
4563
|
}
|
|
4259
4564
|
|
|
@@ -4264,7 +4569,7 @@ import {
|
|
|
4264
4569
|
mkdirSync as mkdirSync5,
|
|
4265
4570
|
readFileSync as readFileSync6,
|
|
4266
4571
|
readdirSync as readdirSync5,
|
|
4267
|
-
rmSync as
|
|
4572
|
+
rmSync as rmSync3,
|
|
4268
4573
|
writeFileSync as writeFileSync6
|
|
4269
4574
|
} from "node:fs";
|
|
4270
4575
|
import { dirname as dirname2, join as join6 } from "node:path";
|
|
@@ -4478,36 +4783,42 @@ async function upgradeCommand(options = {}) {
|
|
|
4478
4783
|
});
|
|
4479
4784
|
if (orphans.length > 0) {
|
|
4480
4785
|
f2.info(`${import_picocolors10.default.yellow(orphans.length.toString())} files found that are not in the template (orphans).`);
|
|
4481
|
-
if (options.
|
|
4786
|
+
if (options.pruneAll) {
|
|
4482
4787
|
const s2 = de();
|
|
4483
4788
|
s2.start("Pruning orphans");
|
|
4484
4789
|
for (const orphan of orphans) {
|
|
4485
|
-
|
|
4790
|
+
rmSync3(join6(opencodeDir, orphan));
|
|
4486
4791
|
}
|
|
4487
4792
|
s2.stop(`Removed ${orphans.length} files`);
|
|
4488
|
-
} else {
|
|
4489
|
-
const
|
|
4490
|
-
message: "
|
|
4491
|
-
|
|
4793
|
+
} else if (options.prune) {
|
|
4794
|
+
const selected = await ae({
|
|
4795
|
+
message: "Select files to delete",
|
|
4796
|
+
options: orphans.map((o2) => ({ value: o2, label: o2 })),
|
|
4797
|
+
required: false
|
|
4492
4798
|
});
|
|
4493
|
-
if (!lD(
|
|
4494
|
-
const
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
});
|
|
4499
|
-
if (!lD(selected) && selected.length > 0) {
|
|
4500
|
-
const s2 = de();
|
|
4501
|
-
s2.start("Deleting files");
|
|
4502
|
-
for (const file of selected) {
|
|
4503
|
-
rmSync2(join6(opencodeDir, file));
|
|
4504
|
-
}
|
|
4505
|
-
s2.stop(`Deleted ${selected.length} files`);
|
|
4799
|
+
if (!lD(selected) && selected.length > 0) {
|
|
4800
|
+
const s2 = de();
|
|
4801
|
+
s2.start("Deleting files");
|
|
4802
|
+
for (const file of selected) {
|
|
4803
|
+
rmSync3(join6(opencodeDir, file));
|
|
4506
4804
|
}
|
|
4805
|
+
s2.stop(`Deleted ${selected.length} files`);
|
|
4507
4806
|
}
|
|
4807
|
+
} else {
|
|
4808
|
+
f2.info(`Run with ${import_picocolors10.default.cyan("--prune")} to select files or ${import_picocolors10.default.cyan("--prune-all")} to delete all`);
|
|
4809
|
+
}
|
|
4810
|
+
}
|
|
4811
|
+
if (existsSync6(join6(opencodeDir, "package.json"))) {
|
|
4812
|
+
const installSpinner = de();
|
|
4813
|
+
installSpinner.start("Installing dependencies");
|
|
4814
|
+
try {
|
|
4815
|
+
const { execSync: execSync2 } = await import("node:child_process");
|
|
4816
|
+
execSync2("bun install", { cwd: opencodeDir, stdio: "ignore" });
|
|
4817
|
+
installSpinner.stop("Dependencies installed");
|
|
4818
|
+
} catch {
|
|
4819
|
+
installSpinner.stop("Failed to install (run manually: cd .opencode && bun install)");
|
|
4508
4820
|
}
|
|
4509
4821
|
}
|
|
4510
|
-
le("cd .opencode && bun install", "Run if dependencies changed");
|
|
4511
4822
|
$e(import_picocolors10.default.green(`Upgraded to ${versionInfo.latest}`));
|
|
4512
4823
|
}
|
|
4513
4824
|
|
|
@@ -4677,7 +4988,7 @@ async function doctorCommand() {
|
|
|
4677
4988
|
}
|
|
4678
4989
|
checks.push(...configChecks);
|
|
4679
4990
|
displayChecks(configChecks);
|
|
4680
|
-
} catch
|
|
4991
|
+
} catch {
|
|
4681
4992
|
checks.push({
|
|
4682
4993
|
name: "Valid JSON syntax",
|
|
4683
4994
|
ok: false,
|
|
@@ -4964,7 +5275,6 @@ async function runBrowser(options) {
|
|
|
4964
5275
|
items,
|
|
4965
5276
|
icon = "●",
|
|
4966
5277
|
color: itemColor = import_picocolors12.default.cyan,
|
|
4967
|
-
onSelect,
|
|
4968
5278
|
onBack
|
|
4969
5279
|
} = options;
|
|
4970
5280
|
if (items.length === 0) {
|
|
@@ -5155,7 +5465,24 @@ function padRight2(str, len) {
|
|
|
5155
5465
|
return str + " ".repeat(pad);
|
|
5156
5466
|
}
|
|
5157
5467
|
function stripAnsi(str) {
|
|
5158
|
-
|
|
5468
|
+
const esc = "\x1B";
|
|
5469
|
+
let result = "";
|
|
5470
|
+
let index = 0;
|
|
5471
|
+
while (index < str.length) {
|
|
5472
|
+
const start = str.indexOf(esc, index);
|
|
5473
|
+
if (start === -1) {
|
|
5474
|
+
result += str.slice(index);
|
|
5475
|
+
break;
|
|
5476
|
+
}
|
|
5477
|
+
result += str.slice(index, start);
|
|
5478
|
+
const end = str.indexOf("m", start);
|
|
5479
|
+
if (end === -1) {
|
|
5480
|
+
index = start + 1;
|
|
5481
|
+
continue;
|
|
5482
|
+
}
|
|
5483
|
+
index = end + 1;
|
|
5484
|
+
}
|
|
5485
|
+
return result;
|
|
5159
5486
|
}
|
|
5160
5487
|
async function showFileViewer(item) {
|
|
5161
5488
|
if (!existsSync8(item.path)) {
|
|
@@ -5570,7 +5897,24 @@ function padRight3(str, len) {
|
|
|
5570
5897
|
return str + " ".repeat(pad);
|
|
5571
5898
|
}
|
|
5572
5899
|
function stripAnsi2(str) {
|
|
5573
|
-
|
|
5900
|
+
const esc = "\x1B";
|
|
5901
|
+
let result = "";
|
|
5902
|
+
let index = 0;
|
|
5903
|
+
while (index < str.length) {
|
|
5904
|
+
const start = str.indexOf(esc, index);
|
|
5905
|
+
if (start === -1) {
|
|
5906
|
+
result += str.slice(index);
|
|
5907
|
+
break;
|
|
5908
|
+
}
|
|
5909
|
+
result += str.slice(index, start);
|
|
5910
|
+
const end = str.indexOf("m", start);
|
|
5911
|
+
if (end === -1) {
|
|
5912
|
+
index = start + 1;
|
|
5913
|
+
continue;
|
|
5914
|
+
}
|
|
5915
|
+
index = end + 1;
|
|
5916
|
+
}
|
|
5917
|
+
return result;
|
|
5574
5918
|
}
|
|
5575
5919
|
|
|
5576
5920
|
// src/tui/components/Dashboard.tsx
|
|
@@ -5685,7 +6029,24 @@ function padRight4(str, len) {
|
|
|
5685
6029
|
return str + " ".repeat(pad);
|
|
5686
6030
|
}
|
|
5687
6031
|
function stripAnsi3(str) {
|
|
5688
|
-
|
|
6032
|
+
const esc = "\x1B";
|
|
6033
|
+
let result = "";
|
|
6034
|
+
let index = 0;
|
|
6035
|
+
while (index < str.length) {
|
|
6036
|
+
const start = str.indexOf(esc, index);
|
|
6037
|
+
if (start === -1) {
|
|
6038
|
+
result += str.slice(index);
|
|
6039
|
+
break;
|
|
6040
|
+
}
|
|
6041
|
+
result += str.slice(index, start);
|
|
6042
|
+
const end = str.indexOf("m", start);
|
|
6043
|
+
if (end === -1) {
|
|
6044
|
+
index = start + 1;
|
|
6045
|
+
continue;
|
|
6046
|
+
}
|
|
6047
|
+
index = end + 1;
|
|
6048
|
+
}
|
|
6049
|
+
return result;
|
|
5689
6050
|
}
|
|
5690
6051
|
|
|
5691
6052
|
// src/tui/components/MCPMonitor.ts
|
|
@@ -5869,7 +6230,24 @@ function padRight5(str, len) {
|
|
|
5869
6230
|
return str + " ".repeat(pad);
|
|
5870
6231
|
}
|
|
5871
6232
|
function stripAnsi4(str) {
|
|
5872
|
-
|
|
6233
|
+
const esc = "\x1B";
|
|
6234
|
+
let result = "";
|
|
6235
|
+
let index = 0;
|
|
6236
|
+
while (index < str.length) {
|
|
6237
|
+
const start = str.indexOf(esc, index);
|
|
6238
|
+
if (start === -1) {
|
|
6239
|
+
result += str.slice(index);
|
|
6240
|
+
break;
|
|
6241
|
+
}
|
|
6242
|
+
result += str.slice(index, start);
|
|
6243
|
+
const end = str.indexOf("m", start);
|
|
6244
|
+
if (end === -1) {
|
|
6245
|
+
index = start + 1;
|
|
6246
|
+
continue;
|
|
6247
|
+
}
|
|
6248
|
+
index = end + 1;
|
|
6249
|
+
}
|
|
6250
|
+
return result;
|
|
5873
6251
|
}
|
|
5874
6252
|
|
|
5875
6253
|
// src/tui/hooks/useData.ts
|
|
@@ -6045,7 +6423,7 @@ var cli = cac("ock");
|
|
|
6045
6423
|
cli.option("--verbose", "Enable verbose logging");
|
|
6046
6424
|
cli.option("--quiet", "Suppress all output");
|
|
6047
6425
|
cli.version(`${packageVersion}`);
|
|
6048
|
-
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/)").action(initCommand);
|
|
6426
|
+
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);
|
|
6049
6427
|
cli.command("agent [action]", "Manage agents (list, add, view)").action(async (action) => {
|
|
6050
6428
|
if (!action) {
|
|
6051
6429
|
console.log(`
|
|
@@ -6095,7 +6473,7 @@ cli.command("status", "Show project overview").action(statusCommand);
|
|
|
6095
6473
|
cli.command("config [action]", "Edit opencode.json (model, mcp, permission, validate, show)").action(async (action) => {
|
|
6096
6474
|
await configCommand(action);
|
|
6097
6475
|
});
|
|
6098
|
-
cli.command("upgrade", "Update .opencode/ templates to latest version").option("--force", "Force upgrade even if already up to date").option("--check", "Check for updates without upgrading").action(async (options) => {
|
|
6476
|
+
cli.command("upgrade", "Update .opencode/ templates to latest version").option("--force", "Force upgrade even if already up to date").option("--check", "Check for updates without upgrading").option("--prune", "Manually select orphan files to delete").option("--prune-all", "Auto-delete all orphan files").action(async (options) => {
|
|
6099
6477
|
await upgradeCommand(options);
|
|
6100
6478
|
});
|
|
6101
6479
|
cli.command("completion [shell]", "Generate shell completion script (bash, zsh, fish)").action(async (shell) => {
|