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.
Files changed (52) hide show
  1. package/dist/index.js +367 -31
  2. package/dist/template/.opencode/README.md +1 -1
  3. package/dist/template/.opencode/agent/vision.md +4 -4
  4. package/dist/template/.opencode/command/agent-browser.md +21 -0
  5. package/dist/template/.opencode/command/complete-next-task.md +77 -0
  6. package/dist/template/.opencode/command/create.md +38 -3
  7. package/dist/template/.opencode/command/design-audit.md +1 -1
  8. package/dist/template/.opencode/command/design.md +1 -1
  9. package/dist/template/.opencode/command/finish.md +8 -0
  10. package/dist/template/.opencode/command/frontend-design.md +21 -0
  11. package/dist/template/.opencode/command/index-knowledge.md +25 -0
  12. package/dist/template/.opencode/command/init.md +6 -0
  13. package/dist/template/.opencode/command/opensrc.md +58 -0
  14. package/dist/template/.opencode/command/skill-create.md +3 -3
  15. package/dist/template/.opencode/command/skill-optimize.md +2 -2
  16. package/dist/template/.opencode/command/start.md +15 -6
  17. package/dist/template/.opencode/command/ui-review.md +1 -1
  18. package/dist/template/.opencode/memory/_templates/prd.md +50 -14
  19. package/dist/template/.opencode/opencode.json +143 -159
  20. package/dist/template/.opencode/package.json +1 -1
  21. package/dist/template/.opencode/skill/accessibility-audit/SKILL.md +1 -1
  22. package/dist/template/.opencode/skill/agent-browser/SKILL.md +376 -0
  23. package/dist/template/.opencode/skill/design-system-audit/SKILL.md +1 -1
  24. package/dist/template/.opencode/skill/frontend-design/SKILL.md +155 -0
  25. package/dist/template/.opencode/skill/frontend-design/references/animation/motion-advanced.md +224 -0
  26. package/dist/template/.opencode/skill/frontend-design/references/animation/motion-core.md +171 -0
  27. package/dist/template/.opencode/skill/frontend-design/references/canvas/execution.md +90 -0
  28. package/dist/template/.opencode/skill/frontend-design/references/canvas/philosophy.md +94 -0
  29. package/dist/template/.opencode/skill/frontend-design/references/shadcn/accessibility.md +132 -0
  30. package/dist/template/.opencode/skill/frontend-design/references/shadcn/core-components.md +153 -0
  31. package/dist/template/.opencode/skill/frontend-design/references/shadcn/form-components.md +158 -0
  32. package/dist/template/.opencode/skill/frontend-design/references/shadcn/setup.md +69 -0
  33. package/dist/template/.opencode/skill/frontend-design/references/shadcn/theming.md +152 -0
  34. package/dist/template/.opencode/skill/frontend-design/references/tailwind/responsive.md +112 -0
  35. package/dist/template/.opencode/skill/frontend-design/references/tailwind/utilities-layout.md +134 -0
  36. package/dist/template/.opencode/skill/frontend-design/references/tailwind/utilities-styling.md +165 -0
  37. package/dist/template/.opencode/skill/frontend-design/references/tailwind/v4-config.md +147 -0
  38. package/dist/template/.opencode/skill/frontend-design/references/tailwind/v4-features.md +128 -0
  39. package/dist/template/.opencode/skill/index-knowledge/SKILL.md +358 -0
  40. package/dist/template/.opencode/skill/mockup-to-code/SKILL.md +1 -1
  41. package/dist/template/.opencode/skill/opensrc/SKILL.md +115 -0
  42. package/dist/template/.opencode/skill/opensrc/references/architecture.md +176 -0
  43. package/dist/template/.opencode/skill/opensrc/references/cli-usage.md +176 -0
  44. package/dist/template/.opencode/skill/opensrc/references/registry-support.md +137 -0
  45. package/dist/template/.opencode/skill/prd/SKILL.md +212 -0
  46. package/dist/template/.opencode/skill/prd-task/SKILL.md +128 -0
  47. package/dist/template/.opencode/skill/prd-task/references/prd-schema.json +28 -0
  48. package/dist/template/.opencode/skill/skill-creator/SKILL.md +155 -0
  49. package/dist/template/.opencode/skill/ui-ux-research/SKILL.md +1 -1
  50. package/dist/template/.opencode/skill/visual-analysis/SKILL.md +1 -1
  51. package/package.json +1 -1
  52. 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.0",
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 { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, readdirSync as readdirSync3, writeFileSync as writeFileSync4 } from "node:fs";
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 = ["node_modules", ".git", "dist", ".DS_Store", "coverage", ".next", ".turbo"];
3771
- var EXCLUDED_FILES = ["bun.lock", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"];
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 = [join4(__dirname2, "template"), join4(__dirname2, "..", "..", ".opencode")];
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
- le("cd .opencode && bun install", "Next steps");
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
- rmSync(skill.path, { recursive: true, force: true });
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 rmSync2,
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.prune) {
4786
+ if (options.pruneAll) {
4457
4787
  const s2 = de();
4458
4788
  s2.start("Pruning orphans");
4459
4789
  for (const orphan of orphans) {
4460
- rmSync2(join6(opencodeDir, orphan));
4790
+ rmSync3(join6(opencodeDir, orphan));
4461
4791
  }
4462
4792
  s2.stop(`Removed ${orphans.length} files`);
4463
- } else {
4464
- const shouldPrune = await se({
4465
- message: "Do you want to review and delete them?",
4466
- initialValue: false
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(shouldPrune) && shouldPrune) {
4469
- const selected = await ae({
4470
- message: "Select files to delete",
4471
- options: orphans.map((o2) => ({ value: o2, label: o2 })),
4472
- required: false
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-aesthetics, mockup-to-code, visual-analysis, ui-ux-research, accessibility-audit, design-system-audit
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-aesthetics`
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-aesthetics`
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-aesthetics`
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-aesthetics` skill.
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`