opencodekit 0.15.0 → 0.15.2
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 +367 -31
- package/dist/template/.opencode/README.md +1 -1
- package/dist/template/.opencode/agent/vision.md +4 -4
- package/dist/template/.opencode/command/agent-browser.md +21 -0
- package/dist/template/.opencode/command/complete-next-task.md +77 -0
- package/dist/template/.opencode/command/create.md +38 -3
- package/dist/template/.opencode/command/design-audit.md +1 -1
- package/dist/template/.opencode/command/design.md +1 -1
- package/dist/template/.opencode/command/finish.md +8 -0
- package/dist/template/.opencode/command/frontend-design.md +21 -0
- package/dist/template/.opencode/command/index-knowledge.md +25 -0
- package/dist/template/.opencode/command/init.md +6 -0
- package/dist/template/.opencode/command/opensrc.md +58 -0
- package/dist/template/.opencode/command/skill-create.md +3 -3
- package/dist/template/.opencode/command/skill-optimize.md +2 -2
- package/dist/template/.opencode/command/start.md +15 -6
- package/dist/template/.opencode/command/ui-review.md +1 -1
- package/dist/template/.opencode/memory/_templates/prd.md +50 -14
- package/dist/template/.opencode/opencode.json +143 -159
- package/dist/template/.opencode/package.json +1 -1
- package/dist/template/.opencode/skill/accessibility-audit/SKILL.md +1 -1
- package/dist/template/.opencode/skill/agent-browser/SKILL.md +376 -0
- package/dist/template/.opencode/skill/design-system-audit/SKILL.md +1 -1
- package/dist/template/.opencode/skill/frontend-design/SKILL.md +155 -0
- package/dist/template/.opencode/skill/frontend-design/references/animation/motion-advanced.md +224 -0
- package/dist/template/.opencode/skill/frontend-design/references/animation/motion-core.md +171 -0
- package/dist/template/.opencode/skill/frontend-design/references/canvas/execution.md +90 -0
- package/dist/template/.opencode/skill/frontend-design/references/canvas/philosophy.md +94 -0
- package/dist/template/.opencode/skill/frontend-design/references/shadcn/accessibility.md +132 -0
- package/dist/template/.opencode/skill/frontend-design/references/shadcn/core-components.md +153 -0
- package/dist/template/.opencode/skill/frontend-design/references/shadcn/form-components.md +158 -0
- package/dist/template/.opencode/skill/frontend-design/references/shadcn/setup.md +69 -0
- package/dist/template/.opencode/skill/frontend-design/references/shadcn/theming.md +152 -0
- package/dist/template/.opencode/skill/frontend-design/references/tailwind/responsive.md +112 -0
- package/dist/template/.opencode/skill/frontend-design/references/tailwind/utilities-layout.md +134 -0
- package/dist/template/.opencode/skill/frontend-design/references/tailwind/utilities-styling.md +165 -0
- package/dist/template/.opencode/skill/frontend-design/references/tailwind/v4-config.md +147 -0
- package/dist/template/.opencode/skill/frontend-design/references/tailwind/v4-features.md +128 -0
- package/dist/template/.opencode/skill/index-knowledge/SKILL.md +358 -0
- package/dist/template/.opencode/skill/mockup-to-code/SKILL.md +1 -1
- package/dist/template/.opencode/skill/opensrc/SKILL.md +115 -0
- package/dist/template/.opencode/skill/opensrc/references/architecture.md +176 -0
- package/dist/template/.opencode/skill/opensrc/references/cli-usage.md +176 -0
- package/dist/template/.opencode/skill/opensrc/references/registry-support.md +137 -0
- package/dist/template/.opencode/skill/prd/SKILL.md +212 -0
- package/dist/template/.opencode/skill/prd-task/SKILL.md +128 -0
- package/dist/template/.opencode/skill/prd-task/references/prd-schema.json +28 -0
- package/dist/template/.opencode/skill/skill-creator/SKILL.md +155 -0
- package/dist/template/.opencode/skill/ui-ux-research/SKILL.md +1 -1
- package/dist/template/.opencode/skill/visual-analysis/SKILL.md +1 -1
- package/package.json +1 -1
- package/dist/template/.opencode/skill/frontend-aesthetics/SKILL.md +0 -117
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.2",
|
|
754
754
|
description: "CLI tool for bootstrapping and managing OpenCodeKit projects",
|
|
755
755
|
keywords: ["agents", "cli", "mcp", "opencode", "opencodekit", "template"],
|
|
756
756
|
license: "MIT",
|
|
@@ -3762,13 +3762,34 @@ async function editAutoupdate(configPath) {
|
|
|
3762
3762
|
|
|
3763
3763
|
// src/commands/init.ts
|
|
3764
3764
|
import { execSync } from "node:child_process";
|
|
3765
|
-
import {
|
|
3765
|
+
import {
|
|
3766
|
+
existsSync as existsSync4,
|
|
3767
|
+
mkdirSync as mkdirSync3,
|
|
3768
|
+
readFileSync as readFileSync4,
|
|
3769
|
+
readdirSync as readdirSync3,
|
|
3770
|
+
renameSync,
|
|
3771
|
+
rmSync,
|
|
3772
|
+
writeFileSync as writeFileSync4
|
|
3773
|
+
} from "node:fs";
|
|
3766
3774
|
import { homedir, platform } from "node:os";
|
|
3767
3775
|
import { basename as basename2, dirname, join as join4 } from "node:path";
|
|
3768
3776
|
import { fileURLToPath } from "node:url";
|
|
3769
3777
|
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
3770
|
-
var EXCLUDED_DIRS = [
|
|
3771
|
-
|
|
3778
|
+
var EXCLUDED_DIRS = [
|
|
3779
|
+
"node_modules",
|
|
3780
|
+
".git",
|
|
3781
|
+
"dist",
|
|
3782
|
+
".DS_Store",
|
|
3783
|
+
"coverage",
|
|
3784
|
+
".next",
|
|
3785
|
+
".turbo"
|
|
3786
|
+
];
|
|
3787
|
+
var EXCLUDED_FILES = [
|
|
3788
|
+
"bun.lock",
|
|
3789
|
+
"package-lock.json",
|
|
3790
|
+
"yarn.lock",
|
|
3791
|
+
"pnpm-lock.yaml"
|
|
3792
|
+
];
|
|
3772
3793
|
function getGlobalConfigDir() {
|
|
3773
3794
|
const os = platform();
|
|
3774
3795
|
if (os === "win32") {
|
|
@@ -3795,7 +3816,10 @@ function detectMode(targetDir) {
|
|
|
3795
3816
|
function getTemplateRoot() {
|
|
3796
3817
|
const __filename2 = fileURLToPath(import.meta.url);
|
|
3797
3818
|
const __dirname2 = dirname(__filename2);
|
|
3798
|
-
const possiblePaths = [
|
|
3819
|
+
const possiblePaths = [
|
|
3820
|
+
join4(__dirname2, "template"),
|
|
3821
|
+
join4(__dirname2, "..", "..", ".opencode")
|
|
3822
|
+
];
|
|
3799
3823
|
for (const path of possiblePaths) {
|
|
3800
3824
|
const opencodeDir = join4(path, ".opencode");
|
|
3801
3825
|
if (existsSync4(opencodeDir)) {
|
|
@@ -3831,6 +3855,139 @@ async function copyOpenCodeOnly(templateRoot, targetDir) {
|
|
|
3831
3855
|
await copyDir(opencodeSrc, opencodeDest);
|
|
3832
3856
|
return true;
|
|
3833
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
|
+
}
|
|
3834
3991
|
async function initCommand(options = {}) {
|
|
3835
3992
|
if (process.argv.includes("--quiet"))
|
|
3836
3993
|
return;
|
|
@@ -3880,6 +4037,47 @@ for all OpenCode projects on this machine.`, "Global Installation Complete");
|
|
|
3880
4037
|
$e("Nothing to do");
|
|
3881
4038
|
return;
|
|
3882
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
|
+
}
|
|
3883
4081
|
const templateRoot = getTemplateRoot();
|
|
3884
4082
|
if (!templateRoot) {
|
|
3885
4083
|
f2.error("Template not found. Please reinstall opencodekit.");
|
|
@@ -3915,6 +4113,51 @@ for all OpenCode projects on this machine.`, "Global Installation Complete");
|
|
|
3915
4113
|
process.exit(1);
|
|
3916
4114
|
}
|
|
3917
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
|
+
}
|
|
3918
4161
|
if (options.beads) {
|
|
3919
4162
|
const beadsDir = join4(targetDir, ".beads");
|
|
3920
4163
|
if (!existsSync4(beadsDir)) {
|
|
@@ -3936,7 +4179,94 @@ version: 1
|
|
|
3936
4179
|
f2.info(".beads/ already exists");
|
|
3937
4180
|
}
|
|
3938
4181
|
}
|
|
3939
|
-
|
|
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
|
+
}
|
|
3940
4270
|
$e(import_picocolors8.default.green("Ready to code!"));
|
|
3941
4271
|
}
|
|
3942
4272
|
|
|
@@ -3946,7 +4276,7 @@ import { basename as basename4, join as join7 } from "node:path";
|
|
|
3946
4276
|
var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
3947
4277
|
|
|
3948
4278
|
// src/commands/skill.ts
|
|
3949
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync5, readdirSync as readdirSync4, rmSync, writeFileSync as writeFileSync5 } 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";
|
|
3950
4280
|
import { basename as basename3, join as join5 } from "node:path";
|
|
3951
4281
|
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
3952
4282
|
async function skillCommand(action) {
|
|
@@ -4228,7 +4558,7 @@ async function removeSkill(skillDir, skillNameArg) {
|
|
|
4228
4558
|
ue("Cancelled");
|
|
4229
4559
|
return;
|
|
4230
4560
|
}
|
|
4231
|
-
|
|
4561
|
+
rmSync2(skill.path, { recursive: true, force: true });
|
|
4232
4562
|
f2.success(`Removed skill "${skill.name}"`);
|
|
4233
4563
|
}
|
|
4234
4564
|
|
|
@@ -4239,7 +4569,7 @@ import {
|
|
|
4239
4569
|
mkdirSync as mkdirSync5,
|
|
4240
4570
|
readFileSync as readFileSync6,
|
|
4241
4571
|
readdirSync as readdirSync5,
|
|
4242
|
-
rmSync as
|
|
4572
|
+
rmSync as rmSync3,
|
|
4243
4573
|
writeFileSync as writeFileSync6
|
|
4244
4574
|
} from "node:fs";
|
|
4245
4575
|
import { dirname as dirname2, join as join6 } from "node:path";
|
|
@@ -4453,36 +4783,42 @@ async function upgradeCommand(options = {}) {
|
|
|
4453
4783
|
});
|
|
4454
4784
|
if (orphans.length > 0) {
|
|
4455
4785
|
f2.info(`${import_picocolors10.default.yellow(orphans.length.toString())} files found that are not in the template (orphans).`);
|
|
4456
|
-
if (options.
|
|
4786
|
+
if (options.pruneAll) {
|
|
4457
4787
|
const s2 = de();
|
|
4458
4788
|
s2.start("Pruning orphans");
|
|
4459
4789
|
for (const orphan of orphans) {
|
|
4460
|
-
|
|
4790
|
+
rmSync3(join6(opencodeDir, orphan));
|
|
4461
4791
|
}
|
|
4462
4792
|
s2.stop(`Removed ${orphans.length} files`);
|
|
4463
|
-
} else {
|
|
4464
|
-
const
|
|
4465
|
-
message: "
|
|
4466
|
-
|
|
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
|
|
4467
4798
|
});
|
|
4468
|
-
if (!lD(
|
|
4469
|
-
const
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
});
|
|
4474
|
-
if (!lD(selected) && selected.length > 0) {
|
|
4475
|
-
const s2 = de();
|
|
4476
|
-
s2.start("Deleting files");
|
|
4477
|
-
for (const file of selected) {
|
|
4478
|
-
rmSync2(join6(opencodeDir, file));
|
|
4479
|
-
}
|
|
4480
|
-
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));
|
|
4481
4804
|
}
|
|
4805
|
+
s2.stop(`Deleted ${selected.length} files`);
|
|
4482
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)");
|
|
4483
4820
|
}
|
|
4484
4821
|
}
|
|
4485
|
-
le("cd .opencode && bun install", "Run if dependencies changed");
|
|
4486
4822
|
$e(import_picocolors10.default.green(`Upgraded to ${versionInfo.latest}`));
|
|
4487
4823
|
}
|
|
4488
4824
|
|
|
@@ -6087,7 +6423,7 @@ var cli = cac("ock");
|
|
|
6087
6423
|
cli.option("--verbose", "Enable verbose logging");
|
|
6088
6424
|
cli.option("--quiet", "Suppress all output");
|
|
6089
6425
|
cli.version(`${packageVersion}`);
|
|
6090
|
-
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);
|
|
6091
6427
|
cli.command("agent [action]", "Manage agents (list, add, view)").action(async (action) => {
|
|
6092
6428
|
if (!action) {
|
|
6093
6429
|
console.log(`
|
|
@@ -6137,7 +6473,7 @@ cli.command("status", "Show project overview").action(statusCommand);
|
|
|
6137
6473
|
cli.command("config [action]", "Edit opencode.json (model, mcp, permission, validate, show)").action(async (action) => {
|
|
6138
6474
|
await configCommand(action);
|
|
6139
6475
|
});
|
|
6140
|
-
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) => {
|
|
6141
6477
|
await upgradeCommand(options);
|
|
6142
6478
|
});
|
|
6143
6479
|
cli.command("completion [shell]", "Generate shell completion script (bash, zsh, fish)").action(async (shell) => {
|
|
@@ -119,7 +119,7 @@ GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json
|
|
|
119
119
|
|
|
120
120
|
**Core:** brainstorming, writing-plans, executing-plans, verification-before-completion, using-superpowers, finishing-a-development-branch
|
|
121
121
|
**Code:** requesting-code-review, receiving-code-review, root-cause-tracing, test-driven-development, testing-anti-patterns, condition-based-waiting, defense-in-depth, systematic-debugging
|
|
122
|
-
**UI/UX:** frontend-
|
|
122
|
+
**UI/UX:** frontend-design, mockup-to-code, visual-analysis, ui-ux-research, accessibility-audit, design-system-audit
|
|
123
123
|
**Workflow:** gemini-large-context, subagent-driven-development, dispatching-parallel-agents, using-git-worktrees, sharing-skills, writing-skills, testing-skills-with-subagents
|
|
124
124
|
|
|
125
125
|
**Note:** Skills load via native `skill()` tool. Commands auto-load relevant expertise.
|
|
@@ -65,9 +65,9 @@ Comprehensive analysis with actionable recommendations.
|
|
|
65
65
|
**Use when:** Design review, accessibility audit, system consistency check
|
|
66
66
|
**Skills:** Combine multiple skills based on task:
|
|
67
67
|
|
|
68
|
-
- **UI/UX Review**: Primary `ui-ux-research`, supporting `frontend-
|
|
68
|
+
- **UI/UX Review**: Primary `ui-ux-research`, supporting `frontend-design`
|
|
69
69
|
- **Accessibility**: Primary `accessibility-audit`, supporting `visual-analysis`
|
|
70
|
-
- **Design System**: Primary `design-system-audit`, supporting `frontend-
|
|
70
|
+
- **Design System**: Primary `design-system-audit`, supporting `frontend-design`
|
|
71
71
|
- **Mockup Analysis**: Primary `mockup-to-code`, supporting `visual-analysis`
|
|
72
72
|
|
|
73
73
|
```
|
|
@@ -99,7 +99,7 @@ Load skill(s) → Systematic analysis → Structured findings → Recommendation
|
|
|
99
99
|
- "Check accessibility" → `accessibility-audit`
|
|
100
100
|
- "Audit our design system" → `design-system-audit`
|
|
101
101
|
- "Convert this design to code" → `mockup-to-code`
|
|
102
|
-
- "Is this too AI-looking?" → `frontend-
|
|
102
|
+
- "Is this too AI-looking?" → `frontend-design`
|
|
103
103
|
- "Deep UI/UX analysis" → `ui-ux-research`
|
|
104
104
|
|
|
105
105
|
## Output Format
|
|
@@ -144,4 +144,4 @@ When reviewing designs, actively identify these AI-slop patterns:
|
|
|
144
144
|
- Excessive rounded corners on everything
|
|
145
145
|
- Glassmorphism without purpose
|
|
146
146
|
|
|
147
|
-
**Alternative directions** are covered in `frontend-
|
|
147
|
+
**Alternative directions** are covered in `frontend-design` skill.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Automate browser tasks (scraping, form filling, web interaction)
|
|
3
|
+
argument-hint: "[what you want to do in the browser]"
|
|
4
|
+
agent: general
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Agent Browser: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Automate browser tasks using agent-browser CLI.
|
|
10
|
+
|
|
11
|
+
## Load Skill
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
skill({ name: "agent-browser" });
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then follow the skill instructions to help with browser automation.
|
|
18
|
+
|
|
19
|
+
<user-request>
|
|
20
|
+
$ARGUMENTS
|
|
21
|
+
</user-request>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Complete the next incomplete PRD task for a bead
|
|
3
|
+
argument-hint: "<bead-id>"
|
|
4
|
+
agent: build
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Complete Next Task: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Complete one task from a bead PRD task list.
|
|
10
|
+
|
|
11
|
+
This command is **Beads-native**:
|
|
12
|
+
|
|
13
|
+
- PRD: `.beads/artifacts/<bead-id>/prd.md`
|
|
14
|
+
- Tasks: `.beads/artifacts/<bead-id>/prd.json`
|
|
15
|
+
- Progress: `.beads/artifacts/<bead-id>/progress.txt`
|
|
16
|
+
|
|
17
|
+
## Preconditions
|
|
18
|
+
|
|
19
|
+
- A bead exists: `bd show $ARGUMENTS`
|
|
20
|
+
- PRD task list exists:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
ls ".beads/artifacts/$ARGUMENTS/prd.json"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
If missing:
|
|
27
|
+
|
|
28
|
+
- Create PRD: `.beads/artifacts/$ARGUMENTS/prd.md` (use `skill({ name: "prd" })`)
|
|
29
|
+
- Convert: `skill({ name: "prd-task" })`
|
|
30
|
+
|
|
31
|
+
## Process
|
|
32
|
+
|
|
33
|
+
### 1) Get Bearings
|
|
34
|
+
|
|
35
|
+
- Read `.beads/artifacts/$ARGUMENTS/progress.txt` (create if missing)
|
|
36
|
+
- Read `.beads/artifacts/$ARGUMENTS/prd.json`
|
|
37
|
+
- Pick the next task with `passes: false`
|
|
38
|
+
|
|
39
|
+
### 2) Implement the Task
|
|
40
|
+
|
|
41
|
+
Implement only what’s needed to satisfy the verification steps.
|
|
42
|
+
|
|
43
|
+
### 3) Run Feedback Loops (Required)
|
|
44
|
+
|
|
45
|
+
Run what applies to the repo:
|
|
46
|
+
|
|
47
|
+
- tests
|
|
48
|
+
- lint
|
|
49
|
+
- typecheck
|
|
50
|
+
|
|
51
|
+
Do not commit if any fail.
|
|
52
|
+
|
|
53
|
+
### 4) Update PRD JSON
|
|
54
|
+
|
|
55
|
+
Set that task’s `passes` to `true`.
|
|
56
|
+
|
|
57
|
+
### 5) Update Progress Log
|
|
58
|
+
|
|
59
|
+
Append a short entry to `.beads/artifacts/$ARGUMENTS/progress.txt`:
|
|
60
|
+
|
|
61
|
+
```markdown
|
|
62
|
+
## Task - <task.id>
|
|
63
|
+
|
|
64
|
+
- What was implemented
|
|
65
|
+
- Files changed
|
|
66
|
+
- Learnings / patterns
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 6) Commit (Ask First)
|
|
70
|
+
|
|
71
|
+
Show staged changes and ask user before committing.
|
|
72
|
+
|
|
73
|
+
## Completion
|
|
74
|
+
|
|
75
|
+
If all tasks have `passes: true`, report that the PRD is complete and recommend:
|
|
76
|
+
|
|
77
|
+
- `/finish $ARGUMENTS`
|