opencodekit 0.0.1 → 0.2.0
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 +437 -64
- package/dist/template/.opencode/dcp.jsonc +1 -1
- package/dist/template/.opencode/memory/_templates/task-design.md +59 -0
- package/dist/template/.opencode/opencode.json +9 -52
- package/dist/template/.opencode/package.json +2 -2
- package/dist/template/.opencode/superpowers/skills/brainstorming/SKILL.md +6 -1
- package/dist/template/.opencode/superpowers/skills/writing-plans/SKILL.md +7 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -749,8 +749,8 @@ class CAC extends EventEmitter {
|
|
|
749
749
|
var cac = (name = "") => new CAC(name);
|
|
750
750
|
// package.json
|
|
751
751
|
var package_default = {
|
|
752
|
-
name: "
|
|
753
|
-
version: "0.
|
|
752
|
+
name: "opencodekit",
|
|
753
|
+
version: "0.2.0",
|
|
754
754
|
description: "CLI tool for bootstrapping and managing OpenCodeKit projects",
|
|
755
755
|
type: "module",
|
|
756
756
|
repository: {
|
|
@@ -794,11 +794,8 @@ var package_default = {
|
|
|
794
794
|
devDependencies: {
|
|
795
795
|
"@beads/bd": "^0.29.0",
|
|
796
796
|
"@biomejs/biome": "^1.9.4",
|
|
797
|
-
"@semantic-release/changelog": "^6.0.3",
|
|
798
|
-
"@semantic-release/git": "^10.0.1",
|
|
799
797
|
"@types/bun": "latest",
|
|
800
798
|
"@types/node": "^22.10.1",
|
|
801
|
-
"semantic-release": "^24.2.0",
|
|
802
799
|
typescript: "^5.7.2"
|
|
803
800
|
},
|
|
804
801
|
trustedDependencies: ["@beads/bd"]
|
|
@@ -1968,11 +1965,37 @@ async function configCommand(action) {
|
|
|
1968
1965
|
case "keybinds":
|
|
1969
1966
|
await editKeybinds(configPath);
|
|
1970
1967
|
break;
|
|
1968
|
+
case "theme":
|
|
1969
|
+
await editTheme(configPath);
|
|
1970
|
+
break;
|
|
1971
|
+
case "tui":
|
|
1972
|
+
await editTui(configPath);
|
|
1973
|
+
break;
|
|
1974
|
+
case "tools":
|
|
1975
|
+
await editTools(configPath);
|
|
1976
|
+
break;
|
|
1977
|
+
case "share":
|
|
1978
|
+
await editShare(configPath);
|
|
1979
|
+
break;
|
|
1980
|
+
case "autoupdate":
|
|
1981
|
+
await editAutoupdate(configPath);
|
|
1982
|
+
break;
|
|
1971
1983
|
case "show":
|
|
1972
1984
|
showConfig(configPath);
|
|
1973
1985
|
break;
|
|
1974
1986
|
default:
|
|
1975
|
-
unknownAction(action, [
|
|
1987
|
+
unknownAction(action, [
|
|
1988
|
+
"model",
|
|
1989
|
+
"mcp",
|
|
1990
|
+
"permission",
|
|
1991
|
+
"keybinds",
|
|
1992
|
+
"theme",
|
|
1993
|
+
"tui",
|
|
1994
|
+
"tools",
|
|
1995
|
+
"share",
|
|
1996
|
+
"autoupdate",
|
|
1997
|
+
"show"
|
|
1998
|
+
]);
|
|
1976
1999
|
}
|
|
1977
2000
|
}
|
|
1978
2001
|
function loadConfig(configPath) {
|
|
@@ -1993,6 +2016,23 @@ function showConfig(configPath) {
|
|
|
1993
2016
|
}
|
|
1994
2017
|
console.log(import_picocolors7.default.bold(" Theme"));
|
|
1995
2018
|
console.log(` ${import_picocolors7.default.cyan(config.theme || "system")}`);
|
|
2019
|
+
console.log(import_picocolors7.default.bold(" Share"));
|
|
2020
|
+
console.log(` ${import_picocolors7.default.cyan(config.share || "manual")}`);
|
|
2021
|
+
const autoupdateDisplay = config.autoupdate === "notify" ? "notify" : config.autoupdate === false ? "disabled" : "enabled";
|
|
2022
|
+
console.log(import_picocolors7.default.bold(" Autoupdate"));
|
|
2023
|
+
console.log(` ${import_picocolors7.default.cyan(autoupdateDisplay)}`);
|
|
2024
|
+
if (config.tui && Object.keys(config.tui).length > 0) {
|
|
2025
|
+
console.log(import_picocolors7.default.bold(" TUI"));
|
|
2026
|
+
if (config.tui.scroll_speed !== undefined) {
|
|
2027
|
+
console.log(` scroll_speed: ${import_picocolors7.default.cyan(String(config.tui.scroll_speed))}`);
|
|
2028
|
+
}
|
|
2029
|
+
if (config.tui.scroll_acceleration !== undefined) {
|
|
2030
|
+
console.log(` scroll_acceleration: ${import_picocolors7.default.cyan(String(config.tui.scroll_acceleration))}`);
|
|
2031
|
+
}
|
|
2032
|
+
if (config.tui.diff_style) {
|
|
2033
|
+
console.log(` diff_style: ${import_picocolors7.default.cyan(config.tui.diff_style)}`);
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
1996
2036
|
if (config.mcp && Object.keys(config.mcp).length > 0) {
|
|
1997
2037
|
console.log(import_picocolors7.default.bold(" MCP Servers"));
|
|
1998
2038
|
for (const [name, server] of Object.entries(config.mcp)) {
|
|
@@ -2000,6 +2040,13 @@ function showConfig(configPath) {
|
|
|
2000
2040
|
console.log(` ${status} ${name}`);
|
|
2001
2041
|
}
|
|
2002
2042
|
}
|
|
2043
|
+
if (config.tools && Object.keys(config.tools).length > 0) {
|
|
2044
|
+
console.log(import_picocolors7.default.bold(" Tools"));
|
|
2045
|
+
for (const [tool, enabled] of Object.entries(config.tools)) {
|
|
2046
|
+
const status = enabled === false ? import_picocolors7.default.red("off") : import_picocolors7.default.green("on");
|
|
2047
|
+
console.log(` ${status} ${tool}`);
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2003
2050
|
if (config.keybinds && Object.keys(config.keybinds).length > 0) {
|
|
2004
2051
|
console.log(import_picocolors7.default.bold(" Keybinds"));
|
|
2005
2052
|
for (const [action, key] of Object.entries(config.keybinds)) {
|
|
@@ -2010,51 +2057,74 @@ function showConfig(configPath) {
|
|
|
2010
2057
|
}
|
|
2011
2058
|
async function configMenu(configPath) {
|
|
2012
2059
|
oe(import_picocolors7.default.bgCyan(import_picocolors7.default.black(" Configuration ")));
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
value: "
|
|
2025
|
-
label: "
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2060
|
+
while (true) {
|
|
2061
|
+
const action = await ie({
|
|
2062
|
+
message: "What do you want to configure?",
|
|
2063
|
+
options: [
|
|
2064
|
+
{ value: "model", label: "Model - change default model" },
|
|
2065
|
+
{
|
|
2066
|
+
value: "small_model",
|
|
2067
|
+
label: "Small Model - change small model"
|
|
2068
|
+
},
|
|
2069
|
+
{ value: "agent", label: "Agents - configure agent models" },
|
|
2070
|
+
{ value: "theme", label: "Theme - change UI theme" },
|
|
2071
|
+
{ value: "tui", label: "TUI - scroll speed, diff style" },
|
|
2072
|
+
{ value: "mcp", label: "MCP - manage MCP servers" },
|
|
2073
|
+
{ value: "tools", label: "Tools - enable/disable tools" },
|
|
2074
|
+
{
|
|
2075
|
+
value: "permission",
|
|
2076
|
+
label: "Permissions - bash/edit permissions"
|
|
2077
|
+
},
|
|
2078
|
+
{ value: "keybinds", label: "Keybinds - keyboard shortcuts" },
|
|
2079
|
+
{ value: "share", label: "Share - sharing settings" },
|
|
2080
|
+
{ value: "autoupdate", label: "Autoupdate - update behavior" },
|
|
2081
|
+
{ value: "show", label: "Show - view current config" },
|
|
2082
|
+
{ value: "exit", label: "Exit" }
|
|
2083
|
+
]
|
|
2084
|
+
});
|
|
2085
|
+
if (lD(action) || action === "exit") {
|
|
2086
|
+
$e("Done");
|
|
2087
|
+
return;
|
|
2088
|
+
}
|
|
2089
|
+
switch (action) {
|
|
2090
|
+
case "model":
|
|
2091
|
+
await editModel(configPath);
|
|
2092
|
+
break;
|
|
2093
|
+
case "small_model":
|
|
2094
|
+
await editModel(configPath, "small_model");
|
|
2095
|
+
break;
|
|
2096
|
+
case "agent":
|
|
2097
|
+
await editAgentModel(configPath);
|
|
2098
|
+
break;
|
|
2099
|
+
case "theme":
|
|
2100
|
+
await editTheme(configPath);
|
|
2101
|
+
break;
|
|
2102
|
+
case "tui":
|
|
2103
|
+
await editTui(configPath);
|
|
2104
|
+
break;
|
|
2105
|
+
case "mcp":
|
|
2106
|
+
await editMCP(configPath);
|
|
2107
|
+
break;
|
|
2108
|
+
case "tools":
|
|
2109
|
+
await editTools(configPath);
|
|
2110
|
+
break;
|
|
2111
|
+
case "permission":
|
|
2112
|
+
await editPermissions(configPath);
|
|
2113
|
+
break;
|
|
2114
|
+
case "keybinds":
|
|
2115
|
+
await editKeybinds(configPath);
|
|
2116
|
+
break;
|
|
2117
|
+
case "share":
|
|
2118
|
+
await editShare(configPath);
|
|
2119
|
+
break;
|
|
2120
|
+
case "autoupdate":
|
|
2121
|
+
await editAutoupdate(configPath);
|
|
2122
|
+
break;
|
|
2123
|
+
case "show":
|
|
2124
|
+
showConfig(configPath);
|
|
2125
|
+
break;
|
|
2126
|
+
}
|
|
2127
|
+
console.log();
|
|
2058
2128
|
}
|
|
2059
2129
|
}
|
|
2060
2130
|
async function editModel(configPath, modelType = "model") {
|
|
@@ -2091,6 +2161,11 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2091
2161
|
const configuredProviderIds = new Set(Object.keys(localProviders));
|
|
2092
2162
|
const allProviders = Object.values(modelsDevData);
|
|
2093
2163
|
const quickOptions = [];
|
|
2164
|
+
quickOptions.push({
|
|
2165
|
+
value: "__back__",
|
|
2166
|
+
label: "← Back",
|
|
2167
|
+
hint: "return to menu"
|
|
2168
|
+
});
|
|
2094
2169
|
for (const [providerId2, providerConfig] of Object.entries(localProviders)) {
|
|
2095
2170
|
const modelsDevProvider2 = modelsDevData[providerId2];
|
|
2096
2171
|
const localModels = providerConfig.models || {};
|
|
@@ -2118,10 +2193,12 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2118
2193
|
options: quickOptions
|
|
2119
2194
|
});
|
|
2120
2195
|
if (lD(quickPick)) {
|
|
2121
|
-
ue("Cancelled");
|
|
2122
2196
|
return;
|
|
2123
2197
|
}
|
|
2124
2198
|
let providerId = quickPick;
|
|
2199
|
+
if (providerId === "__back__") {
|
|
2200
|
+
return;
|
|
2201
|
+
}
|
|
2125
2202
|
if (providerId === "__custom__") {
|
|
2126
2203
|
const customModel = await te({
|
|
2127
2204
|
message: `Enter ${modelLabel}`,
|
|
@@ -2175,10 +2252,21 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2175
2252
|
const modelsDevProvider = modelsDevData[providerId];
|
|
2176
2253
|
const localProviderConfig = localProviders[providerId];
|
|
2177
2254
|
let modelOptions = [];
|
|
2255
|
+
modelOptions.push({
|
|
2256
|
+
value: "__back__",
|
|
2257
|
+
label: "← Back",
|
|
2258
|
+
hint: "return to provider selection"
|
|
2259
|
+
});
|
|
2178
2260
|
if (modelsDevProvider && Object.keys(modelsDevProvider.models || {}).length > 0) {
|
|
2179
|
-
modelOptions =
|
|
2261
|
+
modelOptions = [
|
|
2262
|
+
modelOptions[0],
|
|
2263
|
+
...getModelsForProvider(modelsDevProvider)
|
|
2264
|
+
];
|
|
2180
2265
|
} else if (localProviderConfig?.models && Object.keys(localProviderConfig.models).length > 0) {
|
|
2181
|
-
modelOptions =
|
|
2266
|
+
modelOptions = [
|
|
2267
|
+
modelOptions[0],
|
|
2268
|
+
...getModelsFromLocalConfig(localProviderConfig.models)
|
|
2269
|
+
];
|
|
2182
2270
|
} else {
|
|
2183
2271
|
f2.warn(`No models found for ${providerId}`);
|
|
2184
2272
|
return;
|
|
@@ -2187,8 +2275,7 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2187
2275
|
message: `Select model from ${providerId}`,
|
|
2188
2276
|
options: modelOptions
|
|
2189
2277
|
});
|
|
2190
|
-
if (lD(selectedModel)) {
|
|
2191
|
-
ue("Cancelled");
|
|
2278
|
+
if (lD(selectedModel) || selectedModel === "__back__") {
|
|
2192
2279
|
return;
|
|
2193
2280
|
}
|
|
2194
2281
|
const fullModelId = `${providerId}/${selectedModel}`;
|
|
@@ -2276,9 +2363,9 @@ async function editAgentModel(configPath) {
|
|
|
2276
2363
|
console.log(` ${import_picocolors7.default.cyan(name)}: ${model}${builtIn}${disabled}`);
|
|
2277
2364
|
}
|
|
2278
2365
|
console.log();
|
|
2279
|
-
const
|
|
2280
|
-
|
|
2281
|
-
|
|
2366
|
+
const agentOptions = [
|
|
2367
|
+
{ value: "__back__", label: "← Back", hint: "return to menu" },
|
|
2368
|
+
...agentNames.map((name) => {
|
|
2282
2369
|
const info = agentInfoMap.get(name);
|
|
2283
2370
|
return {
|
|
2284
2371
|
value: name,
|
|
@@ -2286,8 +2373,12 @@ async function editAgentModel(configPath) {
|
|
|
2286
2373
|
hint: info?.model || "(default)"
|
|
2287
2374
|
};
|
|
2288
2375
|
})
|
|
2376
|
+
];
|
|
2377
|
+
const selectedAgent = await ie({
|
|
2378
|
+
message: "Select agent to configure",
|
|
2379
|
+
options: agentOptions
|
|
2289
2380
|
});
|
|
2290
|
-
if (lD(selectedAgent)) {
|
|
2381
|
+
if (lD(selectedAgent) || selectedAgent === "__back__") {
|
|
2291
2382
|
return;
|
|
2292
2383
|
}
|
|
2293
2384
|
const agentName = selectedAgent;
|
|
@@ -2295,6 +2386,11 @@ async function editAgentModel(configPath) {
|
|
|
2295
2386
|
const action = await ie({
|
|
2296
2387
|
message: `Configure ${agentName}`,
|
|
2297
2388
|
options: [
|
|
2389
|
+
{
|
|
2390
|
+
value: "__back__",
|
|
2391
|
+
label: "← Back",
|
|
2392
|
+
hint: "return to agent list"
|
|
2393
|
+
},
|
|
2298
2394
|
{ value: "model", label: "Change model" },
|
|
2299
2395
|
{
|
|
2300
2396
|
value: "toggle",
|
|
@@ -2303,7 +2399,7 @@ async function editAgentModel(configPath) {
|
|
|
2303
2399
|
{ value: "description", label: "Edit description" }
|
|
2304
2400
|
]
|
|
2305
2401
|
});
|
|
2306
|
-
if (lD(action)) {
|
|
2402
|
+
if (lD(action) || action === "__back__") {
|
|
2307
2403
|
return;
|
|
2308
2404
|
}
|
|
2309
2405
|
if (action === "toggle") {
|
|
@@ -2362,6 +2458,11 @@ async function editAgentModel(configPath) {
|
|
|
2362
2458
|
const localProviders = config.provider || {};
|
|
2363
2459
|
const allProviders = Object.values(modelsDevData);
|
|
2364
2460
|
const quickOptions = [];
|
|
2461
|
+
quickOptions.push({
|
|
2462
|
+
value: "__back__",
|
|
2463
|
+
label: "← Back",
|
|
2464
|
+
hint: "return to agent list"
|
|
2465
|
+
});
|
|
2365
2466
|
quickOptions.push({
|
|
2366
2467
|
value: "__default__",
|
|
2367
2468
|
label: "Default - use session model",
|
|
@@ -2397,6 +2498,9 @@ async function editAgentModel(configPath) {
|
|
|
2397
2498
|
return;
|
|
2398
2499
|
}
|
|
2399
2500
|
let providerId = quickPick;
|
|
2501
|
+
if (providerId === "__back__") {
|
|
2502
|
+
return;
|
|
2503
|
+
}
|
|
2400
2504
|
if (providerId === "__default__") {
|
|
2401
2505
|
if (!config.agent[agentName]) {
|
|
2402
2506
|
config.agent[agentName] = {};
|
|
@@ -2504,12 +2608,13 @@ async function editMCP(configPath) {
|
|
|
2504
2608
|
const action = await ie({
|
|
2505
2609
|
message: "MCP Servers",
|
|
2506
2610
|
options: [
|
|
2611
|
+
{ value: "__back__", label: "← Back", hint: "return to menu" },
|
|
2507
2612
|
{ value: "toggle", label: "Toggle server on/off" },
|
|
2508
2613
|
{ value: "add", label: "Add new server" },
|
|
2509
2614
|
{ value: "remove", label: "Remove server" }
|
|
2510
2615
|
]
|
|
2511
2616
|
});
|
|
2512
|
-
if (lD(action)) {
|
|
2617
|
+
if (lD(action) || action === "__back__") {
|
|
2513
2618
|
return;
|
|
2514
2619
|
}
|
|
2515
2620
|
switch (action) {
|
|
@@ -2652,6 +2757,7 @@ async function editPermissions(configPath) {
|
|
|
2652
2757
|
const action = await ie({
|
|
2653
2758
|
message: "Edit permission",
|
|
2654
2759
|
options: [
|
|
2760
|
+
{ value: "__back__", label: "← Back", hint: "return to menu" },
|
|
2655
2761
|
{ value: "edit", label: "edit - file editing" },
|
|
2656
2762
|
{
|
|
2657
2763
|
value: "external",
|
|
@@ -2660,7 +2766,7 @@ async function editPermissions(configPath) {
|
|
|
2660
2766
|
{ value: "bash", label: "bash - add command pattern" }
|
|
2661
2767
|
]
|
|
2662
2768
|
});
|
|
2663
|
-
if (lD(action)) {
|
|
2769
|
+
if (lD(action) || action === "__back__") {
|
|
2664
2770
|
return;
|
|
2665
2771
|
}
|
|
2666
2772
|
const permValue = await ie({
|
|
@@ -2715,6 +2821,7 @@ async function editKeybinds(configPath) {
|
|
|
2715
2821
|
const action = await ie({
|
|
2716
2822
|
message: "Select keybind to edit",
|
|
2717
2823
|
options: [
|
|
2824
|
+
{ value: "__back__", label: "← Back", hint: "return to menu" },
|
|
2718
2825
|
{ value: "leader", label: "leader - prefix key" },
|
|
2719
2826
|
{
|
|
2720
2827
|
value: "command_list",
|
|
@@ -2731,7 +2838,7 @@ async function editKeybinds(configPath) {
|
|
|
2731
2838
|
{ value: "custom", label: "Custom keybind" }
|
|
2732
2839
|
]
|
|
2733
2840
|
});
|
|
2734
|
-
if (lD(action)) {
|
|
2841
|
+
if (lD(action) || action === "__back__") {
|
|
2735
2842
|
return;
|
|
2736
2843
|
}
|
|
2737
2844
|
let keybindName = action;
|
|
@@ -2762,6 +2869,272 @@ async function editKeybinds(configPath) {
|
|
|
2762
2869
|
saveConfig(configPath, config);
|
|
2763
2870
|
f2.success(`${keybindName} → ${import_picocolors7.default.cyan(newKey)}`);
|
|
2764
2871
|
}
|
|
2872
|
+
var OPENCODE_THEMES = [
|
|
2873
|
+
{ value: "system", label: "System", hint: "follows OS preference" },
|
|
2874
|
+
{ value: "opencode", label: "OpenCode", hint: "default theme" },
|
|
2875
|
+
{ value: "aura", label: "Aura", hint: "dark purple" },
|
|
2876
|
+
{ value: "ayu", label: "Ayu", hint: "warm dark" },
|
|
2877
|
+
{ value: "catppuccin", label: "Catppuccin", hint: "pastel dark" },
|
|
2878
|
+
{
|
|
2879
|
+
value: "catppuccin-macchiato",
|
|
2880
|
+
label: "Catppuccin Macchiato",
|
|
2881
|
+
hint: "warm pastel"
|
|
2882
|
+
},
|
|
2883
|
+
{ value: "cobalt2", label: "Cobalt2", hint: "blue dark" },
|
|
2884
|
+
{ value: "dracula", label: "Dracula", hint: "dark purple/pink" },
|
|
2885
|
+
{ value: "everforest", label: "Everforest", hint: "green dark" },
|
|
2886
|
+
{ value: "flexoki", label: "Flexoki", hint: "warm minimal" },
|
|
2887
|
+
{ value: "github", label: "GitHub", hint: "light/dark" },
|
|
2888
|
+
{ value: "gruvbox", label: "Gruvbox", hint: "retro warm" },
|
|
2889
|
+
{ value: "kanagawa", label: "Kanagawa", hint: "japanese inspired" },
|
|
2890
|
+
{ value: "material", label: "Material", hint: "google material" },
|
|
2891
|
+
{ value: "matrix", label: "Matrix", hint: "green terminal" },
|
|
2892
|
+
{ value: "mercury", label: "Mercury", hint: "minimal dark" },
|
|
2893
|
+
{ value: "monokai", label: "Monokai", hint: "classic dark" },
|
|
2894
|
+
{ value: "nightowl", label: "Night Owl", hint: "blue dark" },
|
|
2895
|
+
{ value: "nord", label: "Nord", hint: "arctic blue" },
|
|
2896
|
+
{ value: "one-dark", label: "One Dark", hint: "atom inspired" },
|
|
2897
|
+
{ value: "orng", label: "Orng", hint: "orange accent" },
|
|
2898
|
+
{ value: "palenight", label: "Palenight", hint: "purple dark" },
|
|
2899
|
+
{ value: "rosepine", label: "Rosé Pine", hint: "soft pink" },
|
|
2900
|
+
{ value: "solarized", label: "Solarized", hint: "precision colors" },
|
|
2901
|
+
{ value: "synthwave84", label: "Synthwave '84", hint: "retro neon" },
|
|
2902
|
+
{ value: "tokyonight", label: "Tokyo Night", hint: "vibrant dark" },
|
|
2903
|
+
{ value: "vercel", label: "Vercel", hint: "minimal black" },
|
|
2904
|
+
{ value: "vesper", label: "Vesper", hint: "warm dark" },
|
|
2905
|
+
{ value: "zenburn", label: "Zenburn", hint: "low contrast" }
|
|
2906
|
+
];
|
|
2907
|
+
async function editTheme(configPath) {
|
|
2908
|
+
const config = loadConfig(configPath);
|
|
2909
|
+
const currentTheme = config.theme || "system";
|
|
2910
|
+
f2.info(`Current theme: ${import_picocolors7.default.cyan(currentTheme)}`);
|
|
2911
|
+
const selectedTheme = await ie({
|
|
2912
|
+
message: "Select theme",
|
|
2913
|
+
options: OPENCODE_THEMES.map((t) => ({
|
|
2914
|
+
value: t.value,
|
|
2915
|
+
label: t.label,
|
|
2916
|
+
hint: t.hint
|
|
2917
|
+
})),
|
|
2918
|
+
initialValue: currentTheme
|
|
2919
|
+
});
|
|
2920
|
+
if (lD(selectedTheme)) {
|
|
2921
|
+
ue("Cancelled");
|
|
2922
|
+
return;
|
|
2923
|
+
}
|
|
2924
|
+
config.theme = selectedTheme;
|
|
2925
|
+
saveConfig(configPath, config);
|
|
2926
|
+
f2.success(`Theme set to ${import_picocolors7.default.cyan(selectedTheme)}`);
|
|
2927
|
+
}
|
|
2928
|
+
async function editTui(configPath) {
|
|
2929
|
+
const config = loadConfig(configPath);
|
|
2930
|
+
if (!config.tui) {
|
|
2931
|
+
config.tui = {};
|
|
2932
|
+
}
|
|
2933
|
+
const setting = await ie({
|
|
2934
|
+
message: "TUI Setting",
|
|
2935
|
+
options: [
|
|
2936
|
+
{
|
|
2937
|
+
value: "__back__",
|
|
2938
|
+
label: "← Back",
|
|
2939
|
+
hint: "return to menu"
|
|
2940
|
+
},
|
|
2941
|
+
{
|
|
2942
|
+
value: "scroll_speed",
|
|
2943
|
+
label: "Scroll Speed",
|
|
2944
|
+
hint: `current: ${config.tui.scroll_speed ?? "default"}`
|
|
2945
|
+
},
|
|
2946
|
+
{
|
|
2947
|
+
value: "scroll_acceleration",
|
|
2948
|
+
label: "Scroll Acceleration",
|
|
2949
|
+
hint: `current: ${config.tui.scroll_acceleration ?? "default"}`
|
|
2950
|
+
},
|
|
2951
|
+
{
|
|
2952
|
+
value: "diff_style",
|
|
2953
|
+
label: "Diff Style",
|
|
2954
|
+
hint: `current: ${config.tui.diff_style ?? "unified"}`
|
|
2955
|
+
}
|
|
2956
|
+
]
|
|
2957
|
+
});
|
|
2958
|
+
if (lD(setting) || setting === "__back__") {
|
|
2959
|
+
return;
|
|
2960
|
+
}
|
|
2961
|
+
if (setting === "diff_style") {
|
|
2962
|
+
const style = await ie({
|
|
2963
|
+
message: "Diff style",
|
|
2964
|
+
options: [
|
|
2965
|
+
{ value: "unified", label: "Unified", hint: "single column" },
|
|
2966
|
+
{ value: "split", label: "Split", hint: "side by side" }
|
|
2967
|
+
]
|
|
2968
|
+
});
|
|
2969
|
+
if (lD(style)) {
|
|
2970
|
+
return;
|
|
2971
|
+
}
|
|
2972
|
+
config.tui.diff_style = style;
|
|
2973
|
+
saveConfig(configPath, config);
|
|
2974
|
+
f2.success(`Diff style set to ${import_picocolors7.default.cyan(style)}`);
|
|
2975
|
+
} else {
|
|
2976
|
+
const settingKey = setting;
|
|
2977
|
+
const value = await te({
|
|
2978
|
+
message: `${settingKey === "scroll_speed" ? "Scroll speed" : "Scroll acceleration"}`,
|
|
2979
|
+
placeholder: "e.g. 1.0, 2.0",
|
|
2980
|
+
initialValue: String(config.tui[settingKey] ?? ""),
|
|
2981
|
+
validate: (v2) => {
|
|
2982
|
+
if (v2 && Number.isNaN(Number(v2)))
|
|
2983
|
+
return "Must be a number";
|
|
2984
|
+
}
|
|
2985
|
+
});
|
|
2986
|
+
if (lD(value)) {
|
|
2987
|
+
return;
|
|
2988
|
+
}
|
|
2989
|
+
config.tui[settingKey] = value ? Number(value) : undefined;
|
|
2990
|
+
saveConfig(configPath, config);
|
|
2991
|
+
f2.success(`${settingKey} set to ${import_picocolors7.default.cyan(value || "default")}`);
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
async function editTools(configPath) {
|
|
2995
|
+
const config = loadConfig(configPath);
|
|
2996
|
+
if (!config.tools) {
|
|
2997
|
+
config.tools = {};
|
|
2998
|
+
}
|
|
2999
|
+
const commonTools = [
|
|
3000
|
+
"read",
|
|
3001
|
+
"glob",
|
|
3002
|
+
"grep",
|
|
3003
|
+
"edit",
|
|
3004
|
+
"write",
|
|
3005
|
+
"bash",
|
|
3006
|
+
"webfetch",
|
|
3007
|
+
"todowrite",
|
|
3008
|
+
"todoread"
|
|
3009
|
+
];
|
|
3010
|
+
console.log();
|
|
3011
|
+
console.log(import_picocolors7.default.bold(" Tool Status"));
|
|
3012
|
+
for (const tool of commonTools) {
|
|
3013
|
+
const status = config.tools[tool] === false ? import_picocolors7.default.red("off") : import_picocolors7.default.green("on");
|
|
3014
|
+
console.log(` ${status} ${tool}`);
|
|
3015
|
+
}
|
|
3016
|
+
console.log();
|
|
3017
|
+
const action = await ie({
|
|
3018
|
+
message: "Select action",
|
|
3019
|
+
options: [
|
|
3020
|
+
{ value: "__back__", label: "← Back", hint: "return to menu" },
|
|
3021
|
+
{ value: "toggle", label: "Toggle tool on/off" },
|
|
3022
|
+
{ value: "custom", label: "Add custom tool" }
|
|
3023
|
+
]
|
|
3024
|
+
});
|
|
3025
|
+
if (lD(action) || action === "__back__") {
|
|
3026
|
+
return;
|
|
3027
|
+
}
|
|
3028
|
+
if (action === "toggle") {
|
|
3029
|
+
const allTools = [
|
|
3030
|
+
...new Set([...commonTools, ...Object.keys(config.tools)])
|
|
3031
|
+
];
|
|
3032
|
+
const selected = await ie({
|
|
3033
|
+
message: "Select tool to toggle",
|
|
3034
|
+
options: allTools.map((tool) => ({
|
|
3035
|
+
value: tool,
|
|
3036
|
+
label: tool,
|
|
3037
|
+
hint: config.tools?.[tool] === false ? "off" : "on"
|
|
3038
|
+
}))
|
|
3039
|
+
});
|
|
3040
|
+
if (lD(selected)) {
|
|
3041
|
+
return;
|
|
3042
|
+
}
|
|
3043
|
+
const toolName = selected;
|
|
3044
|
+
const wasEnabled = config.tools[toolName] !== false;
|
|
3045
|
+
config.tools[toolName] = !wasEnabled;
|
|
3046
|
+
saveConfig(configPath, config);
|
|
3047
|
+
const status = config.tools[toolName] ? import_picocolors7.default.green("enabled") : import_picocolors7.default.red("disabled");
|
|
3048
|
+
f2.success(`${toolName}: ${status}`);
|
|
3049
|
+
} else {
|
|
3050
|
+
const toolName = await te({
|
|
3051
|
+
message: "Tool name",
|
|
3052
|
+
placeholder: "e.g. my-custom-tool",
|
|
3053
|
+
validate: (v2) => {
|
|
3054
|
+
if (!v2)
|
|
3055
|
+
return "Tool name is required";
|
|
3056
|
+
}
|
|
3057
|
+
});
|
|
3058
|
+
if (lD(toolName)) {
|
|
3059
|
+
return;
|
|
3060
|
+
}
|
|
3061
|
+
const enabled = await se({
|
|
3062
|
+
message: "Enable this tool?",
|
|
3063
|
+
initialValue: true
|
|
3064
|
+
});
|
|
3065
|
+
if (lD(enabled)) {
|
|
3066
|
+
return;
|
|
3067
|
+
}
|
|
3068
|
+
config.tools[toolName] = enabled;
|
|
3069
|
+
saveConfig(configPath, config);
|
|
3070
|
+
f2.success(`Added ${toolName}: ${enabled ? import_picocolors7.default.green("on") : import_picocolors7.default.red("off")}`);
|
|
3071
|
+
}
|
|
3072
|
+
}
|
|
3073
|
+
async function editShare(configPath) {
|
|
3074
|
+
const config = loadConfig(configPath);
|
|
3075
|
+
const current = config.share || "manual";
|
|
3076
|
+
f2.info(`Current share setting: ${import_picocolors7.default.cyan(current)}`);
|
|
3077
|
+
const selected = await ie({
|
|
3078
|
+
message: "Share setting",
|
|
3079
|
+
options: [
|
|
3080
|
+
{
|
|
3081
|
+
value: "manual",
|
|
3082
|
+
label: "Manual",
|
|
3083
|
+
hint: "share when requested"
|
|
3084
|
+
},
|
|
3085
|
+
{
|
|
3086
|
+
value: "auto",
|
|
3087
|
+
label: "Auto",
|
|
3088
|
+
hint: "automatically share sessions"
|
|
3089
|
+
},
|
|
3090
|
+
{ value: "disabled", label: "Disabled", hint: "never share" }
|
|
3091
|
+
]
|
|
3092
|
+
});
|
|
3093
|
+
if (lD(selected)) {
|
|
3094
|
+
return;
|
|
3095
|
+
}
|
|
3096
|
+
const shareValue = selected;
|
|
3097
|
+
config.share = shareValue;
|
|
3098
|
+
saveConfig(configPath, config);
|
|
3099
|
+
f2.success(`Share set to ${import_picocolors7.default.cyan(shareValue)}`);
|
|
3100
|
+
}
|
|
3101
|
+
async function editAutoupdate(configPath) {
|
|
3102
|
+
const config = loadConfig(configPath);
|
|
3103
|
+
const current = config.autoupdate ?? true;
|
|
3104
|
+
const display = current === "notify" ? "notify" : current ? "enabled" : "disabled";
|
|
3105
|
+
f2.info(`Current autoupdate: ${import_picocolors7.default.cyan(display)}`);
|
|
3106
|
+
const selected = await ie({
|
|
3107
|
+
message: "Autoupdate behavior",
|
|
3108
|
+
options: [
|
|
3109
|
+
{
|
|
3110
|
+
value: "true",
|
|
3111
|
+
label: "Enabled",
|
|
3112
|
+
hint: "auto-update OpenCode"
|
|
3113
|
+
},
|
|
3114
|
+
{
|
|
3115
|
+
value: "notify",
|
|
3116
|
+
label: "Notify",
|
|
3117
|
+
hint: "notify but don't auto-update"
|
|
3118
|
+
},
|
|
3119
|
+
{
|
|
3120
|
+
value: "false",
|
|
3121
|
+
label: "Disabled",
|
|
3122
|
+
hint: "never update automatically"
|
|
3123
|
+
}
|
|
3124
|
+
]
|
|
3125
|
+
});
|
|
3126
|
+
if (lD(selected)) {
|
|
3127
|
+
return;
|
|
3128
|
+
}
|
|
3129
|
+
const selectedValue = selected;
|
|
3130
|
+
if (selectedValue === "notify") {
|
|
3131
|
+
config.autoupdate = "notify";
|
|
3132
|
+
} else {
|
|
3133
|
+
config.autoupdate = selectedValue === "true";
|
|
3134
|
+
}
|
|
3135
|
+
saveConfig(configPath, config);
|
|
3136
|
+
f2.success(`Autoupdate set to ${import_picocolors7.default.cyan(selectedValue)}`);
|
|
3137
|
+
}
|
|
2765
3138
|
|
|
2766
3139
|
// src/commands/upgrade.ts
|
|
2767
3140
|
import { join as join5, dirname as dirname2 } from "node:path";
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// AI analysis strategies (deduplication runs automatically on every request)
|
|
13
13
|
"strategies": {
|
|
14
14
|
// Strategies to run when session goes idle
|
|
15
|
-
"onIdle": ["
|
|
15
|
+
"onIdle": [""],
|
|
16
16
|
// Strategies to run when AI calls prune tool
|
|
17
17
|
"onTool": ["ai-analysis"],
|
|
18
18
|
},
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Design Document
|
|
2
|
+
|
|
3
|
+
**Bead ID:** [bead-id]
|
|
4
|
+
**Created:** [date]
|
|
5
|
+
**Status:** Draft | Validated
|
|
6
|
+
|
|
7
|
+
## Problem Statement
|
|
8
|
+
|
|
9
|
+
What we're solving and why it matters:
|
|
10
|
+
|
|
11
|
+
## Approaches Considered
|
|
12
|
+
|
|
13
|
+
### Option A: [Name]
|
|
14
|
+
|
|
15
|
+
- **Pros:** [advantages]
|
|
16
|
+
- **Cons:** [drawbacks]
|
|
17
|
+
|
|
18
|
+
### Option B: [Name]
|
|
19
|
+
|
|
20
|
+
- **Pros:** [advantages]
|
|
21
|
+
- **Cons:** [drawbacks]
|
|
22
|
+
|
|
23
|
+
### Chosen Approach
|
|
24
|
+
|
|
25
|
+
[Which option and why]
|
|
26
|
+
|
|
27
|
+
## Architecture
|
|
28
|
+
|
|
29
|
+
High-level structure and how components fit together:
|
|
30
|
+
|
|
31
|
+
### Components
|
|
32
|
+
|
|
33
|
+
- [Component 1]: [purpose]
|
|
34
|
+
- [Component 2]: [purpose]
|
|
35
|
+
|
|
36
|
+
### Data Flow
|
|
37
|
+
|
|
38
|
+
[How data moves through the system]
|
|
39
|
+
|
|
40
|
+
## Error Handling
|
|
41
|
+
|
|
42
|
+
How the design handles failure cases:
|
|
43
|
+
|
|
44
|
+
- [Error scenario 1]: [handling approach]
|
|
45
|
+
- [Error scenario 2]: [handling approach]
|
|
46
|
+
|
|
47
|
+
## Testing Strategy
|
|
48
|
+
|
|
49
|
+
How we'll validate this design works:
|
|
50
|
+
|
|
51
|
+
- [Testing approach 1]
|
|
52
|
+
- [Testing approach 2]
|
|
53
|
+
|
|
54
|
+
## Open Questions
|
|
55
|
+
|
|
56
|
+
Unresolved items to address during implementation:
|
|
57
|
+
|
|
58
|
+
- [ ] [Question 1]
|
|
59
|
+
- [ ] [Question 2]
|
|
@@ -35,60 +35,23 @@
|
|
|
35
35
|
"experimental": {
|
|
36
36
|
"batch_tool": true,
|
|
37
37
|
"chatMaxRetries": 2,
|
|
38
|
-
"primary_tools": [
|
|
39
|
-
"edit",
|
|
40
|
-
"write",
|
|
41
|
-
"bash",
|
|
42
|
-
"prune"
|
|
43
|
-
]
|
|
38
|
+
"primary_tools": ["edit", "write", "bash", "prune"]
|
|
44
39
|
},
|
|
45
40
|
"formatter": {
|
|
46
41
|
"biome": {
|
|
47
|
-
"command": [
|
|
48
|
-
|
|
49
|
-
"@biomejs/biome",
|
|
50
|
-
"check",
|
|
51
|
-
"--write",
|
|
52
|
-
"$FILE"
|
|
53
|
-
],
|
|
54
|
-
"extensions": [
|
|
55
|
-
".js",
|
|
56
|
-
".jsx",
|
|
57
|
-
".ts",
|
|
58
|
-
".tsx",
|
|
59
|
-
".json",
|
|
60
|
-
".jsonc"
|
|
61
|
-
]
|
|
42
|
+
"command": ["npx", "@biomejs/biome", "check", "--write", "$FILE"],
|
|
43
|
+
"extensions": [".js", ".jsx", ".ts", ".tsx", ".json", ".jsonc"]
|
|
62
44
|
},
|
|
63
45
|
"java-formatter": {
|
|
64
|
-
"command": [
|
|
65
|
-
"google-java-format",
|
|
66
|
-
"--replace",
|
|
67
|
-
"$FILE"
|
|
68
|
-
],
|
|
46
|
+
"command": ["google-java-format", "--replace", "$FILE"],
|
|
69
47
|
"environment": {
|
|
70
48
|
"JAVA_HOME": "{env:JAVA_HOME}"
|
|
71
49
|
},
|
|
72
|
-
"extensions": [
|
|
73
|
-
".java"
|
|
74
|
-
]
|
|
50
|
+
"extensions": [".java"]
|
|
75
51
|
},
|
|
76
52
|
"prettier": {
|
|
77
|
-
"command": [
|
|
78
|
-
|
|
79
|
-
"prettier",
|
|
80
|
-
"--write",
|
|
81
|
-
"$FILE"
|
|
82
|
-
],
|
|
83
|
-
"extensions": [
|
|
84
|
-
".html",
|
|
85
|
-
".css",
|
|
86
|
-
".scss",
|
|
87
|
-
".sass",
|
|
88
|
-
".md",
|
|
89
|
-
".yaml",
|
|
90
|
-
".yml"
|
|
91
|
-
]
|
|
53
|
+
"command": ["npx", "prettier", "--write", "$FILE"],
|
|
54
|
+
"extensions": [".html", ".css", ".scss", ".sass", ".md", ".yaml", ".yml"]
|
|
92
55
|
}
|
|
93
56
|
},
|
|
94
57
|
"keybinds": {
|
|
@@ -110,10 +73,7 @@
|
|
|
110
73
|
"type": "local"
|
|
111
74
|
},
|
|
112
75
|
"augment-context-engine": {
|
|
113
|
-
"command": [
|
|
114
|
-
"auggie",
|
|
115
|
-
"--mcp"
|
|
116
|
-
],
|
|
76
|
+
"command": ["auggie", "--mcp"],
|
|
117
77
|
"enabled": false,
|
|
118
78
|
"type": "local"
|
|
119
79
|
},
|
|
@@ -136,10 +96,7 @@
|
|
|
136
96
|
"url": "http://localhost:27495/mcp"
|
|
137
97
|
},
|
|
138
98
|
"playwright": {
|
|
139
|
-
"command": [
|
|
140
|
-
"npx",
|
|
141
|
-
"@playwright/mcp@latest"
|
|
142
|
-
],
|
|
99
|
+
"command": ["npx", "@playwright/mcp@latest"],
|
|
143
100
|
"enabled": false,
|
|
144
101
|
"type": "local"
|
|
145
102
|
}
|
|
@@ -14,6 +14,7 @@ Start by understanding the current project context, then ask questions one at a
|
|
|
14
14
|
## The Process
|
|
15
15
|
|
|
16
16
|
**Understanding the idea:**
|
|
17
|
+
|
|
17
18
|
- Check out the current project state first (files, docs, recent commits)
|
|
18
19
|
- Ask questions one at a time to refine the idea
|
|
19
20
|
- Prefer multiple choice questions when possible, but open-ended is fine too
|
|
@@ -21,11 +22,13 @@ Start by understanding the current project context, then ask questions one at a
|
|
|
21
22
|
- Focus on understanding: purpose, constraints, success criteria
|
|
22
23
|
|
|
23
24
|
**Exploring approaches:**
|
|
25
|
+
|
|
24
26
|
- Propose 2-3 different approaches with trade-offs
|
|
25
27
|
- Present options conversationally with your recommendation and reasoning
|
|
26
28
|
- Lead with your recommended option and explain why
|
|
27
29
|
|
|
28
30
|
**Presenting the design:**
|
|
31
|
+
|
|
29
32
|
- Once you believe you understand what you're building, present the design
|
|
30
33
|
- Break it into sections of 200-300 words
|
|
31
34
|
- Ask after each section whether it looks right so far
|
|
@@ -35,11 +38,13 @@ Start by understanding the current project context, then ask questions one at a
|
|
|
35
38
|
## After the Design
|
|
36
39
|
|
|
37
40
|
**Documentation:**
|
|
38
|
-
|
|
41
|
+
|
|
42
|
+
- Write the validated design to `.beads/artifacts/<bead-id>/design.md` using template from `.opencode/memory/_templates/task-design.md`
|
|
39
43
|
- Use elements-of-style:writing-clearly-and-concisely skill if available
|
|
40
44
|
- Commit the design document to git
|
|
41
45
|
|
|
42
46
|
**Implementation (if continuing):**
|
|
47
|
+
|
|
43
48
|
- Ask: "Ready to set up for implementation?"
|
|
44
49
|
- Use superpowers:using-git-worktrees to create isolated workspace
|
|
45
50
|
- Use superpowers:writing-plans to create detailed implementation plan
|
|
@@ -20,6 +20,7 @@ Assume they are a skilled developer, but know almost nothing about our toolset o
|
|
|
20
20
|
## Bite-Sized Task Granularity
|
|
21
21
|
|
|
22
22
|
**Each step is one action (2-5 minutes):**
|
|
23
|
+
|
|
23
24
|
- "Write the failing test" - step
|
|
24
25
|
- "Run it to make sure it fails" - step
|
|
25
26
|
- "Implement the minimal code to make the test pass" - step
|
|
@@ -46,10 +47,11 @@ Assume they are a skilled developer, but know almost nothing about our toolset o
|
|
|
46
47
|
|
|
47
48
|
## Task Structure
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
````markdown
|
|
50
51
|
### Task N: [Component Name]
|
|
51
52
|
|
|
52
53
|
**Files:**
|
|
54
|
+
|
|
53
55
|
- Create: `exact/path/to/file.py`
|
|
54
56
|
- Modify: `exact/path/to/existing.py:123-145`
|
|
55
57
|
- Test: `tests/exact/path/to/test.py`
|
|
@@ -61,6 +63,7 @@ def test_specific_behavior():
|
|
|
61
63
|
result = function(input)
|
|
62
64
|
assert result == expected
|
|
63
65
|
```
|
|
66
|
+
````
|
|
64
67
|
|
|
65
68
|
**Step 2: Run test to verify it fails**
|
|
66
69
|
|
|
@@ -85,6 +88,7 @@ Expected: PASS
|
|
|
85
88
|
git add tests/path/test.py src/path/file.py
|
|
86
89
|
git commit -m "feat: add specific feature"
|
|
87
90
|
```
|
|
91
|
+
|
|
88
92
|
```
|
|
89
93
|
|
|
90
94
|
## Remember
|
|
@@ -98,7 +102,7 @@ git commit -m "feat: add specific feature"
|
|
|
98
102
|
|
|
99
103
|
After saving the plan, offer execution choice:
|
|
100
104
|
|
|
101
|
-
**"Plan complete and saved to
|
|
105
|
+
**"Plan complete and saved to `.beads/artifacts/<bead-id>/plan.md`. Two execution options:**
|
|
102
106
|
|
|
103
107
|
**1. Subagent-Driven (this session)** - I dispatch fresh subagent per task, review between tasks, fast iteration
|
|
104
108
|
|
|
@@ -114,3 +118,4 @@ After saving the plan, offer execution choice:
|
|
|
114
118
|
**If Parallel Session chosen:**
|
|
115
119
|
- Guide them to open new session in worktree
|
|
116
120
|
- **REQUIRED SUB-SKILL:** New session uses superpowers:executing-plans
|
|
121
|
+
```
|