opencodekit 0.6.6 → 0.7.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 +656 -651
- package/dist/template/.opencode/AGENTS.md +56 -11
- package/dist/template/.opencode/README.md +18 -16
- package/dist/template/.opencode/command/accessibility-check.md +1 -1
- package/dist/template/.opencode/command/analyze-mockup.md +1 -1
- package/dist/template/.opencode/command/analyze-project.md +2 -0
- package/dist/template/.opencode/command/brainstorm.md +1 -1
- package/dist/template/.opencode/command/commit.md +1 -1
- package/dist/template/.opencode/command/create.md +9 -0
- 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 +17 -0
- package/dist/template/.opencode/command/fix-ci.md +4 -0
- package/dist/template/.opencode/command/fix-types.md +2 -0
- package/dist/template/.opencode/command/fix-ui.md +1 -1
- package/dist/template/.opencode/command/fix.md +1 -1
- package/dist/template/.opencode/command/handoff.md +2 -0
- package/dist/template/.opencode/command/implement.md +31 -1
- package/dist/template/.opencode/command/import-plan.md +2 -0
- package/dist/template/.opencode/command/integration-test.md +6 -2
- package/dist/template/.opencode/command/new-feature.md +2 -0
- package/dist/template/.opencode/command/plan.md +2 -0
- package/dist/template/.opencode/command/pr.md +2 -0
- package/dist/template/.opencode/command/research-and-implement.md +1 -1
- package/dist/template/.opencode/command/research-ui.md +1 -1
- package/dist/template/.opencode/command/resume.md +2 -0
- package/dist/template/.opencode/command/revert-feature.md +2 -0
- package/dist/template/.opencode/command/review-codebase.md +1 -1
- package/dist/template/.opencode/command/skill-create.md +4 -4
- package/dist/template/.opencode/command/skill-optimize.md +4 -4
- package/dist/template/.opencode/command/ui-review.md +2 -2
- package/dist/template/.opencode/opencode.json +490 -535
- package/dist/template/.opencode/package.json +20 -20
- package/dist/template/.opencode/skill/brainstorming/SKILL.md +2 -2
- package/dist/template/.opencode/skill/executing-plans/SKILL.md +1 -1
- package/dist/template/.opencode/skill/sharing-skills/SKILL.md +13 -4
- package/dist/template/.opencode/skill/subagent-driven-development/SKILL.md +1 -1
- package/dist/template/.opencode/skill/systematic-debugging/SKILL.md +2 -2
- package/dist/template/.opencode/skill/using-git-worktrees/SKILL.md +27 -18
- package/dist/template/.opencode/skill/{using-superpowers → using-skills}/SKILL.md +6 -3
- package/dist/template/.opencode/skill/writing-plans/SKILL.md +3 -3
- package/dist/template/.opencode/skill/writing-skills/SKILL.md +2 -2
- package/package.json +2 -1
- package/dist/template/.opencode/memory/handoffs/2025-12-27T103000Z.md +0 -76
- package/dist/template/.opencode/plugin/skill.ts +0 -275
- package/dist/template/.opencode/skill/systematic-debugging/CREATION-LOG.md +0 -119
- package/dist/template/.opencode/skill/systematic-debugging/test-academic.md +0 -14
- package/dist/template/.opencode/skill/systematic-debugging/test-pressure-1.md +0 -58
- package/dist/template/.opencode/skill/systematic-debugging/test-pressure-2.md +0 -68
- package/dist/template/.opencode/skill/systematic-debugging/test-pressure-3.md +0 -69
- package/dist/template/.opencode/skill/testing-skills-with-subagents/examples/CLAUDE_MD_TESTING.md +0 -189
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.
|
|
753
|
+
version: "0.7.0",
|
|
754
754
|
description: "CLI tool for bootstrapping and managing OpenCodeKit projects",
|
|
755
755
|
type: "module",
|
|
756
756
|
repository: {
|
|
@@ -785,6 +785,7 @@ var package_default = {
|
|
|
785
785
|
dependencies: {
|
|
786
786
|
"@clack/prompts": "^0.7.0",
|
|
787
787
|
"@opencode-ai/plugin": "^1.0.141",
|
|
788
|
+
"beads-village": "^1.3.3",
|
|
788
789
|
cac: "^6.7.14",
|
|
789
790
|
"cli-table3": "^0.6.5",
|
|
790
791
|
ora: "^9.0.0",
|
|
@@ -801,16 +802,16 @@ var package_default = {
|
|
|
801
802
|
trustedDependencies: ["@beads/bd"]
|
|
802
803
|
};
|
|
803
804
|
|
|
804
|
-
// src/commands/
|
|
805
|
+
// src/commands/agent.ts
|
|
805
806
|
import {
|
|
806
807
|
existsSync,
|
|
808
|
+
lstatSync,
|
|
807
809
|
mkdirSync,
|
|
808
810
|
readFileSync,
|
|
809
|
-
|
|
810
|
-
|
|
811
|
+
readdirSync,
|
|
812
|
+
writeFileSync
|
|
811
813
|
} from "node:fs";
|
|
812
|
-
import { join
|
|
813
|
-
import { fileURLToPath } from "node:url";
|
|
814
|
+
import { join } from "node:path";
|
|
814
815
|
|
|
815
816
|
// node_modules/@clack/core/dist/index.mjs
|
|
816
817
|
var import_sisteransi = __toESM(require_src(), 1);
|
|
@@ -1404,149 +1405,16 @@ function me() {
|
|
|
1404
1405
|
return new RegExp(r2, "g");
|
|
1405
1406
|
}
|
|
1406
1407
|
|
|
1407
|
-
// src/commands/init.ts
|
|
1408
|
-
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
1409
|
-
var EXCLUDED_DIRS = [
|
|
1410
|
-
"node_modules",
|
|
1411
|
-
".git",
|
|
1412
|
-
"dist",
|
|
1413
|
-
".DS_Store",
|
|
1414
|
-
"coverage",
|
|
1415
|
-
".next",
|
|
1416
|
-
".turbo"
|
|
1417
|
-
];
|
|
1418
|
-
var EXCLUDED_FILES = [
|
|
1419
|
-
"bun.lock",
|
|
1420
|
-
"package-lock.json",
|
|
1421
|
-
"yarn.lock",
|
|
1422
|
-
"pnpm-lock.yaml"
|
|
1423
|
-
];
|
|
1424
|
-
function detectMode(targetDir) {
|
|
1425
|
-
const opencodeDir = join(targetDir, ".opencode");
|
|
1426
|
-
if (existsSync(opencodeDir)) {
|
|
1427
|
-
return "already-initialized";
|
|
1428
|
-
}
|
|
1429
|
-
if (existsSync(targetDir)) {
|
|
1430
|
-
const entries = readdirSync(targetDir);
|
|
1431
|
-
const hasCode = entries.some((e2) => !e2.startsWith(".") && !EXCLUDED_DIRS.includes(e2) && e2 !== "node_modules");
|
|
1432
|
-
if (hasCode) {
|
|
1433
|
-
return "add-config";
|
|
1434
|
-
}
|
|
1435
|
-
}
|
|
1436
|
-
return "scaffold";
|
|
1437
|
-
}
|
|
1438
|
-
function getTemplateRoot() {
|
|
1439
|
-
const __filename2 = fileURLToPath(import.meta.url);
|
|
1440
|
-
const __dirname2 = dirname(__filename2);
|
|
1441
|
-
const possiblePaths = [
|
|
1442
|
-
join(__dirname2, "template"),
|
|
1443
|
-
join(__dirname2, "..", "..", ".opencode")
|
|
1444
|
-
];
|
|
1445
|
-
for (const path of possiblePaths) {
|
|
1446
|
-
const opencodeDir = join(path, ".opencode");
|
|
1447
|
-
if (existsSync(opencodeDir)) {
|
|
1448
|
-
return path;
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
|
-
return null;
|
|
1452
|
-
}
|
|
1453
|
-
async function copyDir(src, dest) {
|
|
1454
|
-
const { mkdir, readdir } = await import("node:fs/promises");
|
|
1455
|
-
await mkdir(dest, { recursive: true });
|
|
1456
|
-
for (const entry of await readdir(src, { withFileTypes: true })) {
|
|
1457
|
-
if (EXCLUDED_DIRS.includes(entry.name))
|
|
1458
|
-
continue;
|
|
1459
|
-
if (!entry.isDirectory() && EXCLUDED_FILES.includes(entry.name))
|
|
1460
|
-
continue;
|
|
1461
|
-
const srcPath = join(src, entry.name);
|
|
1462
|
-
const destPath = join(dest, entry.name);
|
|
1463
|
-
if (entry.isSymbolicLink()) {
|
|
1464
|
-
continue;
|
|
1465
|
-
} else if (entry.isDirectory()) {
|
|
1466
|
-
await copyDir(srcPath, destPath);
|
|
1467
|
-
} else {
|
|
1468
|
-
const content = readFileSync(srcPath, "utf-8");
|
|
1469
|
-
writeFileSync(destPath, content);
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
}
|
|
1473
|
-
async function copyOpenCodeOnly(templateRoot, targetDir) {
|
|
1474
|
-
const opencodeSrc = join(templateRoot, ".opencode");
|
|
1475
|
-
const opencodeDest = join(targetDir, ".opencode");
|
|
1476
|
-
if (!existsSync(opencodeSrc)) {
|
|
1477
|
-
return false;
|
|
1478
|
-
}
|
|
1479
|
-
await copyDir(opencodeSrc, opencodeDest);
|
|
1480
|
-
return true;
|
|
1481
|
-
}
|
|
1482
|
-
async function initCommand(options = {}) {
|
|
1483
|
-
const targetDir = process.cwd();
|
|
1484
|
-
const mode = detectMode(targetDir);
|
|
1485
|
-
oe(import_picocolors3.default.bgCyan(import_picocolors3.default.black(" OpenCodeKit ")));
|
|
1486
|
-
if (mode === "already-initialized" && !options.force) {
|
|
1487
|
-
f2.warn("Already initialized (.opencode/ exists)");
|
|
1488
|
-
f2.info(`Use ${import_picocolors3.default.cyan("--force")} to reinitialize`);
|
|
1489
|
-
$e("Nothing to do");
|
|
1490
|
-
return;
|
|
1491
|
-
}
|
|
1492
|
-
const templateRoot = getTemplateRoot();
|
|
1493
|
-
if (!templateRoot) {
|
|
1494
|
-
f2.error("Template not found. Please reinstall opencodekit.");
|
|
1495
|
-
$e(import_picocolors3.default.red("Failed"));
|
|
1496
|
-
process.exit(1);
|
|
1497
|
-
}
|
|
1498
|
-
let projectName = basename(targetDir);
|
|
1499
|
-
if (mode === "scaffold") {
|
|
1500
|
-
const name = await te({
|
|
1501
|
-
message: "Project name",
|
|
1502
|
-
placeholder: projectName,
|
|
1503
|
-
defaultValue: projectName
|
|
1504
|
-
});
|
|
1505
|
-
if (lD(name)) {
|
|
1506
|
-
ue("Cancelled");
|
|
1507
|
-
process.exit(0);
|
|
1508
|
-
}
|
|
1509
|
-
projectName = name || projectName;
|
|
1510
|
-
}
|
|
1511
|
-
const s = de();
|
|
1512
|
-
if (mode === "scaffold") {
|
|
1513
|
-
s.start("Scaffolding project");
|
|
1514
|
-
mkdirSync(targetDir, { recursive: true });
|
|
1515
|
-
} else if (mode === "add-config") {
|
|
1516
|
-
s.start("Adding OpenCodeKit");
|
|
1517
|
-
} else {
|
|
1518
|
-
s.start("Reinitializing");
|
|
1519
|
-
}
|
|
1520
|
-
const success = await copyOpenCodeOnly(templateRoot, targetDir);
|
|
1521
|
-
if (!success) {
|
|
1522
|
-
s.stop("Failed");
|
|
1523
|
-
$e(import_picocolors3.default.red("Template copy failed"));
|
|
1524
|
-
process.exit(1);
|
|
1525
|
-
}
|
|
1526
|
-
s.stop("Done");
|
|
1527
|
-
le(`cd .opencode && bun install`, "Next steps");
|
|
1528
|
-
$e(import_picocolors3.default.green("Ready to code!"));
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
1408
|
// src/commands/agent.ts
|
|
1532
|
-
|
|
1533
|
-
existsSync as existsSync2,
|
|
1534
|
-
lstatSync,
|
|
1535
|
-
mkdirSync as mkdirSync2,
|
|
1536
|
-
readFileSync as readFileSync2,
|
|
1537
|
-
readdirSync as readdirSync2,
|
|
1538
|
-
writeFileSync as writeFileSync2
|
|
1539
|
-
} from "node:fs";
|
|
1540
|
-
import { join as join2 } from "node:path";
|
|
1541
|
-
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
1409
|
+
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
1542
1410
|
|
|
1543
1411
|
// src/utils/errors.ts
|
|
1544
|
-
var
|
|
1412
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
1545
1413
|
function showError(message, fix) {
|
|
1546
1414
|
console.log();
|
|
1547
|
-
f2.error(
|
|
1415
|
+
f2.error(import_picocolors3.default.red("✗") + " " + message);
|
|
1548
1416
|
if (fix) {
|
|
1549
|
-
f2.info(" " +
|
|
1417
|
+
f2.info(" " + import_picocolors3.default.dim("→ " + fix));
|
|
1550
1418
|
}
|
|
1551
1419
|
console.log();
|
|
1552
1420
|
}
|
|
@@ -1561,18 +1429,18 @@ function alreadyExists(resource, name) {
|
|
|
1561
1429
|
showError(`${resource} "${name}" already exists`);
|
|
1562
1430
|
}
|
|
1563
1431
|
function unknownAction(action, available) {
|
|
1564
|
-
showError(`Unknown action: ${action}`, `Available: ${available.map((a3) =>
|
|
1432
|
+
showError(`Unknown action: ${action}`, `Available: ${available.map((a3) => import_picocolors3.default.cyan(a3)).join(", ")}`);
|
|
1565
1433
|
}
|
|
1566
1434
|
function showWarning(message, suggestion) {
|
|
1567
|
-
f2.warn(
|
|
1435
|
+
f2.warn(import_picocolors3.default.yellow("!") + " " + message);
|
|
1568
1436
|
if (suggestion) {
|
|
1569
|
-
f2.info(" " +
|
|
1437
|
+
f2.info(" " + import_picocolors3.default.dim("→ " + suggestion));
|
|
1570
1438
|
}
|
|
1571
1439
|
}
|
|
1572
1440
|
function showEmpty(resource, createCmd) {
|
|
1573
|
-
f2.info(
|
|
1441
|
+
f2.info(import_picocolors3.default.dim(`No ${resource} found`));
|
|
1574
1442
|
if (createCmd) {
|
|
1575
|
-
f2.info(
|
|
1443
|
+
f2.info(import_picocolors3.default.dim(`→ Run: ${import_picocolors3.default.cyan(createCmd)}`));
|
|
1576
1444
|
}
|
|
1577
1445
|
}
|
|
1578
1446
|
|
|
@@ -1590,12 +1458,12 @@ Describe what this agent does.
|
|
|
1590
1458
|
Provide specific instructions for this agent.
|
|
1591
1459
|
`;
|
|
1592
1460
|
async function agentCommand(action) {
|
|
1593
|
-
const opencodePath =
|
|
1594
|
-
if (!
|
|
1461
|
+
const opencodePath = join(process.cwd(), ".opencode");
|
|
1462
|
+
if (!existsSync(opencodePath)) {
|
|
1595
1463
|
notInitialized();
|
|
1596
1464
|
return;
|
|
1597
1465
|
}
|
|
1598
|
-
const agentPath =
|
|
1466
|
+
const agentPath = join(opencodePath, "agent");
|
|
1599
1467
|
switch (action) {
|
|
1600
1468
|
case "list":
|
|
1601
1469
|
await listAgents(agentPath);
|
|
@@ -1613,37 +1481,37 @@ async function agentCommand(action) {
|
|
|
1613
1481
|
}
|
|
1614
1482
|
}
|
|
1615
1483
|
async function listAgents(agentPath) {
|
|
1616
|
-
if (!
|
|
1484
|
+
if (!existsSync(agentPath)) {
|
|
1617
1485
|
showEmpty("agents", "ock agent add");
|
|
1618
1486
|
return;
|
|
1619
1487
|
}
|
|
1620
|
-
const opencodePath =
|
|
1621
|
-
const configPath =
|
|
1488
|
+
const opencodePath = join(process.cwd(), ".opencode");
|
|
1489
|
+
const configPath = join(opencodePath, "opencode.json");
|
|
1622
1490
|
let agentConfigs = {};
|
|
1623
|
-
if (
|
|
1491
|
+
if (existsSync(configPath)) {
|
|
1624
1492
|
try {
|
|
1625
|
-
const configContent =
|
|
1493
|
+
const configContent = readFileSync(configPath, "utf-8");
|
|
1626
1494
|
const config = JSON.parse(configContent);
|
|
1627
1495
|
agentConfigs = config.agent || {};
|
|
1628
1496
|
} catch {}
|
|
1629
1497
|
}
|
|
1630
|
-
const entries =
|
|
1498
|
+
const entries = readdirSync(agentPath);
|
|
1631
1499
|
const agents = entries.filter((entry) => {
|
|
1632
|
-
const entryPath =
|
|
1500
|
+
const entryPath = join(agentPath, entry);
|
|
1633
1501
|
return lstatSync(entryPath).isFile() && entry.endsWith(".md");
|
|
1634
1502
|
}).map((file) => file.replace(".md", ""));
|
|
1635
1503
|
if (agents.length === 0) {
|
|
1636
1504
|
showEmpty("agents", "ock agent add");
|
|
1637
1505
|
return;
|
|
1638
1506
|
}
|
|
1639
|
-
f2.info(
|
|
1507
|
+
f2.info(import_picocolors4.default.bold("Agents"));
|
|
1640
1508
|
for (const agent of agents) {
|
|
1641
1509
|
let model = agentConfigs[agent]?.model;
|
|
1642
1510
|
const disabled = agentConfigs[agent]?.disable;
|
|
1643
1511
|
if (!model) {
|
|
1644
|
-
const agentFile =
|
|
1512
|
+
const agentFile = join(agentPath, `${agent}.md`);
|
|
1645
1513
|
try {
|
|
1646
|
-
const content =
|
|
1514
|
+
const content = readFileSync(agentFile, "utf-8");
|
|
1647
1515
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
1648
1516
|
if (frontmatterMatch) {
|
|
1649
1517
|
const modelMatch = frontmatterMatch[1].match(/^model:\s*(.+)$/m);
|
|
@@ -1653,13 +1521,13 @@ async function listAgents(agentPath) {
|
|
|
1653
1521
|
}
|
|
1654
1522
|
} catch {}
|
|
1655
1523
|
}
|
|
1656
|
-
const modelDisplay = model ?
|
|
1657
|
-
const disabledDisplay = disabled ?
|
|
1658
|
-
console.log(` ${
|
|
1524
|
+
const modelDisplay = model ? import_picocolors4.default.dim(` → ${model}`) : import_picocolors4.default.dim(" → (default)");
|
|
1525
|
+
const disabledDisplay = disabled ? import_picocolors4.default.red(" [disabled]") : "";
|
|
1526
|
+
console.log(` ${import_picocolors4.default.cyan("•")} ${agent}${modelDisplay}${disabledDisplay}`);
|
|
1659
1527
|
}
|
|
1660
1528
|
}
|
|
1661
1529
|
async function addAgent(agentPath) {
|
|
1662
|
-
oe(
|
|
1530
|
+
oe(import_picocolors4.default.bgMagenta(import_picocolors4.default.black(" Add Agent ")));
|
|
1663
1531
|
const name = await te({
|
|
1664
1532
|
message: "Agent name",
|
|
1665
1533
|
placeholder: "e.g. reviewer, planner, researcher",
|
|
@@ -1686,18 +1554,18 @@ async function addAgent(agentPath) {
|
|
|
1686
1554
|
ue("Cancelled");
|
|
1687
1555
|
return;
|
|
1688
1556
|
}
|
|
1689
|
-
if (!
|
|
1690
|
-
|
|
1557
|
+
if (!existsSync(agentPath)) {
|
|
1558
|
+
mkdirSync(agentPath, { recursive: true });
|
|
1691
1559
|
}
|
|
1692
|
-
const agentFile =
|
|
1693
|
-
if (
|
|
1560
|
+
const agentFile = join(agentPath, `${name}.md`);
|
|
1561
|
+
if (existsSync(agentFile)) {
|
|
1694
1562
|
alreadyExists("Agent", String(name));
|
|
1695
|
-
$e(
|
|
1563
|
+
$e(import_picocolors4.default.red("Failed"));
|
|
1696
1564
|
return;
|
|
1697
1565
|
}
|
|
1698
1566
|
const content = AGENT_TEMPLATE.replace("{{NAME}}", String(name).charAt(0).toUpperCase() + String(name).slice(1));
|
|
1699
|
-
|
|
1700
|
-
f2.success(`Created ${
|
|
1567
|
+
writeFileSync(agentFile, content);
|
|
1568
|
+
f2.success(`Created ${import_picocolors4.default.cyan(`.opencode/agent/${name}.md`)}`);
|
|
1701
1569
|
if (agentType === "primary") {
|
|
1702
1570
|
le(`Add to opencode.json:
|
|
1703
1571
|
|
|
@@ -1708,17 +1576,17 @@ async function addAgent(agentPath) {
|
|
|
1708
1576
|
}
|
|
1709
1577
|
}`, "Next step");
|
|
1710
1578
|
}
|
|
1711
|
-
$e(
|
|
1579
|
+
$e(import_picocolors4.default.green("Done! Edit the file to customize."));
|
|
1712
1580
|
}
|
|
1713
1581
|
async function viewAgent(agentPath, agentName) {
|
|
1714
1582
|
if (!agentName) {
|
|
1715
|
-
if (!
|
|
1583
|
+
if (!existsSync(agentPath)) {
|
|
1716
1584
|
showEmpty("agents", "ock agent add");
|
|
1717
1585
|
return;
|
|
1718
1586
|
}
|
|
1719
|
-
const entries =
|
|
1587
|
+
const entries = readdirSync(agentPath);
|
|
1720
1588
|
const agents = entries.filter((entry) => {
|
|
1721
|
-
const entryPath =
|
|
1589
|
+
const entryPath = join(agentPath, entry);
|
|
1722
1590
|
return lstatSync(entryPath).isFile() && entry.endsWith(".md");
|
|
1723
1591
|
}).map((file) => file.replace(".md", ""));
|
|
1724
1592
|
if (agents.length === 0) {
|
|
@@ -1734,181 +1602,214 @@ async function viewAgent(agentPath, agentName) {
|
|
|
1734
1602
|
}
|
|
1735
1603
|
agentName = selected;
|
|
1736
1604
|
}
|
|
1737
|
-
const agentFile =
|
|
1738
|
-
if (!
|
|
1605
|
+
const agentFile = join(agentPath, `${agentName}.md`);
|
|
1606
|
+
if (!existsSync(agentFile)) {
|
|
1739
1607
|
notFound("Agent", agentName);
|
|
1740
1608
|
return;
|
|
1741
1609
|
}
|
|
1742
|
-
const content =
|
|
1610
|
+
const content = readFileSync(agentFile, "utf-8");
|
|
1743
1611
|
console.log();
|
|
1744
|
-
console.log(
|
|
1612
|
+
console.log(import_picocolors4.default.dim("─".repeat(40)));
|
|
1745
1613
|
console.log(content);
|
|
1746
|
-
console.log(
|
|
1614
|
+
console.log(import_picocolors4.default.dim("─".repeat(40)));
|
|
1747
1615
|
}
|
|
1748
1616
|
|
|
1749
|
-
// src/commands/
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
case "
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
}
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
if (lstatSync2(entryPath).isDirectory()) {
|
|
1789
|
-
skills.push({ name: entry, path: entryPath, tier });
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
}
|
|
1794
|
-
if (!hasTiers) {
|
|
1795
|
-
const entries = readdirSync3(basePath);
|
|
1796
|
-
for (const entry of entries) {
|
|
1797
|
-
const entryPath = join3(basePath, entry);
|
|
1798
|
-
if (lstatSync2(entryPath).isDirectory()) {
|
|
1799
|
-
skills.push({ name: entry, path: entryPath });
|
|
1800
|
-
}
|
|
1801
|
-
}
|
|
1802
|
-
}
|
|
1803
|
-
return skills;
|
|
1804
|
-
}
|
|
1805
|
-
async function listSkills(opencodePath) {
|
|
1806
|
-
const locations = [
|
|
1807
|
-
{ path: join3(opencodePath, "superpowers", "skills"), name: "Superpowers" },
|
|
1808
|
-
{ path: join3(opencodePath, "skills"), name: "Project" }
|
|
1809
|
-
];
|
|
1810
|
-
let totalSkills = 0;
|
|
1811
|
-
for (const loc of locations) {
|
|
1812
|
-
const skills = collectSkills(loc.path);
|
|
1813
|
-
if (skills.length > 0) {
|
|
1814
|
-
f2.info(import_picocolors6.default.bold(loc.name));
|
|
1815
|
-
for (const skill of skills) {
|
|
1816
|
-
const label = skill.tier ? `${skill.tier}/${skill.name}` : skill.name;
|
|
1817
|
-
console.log(` ${import_picocolors6.default.cyan("•")} ${label}`);
|
|
1818
|
-
}
|
|
1819
|
-
totalSkills += skills.length;
|
|
1820
|
-
}
|
|
1821
|
-
}
|
|
1822
|
-
if (totalSkills === 0) {
|
|
1823
|
-
showEmpty("skills", "ock skill add");
|
|
1824
|
-
}
|
|
1617
|
+
// src/commands/completion.ts
|
|
1618
|
+
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
1619
|
+
var BASH_COMPLETION = `# ock bash completion
|
|
1620
|
+
_ock_completion() {
|
|
1621
|
+
local cur prev commands
|
|
1622
|
+
COMPREPLY=()
|
|
1623
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
1624
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
1625
|
+
|
|
1626
|
+
commands="init config upgrade agent skill doctor status help"
|
|
1627
|
+
|
|
1628
|
+
case "\${prev}" in
|
|
1629
|
+
ock)
|
|
1630
|
+
COMPREPLY=( $(compgen -W "\${commands}" -- "\${cur}") )
|
|
1631
|
+
return 0
|
|
1632
|
+
;;
|
|
1633
|
+
agent)
|
|
1634
|
+
COMPREPLY=( $(compgen -W "list add view" -- "\${cur}") )
|
|
1635
|
+
return 0
|
|
1636
|
+
;;
|
|
1637
|
+
skill)
|
|
1638
|
+
COMPREPLY=( $(compgen -W "list add view" -- "\${cur}") )
|
|
1639
|
+
return 0
|
|
1640
|
+
;;
|
|
1641
|
+
config)
|
|
1642
|
+
COMPREPLY=( $(compgen -W "model mcp permission keybinds show" -- "\${cur}") )
|
|
1643
|
+
return 0
|
|
1644
|
+
;;
|
|
1645
|
+
init)
|
|
1646
|
+
COMPREPLY=( $(compgen -W "--force" -- "\${cur}") )
|
|
1647
|
+
return 0
|
|
1648
|
+
;;
|
|
1649
|
+
upgrade)
|
|
1650
|
+
COMPREPLY=( $(compgen -W "--force --check" -- "\${cur}") )
|
|
1651
|
+
return 0
|
|
1652
|
+
;;
|
|
1653
|
+
*)
|
|
1654
|
+
;;
|
|
1655
|
+
esac
|
|
1825
1656
|
}
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1657
|
+
complete -F _ock_completion ock
|
|
1658
|
+
`;
|
|
1659
|
+
var ZSH_COMPLETION = `#compdef ock
|
|
1660
|
+
|
|
1661
|
+
_ock() {
|
|
1662
|
+
local -a commands
|
|
1663
|
+
local -a agent_actions
|
|
1664
|
+
local -a skill_actions
|
|
1665
|
+
local -a config_actions
|
|
1666
|
+
|
|
1667
|
+
commands=(
|
|
1668
|
+
'init:Initialize OpenCodeKit in current directory'
|
|
1669
|
+
'config:Edit opencode.json'
|
|
1670
|
+
'upgrade:Update templates to latest version'
|
|
1671
|
+
'agent:Manage agents'
|
|
1672
|
+
'skill:Manage skills'
|
|
1673
|
+
'doctor:Check project health'
|
|
1674
|
+
'status:Show project overview'
|
|
1675
|
+
'help:Show help'
|
|
1676
|
+
)
|
|
1677
|
+
|
|
1678
|
+
agent_actions=(
|
|
1679
|
+
'list:List all agents'
|
|
1680
|
+
'add:Create a new agent'
|
|
1681
|
+
'view:View agent details'
|
|
1682
|
+
)
|
|
1683
|
+
|
|
1684
|
+
skill_actions=(
|
|
1685
|
+
'list:List all skills'
|
|
1686
|
+
'add:Install a skill'
|
|
1687
|
+
'view:View skill details'
|
|
1688
|
+
)
|
|
1689
|
+
|
|
1690
|
+
config_actions=(
|
|
1691
|
+
'model:Change default model'
|
|
1692
|
+
'mcp:Manage MCP servers'
|
|
1693
|
+
'permission:Edit permissions'
|
|
1694
|
+
'keybinds:Edit keyboard shortcuts'
|
|
1695
|
+
'show:View current config'
|
|
1696
|
+
)
|
|
1697
|
+
|
|
1698
|
+
case "$words[2]" in
|
|
1699
|
+
agent)
|
|
1700
|
+
_describe -t actions 'agent action' agent_actions
|
|
1701
|
+
;;
|
|
1702
|
+
skill)
|
|
1703
|
+
_describe -t actions 'skill action' skill_actions
|
|
1704
|
+
;;
|
|
1705
|
+
config)
|
|
1706
|
+
_describe -t actions 'config action' config_actions
|
|
1707
|
+
;;
|
|
1708
|
+
init)
|
|
1709
|
+
_arguments '--force[Reinitialize even if already exists]'
|
|
1710
|
+
;;
|
|
1711
|
+
upgrade)
|
|
1712
|
+
_arguments \\
|
|
1713
|
+
'--force[Force upgrade even if up to date]' \\
|
|
1714
|
+
'--check[Check for updates only]'
|
|
1715
|
+
;;
|
|
1716
|
+
*)
|
|
1717
|
+
_describe -t commands 'command' commands
|
|
1718
|
+
;;
|
|
1719
|
+
esac
|
|
1873
1720
|
}
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1721
|
+
|
|
1722
|
+
_ock "$@"
|
|
1723
|
+
`;
|
|
1724
|
+
var FISH_COMPLETION = `# ock fish completion
|
|
1725
|
+
complete -c ock -n "__fish_use_subcommand" -a "init" -d "Initialize OpenCodeKit"
|
|
1726
|
+
complete -c ock -n "__fish_use_subcommand" -a "config" -d "Edit opencode.json"
|
|
1727
|
+
complete -c ock -n "__fish_use_subcommand" -a "upgrade" -d "Update templates"
|
|
1728
|
+
complete -c ock -n "__fish_use_subcommand" -a "agent" -d "Manage agents"
|
|
1729
|
+
complete -c ock -n "__fish_use_subcommand" -a "skill" -d "Manage skills"
|
|
1730
|
+
complete -c ock -n "__fish_use_subcommand" -a "doctor" -d "Check project health"
|
|
1731
|
+
complete -c ock -n "__fish_use_subcommand" -a "status" -d "Show project overview"
|
|
1732
|
+
|
|
1733
|
+
# agent subcommands
|
|
1734
|
+
complete -c ock -n "__fish_seen_subcommand_from agent" -a "list" -d "List agents"
|
|
1735
|
+
complete -c ock -n "__fish_seen_subcommand_from agent" -a "add" -d "Add agent"
|
|
1736
|
+
complete -c ock -n "__fish_seen_subcommand_from agent" -a "view" -d "View agent"
|
|
1737
|
+
|
|
1738
|
+
# skill subcommands
|
|
1739
|
+
complete -c ock -n "__fish_seen_subcommand_from skill" -a "list" -d "List skills"
|
|
1740
|
+
complete -c ock -n "__fish_seen_subcommand_from skill" -a "add" -d "Add skill"
|
|
1741
|
+
complete -c ock -n "__fish_seen_subcommand_from skill" -a "view" -d "View skill"
|
|
1742
|
+
|
|
1743
|
+
# config subcommands
|
|
1744
|
+
complete -c ock -n "__fish_seen_subcommand_from config" -a "model" -d "Change model"
|
|
1745
|
+
complete -c ock -n "__fish_seen_subcommand_from config" -a "mcp" -d "Manage MCP"
|
|
1746
|
+
complete -c ock -n "__fish_seen_subcommand_from config" -a "permission" -d "Edit permissions"
|
|
1747
|
+
complete -c ock -n "__fish_seen_subcommand_from config" -a "keybinds" -d "Edit keybinds"
|
|
1748
|
+
complete -c ock -n "__fish_seen_subcommand_from config" -a "show" -d "View config"
|
|
1749
|
+
|
|
1750
|
+
# init options
|
|
1751
|
+
complete -c ock -n "__fish_seen_subcommand_from init" -l force -d "Reinitialize"
|
|
1752
|
+
|
|
1753
|
+
# upgrade options
|
|
1754
|
+
complete -c ock -n "__fish_seen_subcommand_from upgrade" -l force -d "Force upgrade"
|
|
1755
|
+
complete -c ock -n "__fish_seen_subcommand_from upgrade" -l check -d "Check only"
|
|
1756
|
+
`;
|
|
1757
|
+
async function completionCommand(shell) {
|
|
1758
|
+
if (!shell) {
|
|
1759
|
+
oe(import_picocolors5.default.bgCyan(import_picocolors5.default.black(" Shell Completion ")));
|
|
1882
1760
|
const selected = await ie({
|
|
1883
|
-
message: "Select
|
|
1884
|
-
options:
|
|
1761
|
+
message: "Select your shell",
|
|
1762
|
+
options: [
|
|
1763
|
+
{ value: "bash", label: "Bash" },
|
|
1764
|
+
{ value: "zsh", label: "Zsh" },
|
|
1765
|
+
{ value: "fish", label: "Fish" }
|
|
1766
|
+
]
|
|
1885
1767
|
});
|
|
1886
1768
|
if (lD(selected)) {
|
|
1769
|
+
ue("Cancelled");
|
|
1887
1770
|
return;
|
|
1888
1771
|
}
|
|
1889
|
-
|
|
1890
|
-
}
|
|
1891
|
-
const skill = skills.find((s) => s.name === skillName);
|
|
1892
|
-
if (!skill) {
|
|
1893
|
-
notFound("Skill", skillName);
|
|
1894
|
-
return;
|
|
1772
|
+
shell = selected;
|
|
1895
1773
|
}
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1774
|
+
let script;
|
|
1775
|
+
let setupInstructions;
|
|
1776
|
+
switch (shell) {
|
|
1777
|
+
case "bash":
|
|
1778
|
+
script = BASH_COMPLETION;
|
|
1779
|
+
setupInstructions = `Add to ~/.bashrc:
|
|
1780
|
+
source <(ock completion bash)
|
|
1781
|
+
|
|
1782
|
+
Or save to file:
|
|
1783
|
+
ock completion bash > ~/.local/share/bash-completion/completions/ock`;
|
|
1784
|
+
break;
|
|
1785
|
+
case "zsh":
|
|
1786
|
+
script = ZSH_COMPLETION;
|
|
1787
|
+
setupInstructions = `Add to ~/.zshrc (before compinit):
|
|
1788
|
+
source <(ock completion zsh)
|
|
1789
|
+
|
|
1790
|
+
Or save to fpath:
|
|
1791
|
+
ock completion zsh > ~/.zsh/completions/_ock
|
|
1792
|
+
# Then add to ~/.zshrc: fpath=(~/.zsh/completions $fpath)`;
|
|
1793
|
+
break;
|
|
1794
|
+
case "fish":
|
|
1795
|
+
script = FISH_COMPLETION;
|
|
1796
|
+
setupInstructions = `Save to fish completions:
|
|
1797
|
+
ock completion fish > ~/.config/fish/completions/ock.fish`;
|
|
1798
|
+
break;
|
|
1799
|
+
default:
|
|
1800
|
+
f2.error(`Unknown shell: ${shell}`);
|
|
1801
|
+
return;
|
|
1900
1802
|
}
|
|
1901
|
-
|
|
1902
|
-
console.
|
|
1903
|
-
console.
|
|
1904
|
-
console.
|
|
1905
|
-
console.log(import_picocolors6.default.dim("─".repeat(40)));
|
|
1803
|
+
console.log(script);
|
|
1804
|
+
console.error();
|
|
1805
|
+
console.error(import_picocolors5.default.bold("Setup:"));
|
|
1806
|
+
console.error(import_picocolors5.default.dim(setupInstructions));
|
|
1906
1807
|
}
|
|
1907
1808
|
|
|
1908
1809
|
// src/commands/config.ts
|
|
1909
|
-
import { existsSync as
|
|
1910
|
-
import { join as
|
|
1911
|
-
var
|
|
1810
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1811
|
+
import { join as join2 } from "node:path";
|
|
1812
|
+
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
1912
1813
|
var DEFAULT_SERVER_PORT = 4096;
|
|
1913
1814
|
var MODELS_DEV_URL = "https://models.dev/api.json";
|
|
1914
1815
|
async function fetchFromServer(endpoint) {
|
|
@@ -1938,13 +1839,13 @@ async function getAgentsFromServer() {
|
|
|
1938
1839
|
return fetchFromServer("/agent");
|
|
1939
1840
|
}
|
|
1940
1841
|
async function configCommand(action) {
|
|
1941
|
-
const opencodePath =
|
|
1942
|
-
const configPath =
|
|
1943
|
-
if (!
|
|
1842
|
+
const opencodePath = join2(process.cwd(), ".opencode");
|
|
1843
|
+
const configPath = join2(opencodePath, "opencode.json");
|
|
1844
|
+
if (!existsSync2(opencodePath)) {
|
|
1944
1845
|
notInitialized();
|
|
1945
1846
|
return;
|
|
1946
1847
|
}
|
|
1947
|
-
if (!
|
|
1848
|
+
if (!existsSync2(configPath)) {
|
|
1948
1849
|
showError("opencode.json not found", "ock init --force");
|
|
1949
1850
|
return;
|
|
1950
1851
|
}
|
|
@@ -1999,64 +1900,66 @@ async function configCommand(action) {
|
|
|
1999
1900
|
}
|
|
2000
1901
|
}
|
|
2001
1902
|
function loadConfig(configPath) {
|
|
2002
|
-
|
|
1903
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
1904
|
+
const jsonWithoutComments = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
|
|
1905
|
+
return JSON.parse(jsonWithoutComments);
|
|
2003
1906
|
}
|
|
2004
1907
|
function saveConfig(configPath, config) {
|
|
2005
|
-
|
|
1908
|
+
writeFileSync2(configPath, JSON.stringify(config, null, 2) + `
|
|
2006
1909
|
`);
|
|
2007
1910
|
}
|
|
2008
1911
|
function showConfig(configPath) {
|
|
2009
1912
|
const config = loadConfig(configPath);
|
|
2010
1913
|
console.log();
|
|
2011
|
-
console.log(
|
|
2012
|
-
console.log(` ${
|
|
1914
|
+
console.log(import_picocolors6.default.bold(" Model"));
|
|
1915
|
+
console.log(` ${import_picocolors6.default.cyan(config.model || "not set")}`);
|
|
2013
1916
|
if (config.small_model) {
|
|
2014
|
-
console.log(
|
|
2015
|
-
console.log(` ${
|
|
1917
|
+
console.log(import_picocolors6.default.bold(" Small Model"));
|
|
1918
|
+
console.log(` ${import_picocolors6.default.cyan(config.small_model)}`);
|
|
2016
1919
|
}
|
|
2017
|
-
console.log(
|
|
2018
|
-
console.log(` ${
|
|
2019
|
-
console.log(
|
|
2020
|
-
console.log(` ${
|
|
1920
|
+
console.log(import_picocolors6.default.bold(" Theme"));
|
|
1921
|
+
console.log(` ${import_picocolors6.default.cyan(config.theme || "system")}`);
|
|
1922
|
+
console.log(import_picocolors6.default.bold(" Share"));
|
|
1923
|
+
console.log(` ${import_picocolors6.default.cyan(config.share || "manual")}`);
|
|
2021
1924
|
const autoupdateDisplay = config.autoupdate === "notify" ? "notify" : config.autoupdate === false ? "disabled" : "enabled";
|
|
2022
|
-
console.log(
|
|
2023
|
-
console.log(` ${
|
|
1925
|
+
console.log(import_picocolors6.default.bold(" Autoupdate"));
|
|
1926
|
+
console.log(` ${import_picocolors6.default.cyan(autoupdateDisplay)}`);
|
|
2024
1927
|
if (config.tui && Object.keys(config.tui).length > 0) {
|
|
2025
|
-
console.log(
|
|
1928
|
+
console.log(import_picocolors6.default.bold(" TUI"));
|
|
2026
1929
|
if (config.tui.scroll_speed !== undefined) {
|
|
2027
|
-
console.log(` scroll_speed: ${
|
|
1930
|
+
console.log(` scroll_speed: ${import_picocolors6.default.cyan(String(config.tui.scroll_speed))}`);
|
|
2028
1931
|
}
|
|
2029
1932
|
if (config.tui.scroll_acceleration !== undefined) {
|
|
2030
|
-
console.log(` scroll_acceleration: ${
|
|
1933
|
+
console.log(` scroll_acceleration: ${import_picocolors6.default.cyan(String(config.tui.scroll_acceleration))}`);
|
|
2031
1934
|
}
|
|
2032
1935
|
if (config.tui.diff_style) {
|
|
2033
|
-
console.log(` diff_style: ${
|
|
1936
|
+
console.log(` diff_style: ${import_picocolors6.default.cyan(config.tui.diff_style)}`);
|
|
2034
1937
|
}
|
|
2035
1938
|
}
|
|
2036
1939
|
if (config.mcp && Object.keys(config.mcp).length > 0) {
|
|
2037
|
-
console.log(
|
|
1940
|
+
console.log(import_picocolors6.default.bold(" MCP Servers"));
|
|
2038
1941
|
for (const [name, server] of Object.entries(config.mcp)) {
|
|
2039
|
-
const status = server.enabled === false ?
|
|
1942
|
+
const status = server.enabled === false ? import_picocolors6.default.dim("off") : import_picocolors6.default.green("on");
|
|
2040
1943
|
console.log(` ${status} ${name}`);
|
|
2041
1944
|
}
|
|
2042
1945
|
}
|
|
2043
1946
|
if (config.tools && Object.keys(config.tools).length > 0) {
|
|
2044
|
-
console.log(
|
|
1947
|
+
console.log(import_picocolors6.default.bold(" Tools"));
|
|
2045
1948
|
for (const [tool, enabled] of Object.entries(config.tools)) {
|
|
2046
|
-
const status = enabled === false ?
|
|
1949
|
+
const status = enabled === false ? import_picocolors6.default.red("off") : import_picocolors6.default.green("on");
|
|
2047
1950
|
console.log(` ${status} ${tool}`);
|
|
2048
1951
|
}
|
|
2049
1952
|
}
|
|
2050
1953
|
if (config.keybinds && Object.keys(config.keybinds).length > 0) {
|
|
2051
|
-
console.log(
|
|
1954
|
+
console.log(import_picocolors6.default.bold(" Keybinds"));
|
|
2052
1955
|
for (const [action, key] of Object.entries(config.keybinds)) {
|
|
2053
|
-
console.log(` ${
|
|
1956
|
+
console.log(` ${import_picocolors6.default.dim(action)}: ${import_picocolors6.default.cyan(key)}`);
|
|
2054
1957
|
}
|
|
2055
1958
|
}
|
|
2056
1959
|
console.log();
|
|
2057
1960
|
}
|
|
2058
1961
|
async function configMenu(configPath) {
|
|
2059
|
-
oe(
|
|
1962
|
+
oe(import_picocolors6.default.bgCyan(import_picocolors6.default.black(" Configuration ")));
|
|
2060
1963
|
while (true) {
|
|
2061
1964
|
const action = await ie({
|
|
2062
1965
|
message: "What do you want to configure?",
|
|
@@ -2131,8 +2034,8 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2131
2034
|
const config = loadConfig(configPath);
|
|
2132
2035
|
const currentModel = config[modelType] || "not set";
|
|
2133
2036
|
const modelLabel = modelType === "small_model" ? "Small Model" : "Model";
|
|
2134
|
-
f2.info(`Current ${modelLabel}: ${
|
|
2135
|
-
f2.info(
|
|
2037
|
+
f2.info(`Current ${modelLabel}: ${import_picocolors6.default.cyan(currentModel)}`);
|
|
2038
|
+
f2.info(import_picocolors6.default.dim("Fetching models from models.dev..."));
|
|
2136
2039
|
const modelsDevData = await fetchFromModelsDev();
|
|
2137
2040
|
if (!modelsDevData || Object.keys(modelsDevData).length === 0) {
|
|
2138
2041
|
f2.warn("models.dev unavailable - please enter manually");
|
|
@@ -2153,7 +2056,7 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2153
2056
|
}
|
|
2154
2057
|
config[modelType] = newModel;
|
|
2155
2058
|
saveConfig(configPath, config);
|
|
2156
|
-
f2.success(`${modelLabel} set to ${
|
|
2059
|
+
f2.success(`${modelLabel} set to ${import_picocolors6.default.cyan(newModel)}`);
|
|
2157
2060
|
return;
|
|
2158
2061
|
}
|
|
2159
2062
|
f2.success("Fetched models from models.dev");
|
|
@@ -2216,7 +2119,7 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2216
2119
|
}
|
|
2217
2120
|
config[modelType] = customModel;
|
|
2218
2121
|
saveConfig(configPath, config);
|
|
2219
|
-
f2.success(`${modelLabel} set to ${
|
|
2122
|
+
f2.success(`${modelLabel} set to ${import_picocolors6.default.cyan(customModel)}`);
|
|
2220
2123
|
return;
|
|
2221
2124
|
}
|
|
2222
2125
|
if (providerId === "__search__") {
|
|
@@ -2281,7 +2184,7 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2281
2184
|
const fullModelId = `${providerId}/${selectedModel}`;
|
|
2282
2185
|
config[modelType] = fullModelId;
|
|
2283
2186
|
saveConfig(configPath, config);
|
|
2284
|
-
f2.success(`${modelLabel} set to ${
|
|
2187
|
+
f2.success(`${modelLabel} set to ${import_picocolors6.default.cyan(fullModelId)}`);
|
|
2285
2188
|
}
|
|
2286
2189
|
function getModelsForProvider(provider) {
|
|
2287
2190
|
const options = [];
|
|
@@ -2329,7 +2232,7 @@ async function editAgentModel(configPath) {
|
|
|
2329
2232
|
let agentNames = [];
|
|
2330
2233
|
const agentInfoMap = new Map;
|
|
2331
2234
|
if (serverAgents && serverAgents.length > 0) {
|
|
2332
|
-
f2.info(
|
|
2235
|
+
f2.info(import_picocolors6.default.dim("Fetched agents from OpenCode server"));
|
|
2333
2236
|
for (const agent of serverAgents) {
|
|
2334
2237
|
agentNames.push(agent.name);
|
|
2335
2238
|
agentInfoMap.set(agent.name, {
|
|
@@ -2353,14 +2256,14 @@ async function editAgentModel(configPath) {
|
|
|
2353
2256
|
return;
|
|
2354
2257
|
}
|
|
2355
2258
|
console.log();
|
|
2356
|
-
console.log(
|
|
2259
|
+
console.log(import_picocolors6.default.bold(" Agent Models"));
|
|
2357
2260
|
for (const name of agentNames) {
|
|
2358
2261
|
const info = agentInfoMap.get(name);
|
|
2359
|
-
const model = info?.model ||
|
|
2360
|
-
const builtIn = info?.builtIn ?
|
|
2262
|
+
const model = info?.model || import_picocolors6.default.dim("(default)");
|
|
2263
|
+
const builtIn = info?.builtIn ? import_picocolors6.default.dim(" [built-in]") : "";
|
|
2361
2264
|
const localConfig = config.agent[name];
|
|
2362
|
-
const disabled = localConfig?.disable ?
|
|
2363
|
-
console.log(` ${
|
|
2265
|
+
const disabled = localConfig?.disable ? import_picocolors6.default.red(" [disabled]") : "";
|
|
2266
|
+
console.log(` ${import_picocolors6.default.cyan(name)}: ${model}${builtIn}${disabled}`);
|
|
2364
2267
|
}
|
|
2365
2268
|
console.log();
|
|
2366
2269
|
const agentOptions = [
|
|
@@ -2408,7 +2311,7 @@ async function editAgentModel(configPath) {
|
|
|
2408
2311
|
}
|
|
2409
2312
|
config.agent[agentName].disable = !currentAgent.disable;
|
|
2410
2313
|
saveConfig(configPath, config);
|
|
2411
|
-
const status = config.agent[agentName].disable ?
|
|
2314
|
+
const status = config.agent[agentName].disable ? import_picocolors6.default.red("disabled") : import_picocolors6.default.green("enabled");
|
|
2412
2315
|
f2.success(`Agent ${agentName}: ${status}`);
|
|
2413
2316
|
return;
|
|
2414
2317
|
}
|
|
@@ -2429,8 +2332,8 @@ async function editAgentModel(configPath) {
|
|
|
2429
2332
|
return;
|
|
2430
2333
|
}
|
|
2431
2334
|
const agentInfo = agentInfoMap.get(agentName);
|
|
2432
|
-
f2.info(`Current model: ${
|
|
2433
|
-
f2.info(
|
|
2335
|
+
f2.info(`Current model: ${import_picocolors6.default.cyan(agentInfo?.model || currentAgent.model || "(default)")}`);
|
|
2336
|
+
f2.info(import_picocolors6.default.dim("Fetching models from models.dev..."));
|
|
2434
2337
|
const modelsDevData = await fetchFromModelsDev();
|
|
2435
2338
|
if (!modelsDevData || Object.keys(modelsDevData).length === 0) {
|
|
2436
2339
|
f2.warn("models.dev unavailable - please enter manually");
|
|
@@ -2452,7 +2355,7 @@ async function editAgentModel(configPath) {
|
|
|
2452
2355
|
}
|
|
2453
2356
|
config.agent[agentName].model = newModel;
|
|
2454
2357
|
saveConfig(configPath, config);
|
|
2455
|
-
f2.success(`${agentName} model set to ${
|
|
2358
|
+
f2.success(`${agentName} model set to ${import_picocolors6.default.cyan(newModel)}`);
|
|
2456
2359
|
return;
|
|
2457
2360
|
}
|
|
2458
2361
|
const localProviders = config.provider || {};
|
|
@@ -2510,7 +2413,7 @@ async function editAgentModel(configPath) {
|
|
|
2510
2413
|
agentConfig.model = undefined;
|
|
2511
2414
|
}
|
|
2512
2415
|
saveConfig(configPath, config);
|
|
2513
|
-
f2.success(`${agentName} model set to ${
|
|
2416
|
+
f2.success(`${agentName} model set to ${import_picocolors6.default.cyan("(default)")}`);
|
|
2514
2417
|
return;
|
|
2515
2418
|
}
|
|
2516
2419
|
if (providerId === "__custom__") {
|
|
@@ -2532,7 +2435,7 @@ async function editAgentModel(configPath) {
|
|
|
2532
2435
|
}
|
|
2533
2436
|
config.agent[agentName].model = customModel;
|
|
2534
2437
|
saveConfig(configPath, config);
|
|
2535
|
-
f2.success(`${agentName} model set to ${
|
|
2438
|
+
f2.success(`${agentName} model set to ${import_picocolors6.default.cyan(customModel)}`);
|
|
2536
2439
|
return;
|
|
2537
2440
|
}
|
|
2538
2441
|
if (providerId === "__search__") {
|
|
@@ -2587,7 +2490,7 @@ async function editAgentModel(configPath) {
|
|
|
2587
2490
|
}
|
|
2588
2491
|
config.agent[agentName].model = fullModelId;
|
|
2589
2492
|
saveConfig(configPath, config);
|
|
2590
|
-
f2.success(`${agentName} model set to ${
|
|
2493
|
+
f2.success(`${agentName} model set to ${import_picocolors6.default.cyan(fullModelId)}`);
|
|
2591
2494
|
}
|
|
2592
2495
|
async function editMCP(configPath) {
|
|
2593
2496
|
const config = loadConfig(configPath);
|
|
@@ -2606,11 +2509,11 @@ async function editMCP(configPath) {
|
|
|
2606
2509
|
return;
|
|
2607
2510
|
}
|
|
2608
2511
|
console.log();
|
|
2609
|
-
console.log(
|
|
2512
|
+
console.log(import_picocolors6.default.bold(" MCP Servers"));
|
|
2610
2513
|
for (const [name, server] of Object.entries(config.mcp)) {
|
|
2611
|
-
const status = server.enabled === false ?
|
|
2612
|
-
const type = server.type === "remote" ?
|
|
2613
|
-
const endpoint = server.type === "remote" ?
|
|
2514
|
+
const status = server.enabled === false ? import_picocolors6.default.red("off") : import_picocolors6.default.green("on");
|
|
2515
|
+
const type = server.type === "remote" ? import_picocolors6.default.dim("remote") : import_picocolors6.default.dim("local");
|
|
2516
|
+
const endpoint = server.type === "remote" ? import_picocolors6.default.dim(` → ${server.url}`) : import_picocolors6.default.dim(` → ${(server.command || []).join(" ")}`);
|
|
2614
2517
|
console.log(` ${status} ${name} ${type}${endpoint}`);
|
|
2615
2518
|
}
|
|
2616
2519
|
console.log();
|
|
@@ -2656,7 +2559,7 @@ async function toggleMCP(configPath, config) {
|
|
|
2656
2559
|
const wasEnabled = server.enabled !== false;
|
|
2657
2560
|
server.enabled = !wasEnabled;
|
|
2658
2561
|
saveConfig(configPath, config);
|
|
2659
|
-
const status = server.enabled ?
|
|
2562
|
+
const status = server.enabled ? import_picocolors6.default.green("enabled") : import_picocolors6.default.dim("disabled");
|
|
2660
2563
|
f2.success(`${serverName}: ${status}`);
|
|
2661
2564
|
}
|
|
2662
2565
|
async function addMCPServer(configPath, config) {
|
|
@@ -2722,7 +2625,7 @@ async function addMCPServer(configPath, config) {
|
|
|
2722
2625
|
};
|
|
2723
2626
|
}
|
|
2724
2627
|
saveConfig(configPath, config);
|
|
2725
|
-
f2.success(`Added MCP server: ${
|
|
2628
|
+
f2.success(`Added MCP server: ${import_picocolors6.default.cyan(serverName)}`);
|
|
2726
2629
|
}
|
|
2727
2630
|
async function removeMCP(configPath, config) {
|
|
2728
2631
|
const servers = Object.keys(config.mcp || {}).map((name) => ({
|
|
@@ -2753,13 +2656,13 @@ async function editPermissions(configPath) {
|
|
|
2753
2656
|
config.permission = {};
|
|
2754
2657
|
}
|
|
2755
2658
|
console.log();
|
|
2756
|
-
console.log(
|
|
2757
|
-
console.log(` edit: ${
|
|
2758
|
-
console.log(` external_directory: ${
|
|
2659
|
+
console.log(import_picocolors6.default.bold(" Current Permissions"));
|
|
2660
|
+
console.log(` edit: ${import_picocolors6.default.cyan(config.permission.edit || "ask")}`);
|
|
2661
|
+
console.log(` external_directory: ${import_picocolors6.default.cyan(config.permission.external_directory || "ask")}`);
|
|
2759
2662
|
if (config.permission.bash) {
|
|
2760
|
-
console.log(
|
|
2663
|
+
console.log(import_picocolors6.default.bold(" Bash"));
|
|
2761
2664
|
for (const [pattern, perm] of Object.entries(config.permission.bash)) {
|
|
2762
|
-
console.log(` ${
|
|
2665
|
+
console.log(` ${import_picocolors6.default.dim(pattern)}: ${import_picocolors6.default.cyan(perm)}`);
|
|
2763
2666
|
}
|
|
2764
2667
|
}
|
|
2765
2668
|
console.log();
|
|
@@ -2821,9 +2724,9 @@ async function editKeybinds(configPath) {
|
|
|
2821
2724
|
}
|
|
2822
2725
|
if (Object.keys(config.keybinds).length > 0) {
|
|
2823
2726
|
console.log();
|
|
2824
|
-
console.log(
|
|
2727
|
+
console.log(import_picocolors6.default.bold(" Current Keybinds"));
|
|
2825
2728
|
for (const [action2, key] of Object.entries(config.keybinds)) {
|
|
2826
|
-
console.log(` ${
|
|
2729
|
+
console.log(` ${import_picocolors6.default.dim(action2)}: ${import_picocolors6.default.cyan(key)}`);
|
|
2827
2730
|
}
|
|
2828
2731
|
console.log();
|
|
2829
2732
|
}
|
|
@@ -2876,7 +2779,7 @@ async function editKeybinds(configPath) {
|
|
|
2876
2779
|
}
|
|
2877
2780
|
config.keybinds[keybindName] = newKey;
|
|
2878
2781
|
saveConfig(configPath, config);
|
|
2879
|
-
f2.success(`${keybindName} → ${
|
|
2782
|
+
f2.success(`${keybindName} → ${import_picocolors6.default.cyan(newKey)}`);
|
|
2880
2783
|
}
|
|
2881
2784
|
var OPENCODE_THEMES = [
|
|
2882
2785
|
{ value: "system", label: "System", hint: "follows OS preference" },
|
|
@@ -2916,7 +2819,7 @@ var OPENCODE_THEMES = [
|
|
|
2916
2819
|
async function editTheme(configPath) {
|
|
2917
2820
|
const config = loadConfig(configPath);
|
|
2918
2821
|
const currentTheme = config.theme || "system";
|
|
2919
|
-
f2.info(`Current theme: ${
|
|
2822
|
+
f2.info(`Current theme: ${import_picocolors6.default.cyan(currentTheme)}`);
|
|
2920
2823
|
const validTheme = OPENCODE_THEMES.some((t) => t.value === currentTheme) ? currentTheme : "system";
|
|
2921
2824
|
const selectedTheme = await ie({
|
|
2922
2825
|
message: "Select theme",
|
|
@@ -2933,7 +2836,7 @@ async function editTheme(configPath) {
|
|
|
2933
2836
|
}
|
|
2934
2837
|
config.theme = selectedTheme;
|
|
2935
2838
|
saveConfig(configPath, config);
|
|
2936
|
-
f2.success(`Theme set to ${
|
|
2839
|
+
f2.success(`Theme set to ${import_picocolors6.default.cyan(selectedTheme)}`);
|
|
2937
2840
|
}
|
|
2938
2841
|
async function editTui(configPath) {
|
|
2939
2842
|
const config = loadConfig(configPath);
|
|
@@ -2981,7 +2884,7 @@ async function editTui(configPath) {
|
|
|
2981
2884
|
}
|
|
2982
2885
|
config.tui.diff_style = style;
|
|
2983
2886
|
saveConfig(configPath, config);
|
|
2984
|
-
f2.success(`Diff style set to ${
|
|
2887
|
+
f2.success(`Diff style set to ${import_picocolors6.default.cyan(style)}`);
|
|
2985
2888
|
} else {
|
|
2986
2889
|
const settingKey = setting;
|
|
2987
2890
|
const value = await te({
|
|
@@ -2998,7 +2901,7 @@ async function editTui(configPath) {
|
|
|
2998
2901
|
}
|
|
2999
2902
|
config.tui[settingKey] = value ? Number(value) : undefined;
|
|
3000
2903
|
saveConfig(configPath, config);
|
|
3001
|
-
f2.success(`${settingKey} set to ${
|
|
2904
|
+
f2.success(`${settingKey} set to ${import_picocolors6.default.cyan(value || "default")}`);
|
|
3002
2905
|
}
|
|
3003
2906
|
}
|
|
3004
2907
|
async function editTools(configPath) {
|
|
@@ -3018,9 +2921,9 @@ async function editTools(configPath) {
|
|
|
3018
2921
|
"todoread"
|
|
3019
2922
|
];
|
|
3020
2923
|
console.log();
|
|
3021
|
-
console.log(
|
|
2924
|
+
console.log(import_picocolors6.default.bold(" Tool Status"));
|
|
3022
2925
|
for (const tool of commonTools) {
|
|
3023
|
-
const status = config.tools[tool] === false ?
|
|
2926
|
+
const status = config.tools[tool] === false ? import_picocolors6.default.red("off") : import_picocolors6.default.green("on");
|
|
3024
2927
|
console.log(` ${status} ${tool}`);
|
|
3025
2928
|
}
|
|
3026
2929
|
console.log();
|
|
@@ -3054,7 +2957,7 @@ async function editTools(configPath) {
|
|
|
3054
2957
|
const wasEnabled = config.tools[toolName] !== false;
|
|
3055
2958
|
config.tools[toolName] = !wasEnabled;
|
|
3056
2959
|
saveConfig(configPath, config);
|
|
3057
|
-
const status = config.tools[toolName] ?
|
|
2960
|
+
const status = config.tools[toolName] ? import_picocolors6.default.green("enabled") : import_picocolors6.default.red("disabled");
|
|
3058
2961
|
f2.success(`${toolName}: ${status}`);
|
|
3059
2962
|
} else {
|
|
3060
2963
|
const toolName = await te({
|
|
@@ -3077,13 +2980,13 @@ async function editTools(configPath) {
|
|
|
3077
2980
|
}
|
|
3078
2981
|
config.tools[toolName] = enabled;
|
|
3079
2982
|
saveConfig(configPath, config);
|
|
3080
|
-
f2.success(`Added ${toolName}: ${enabled ?
|
|
2983
|
+
f2.success(`Added ${toolName}: ${enabled ? import_picocolors6.default.green("on") : import_picocolors6.default.red("off")}`);
|
|
3081
2984
|
}
|
|
3082
2985
|
}
|
|
3083
2986
|
async function editShare(configPath) {
|
|
3084
2987
|
const config = loadConfig(configPath);
|
|
3085
2988
|
const current = config.share || "manual";
|
|
3086
|
-
f2.info(`Current share setting: ${
|
|
2989
|
+
f2.info(`Current share setting: ${import_picocolors6.default.cyan(current)}`);
|
|
3087
2990
|
const selected = await ie({
|
|
3088
2991
|
message: "Share setting",
|
|
3089
2992
|
options: [
|
|
@@ -3106,13 +3009,13 @@ async function editShare(configPath) {
|
|
|
3106
3009
|
const shareValue = selected;
|
|
3107
3010
|
config.share = shareValue;
|
|
3108
3011
|
saveConfig(configPath, config);
|
|
3109
|
-
f2.success(`Share set to ${
|
|
3012
|
+
f2.success(`Share set to ${import_picocolors6.default.cyan(shareValue)}`);
|
|
3110
3013
|
}
|
|
3111
3014
|
async function editAutoupdate(configPath) {
|
|
3112
3015
|
const config = loadConfig(configPath);
|
|
3113
3016
|
const current = config.autoupdate ?? true;
|
|
3114
3017
|
const display = current === "notify" ? "notify" : current ? "enabled" : "disabled";
|
|
3115
|
-
f2.info(`Current autoupdate: ${
|
|
3018
|
+
f2.info(`Current autoupdate: ${import_picocolors6.default.cyan(display)}`);
|
|
3116
3019
|
const selected = await ie({
|
|
3117
3020
|
message: "Autoupdate behavior",
|
|
3118
3021
|
options: [
|
|
@@ -3143,69 +3046,366 @@ async function editAutoupdate(configPath) {
|
|
|
3143
3046
|
config.autoupdate = selectedValue === "true";
|
|
3144
3047
|
}
|
|
3145
3048
|
saveConfig(configPath, config);
|
|
3146
|
-
f2.success(`Autoupdate set to ${
|
|
3049
|
+
f2.success(`Autoupdate set to ${import_picocolors6.default.cyan(selectedValue)}`);
|
|
3147
3050
|
}
|
|
3148
3051
|
|
|
3149
|
-
// src/commands/
|
|
3150
|
-
import { join as join5, dirname as dirname2 } from "node:path";
|
|
3151
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3052
|
+
// src/commands/init.ts
|
|
3152
3053
|
import {
|
|
3153
|
-
existsSync as
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
copyFileSync
|
|
3054
|
+
existsSync as existsSync3,
|
|
3055
|
+
mkdirSync as mkdirSync2,
|
|
3056
|
+
readFileSync as readFileSync3,
|
|
3057
|
+
writeFileSync as writeFileSync3,
|
|
3058
|
+
readdirSync as readdirSync2
|
|
3159
3059
|
} from "node:fs";
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3060
|
+
import { join as join3, dirname, basename } from "node:path";
|
|
3061
|
+
import { fileURLToPath } from "node:url";
|
|
3062
|
+
var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
3063
|
+
var EXCLUDED_DIRS = [
|
|
3064
|
+
"node_modules",
|
|
3065
|
+
".git",
|
|
3066
|
+
"dist",
|
|
3067
|
+
".DS_Store",
|
|
3068
|
+
"coverage",
|
|
3069
|
+
".next",
|
|
3070
|
+
".turbo"
|
|
3163
3071
|
];
|
|
3164
|
-
var
|
|
3165
|
-
"
|
|
3166
|
-
"
|
|
3167
|
-
"
|
|
3072
|
+
var EXCLUDED_FILES = [
|
|
3073
|
+
"bun.lock",
|
|
3074
|
+
"package-lock.json",
|
|
3075
|
+
"yarn.lock",
|
|
3076
|
+
"pnpm-lock.yaml"
|
|
3168
3077
|
];
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3078
|
+
function detectMode(targetDir) {
|
|
3079
|
+
const opencodeDir = join3(targetDir, ".opencode");
|
|
3080
|
+
if (existsSync3(opencodeDir)) {
|
|
3081
|
+
return "already-initialized";
|
|
3082
|
+
}
|
|
3083
|
+
if (existsSync3(targetDir)) {
|
|
3084
|
+
const entries = readdirSync2(targetDir);
|
|
3085
|
+
const hasCode = entries.some((e2) => !e2.startsWith(".") && !EXCLUDED_DIRS.includes(e2) && e2 !== "node_modules");
|
|
3086
|
+
if (hasCode) {
|
|
3087
|
+
return "add-config";
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
return "scaffold";
|
|
3091
|
+
}
|
|
3092
|
+
function getTemplateRoot() {
|
|
3093
|
+
const __filename2 = fileURLToPath(import.meta.url);
|
|
3094
|
+
const __dirname2 = dirname(__filename2);
|
|
3173
3095
|
const possiblePaths = [
|
|
3174
|
-
|
|
3175
|
-
|
|
3096
|
+
join3(__dirname2, "template"),
|
|
3097
|
+
join3(__dirname2, "..", "..", ".opencode")
|
|
3176
3098
|
];
|
|
3177
3099
|
for (const path of possiblePaths) {
|
|
3178
|
-
const opencodeDir =
|
|
3179
|
-
if (
|
|
3100
|
+
const opencodeDir = join3(path, ".opencode");
|
|
3101
|
+
if (existsSync3(opencodeDir)) {
|
|
3180
3102
|
return path;
|
|
3181
3103
|
}
|
|
3182
3104
|
}
|
|
3183
3105
|
return null;
|
|
3184
3106
|
}
|
|
3185
|
-
function
|
|
3186
|
-
const
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
return pkg.version;
|
|
3107
|
+
async function copyDir(src, dest) {
|
|
3108
|
+
const { mkdir, readdir } = await import("node:fs/promises");
|
|
3109
|
+
await mkdir(dest, { recursive: true });
|
|
3110
|
+
for (const entry of await readdir(src, { withFileTypes: true })) {
|
|
3111
|
+
if (EXCLUDED_DIRS.includes(entry.name))
|
|
3112
|
+
continue;
|
|
3113
|
+
if (!entry.isDirectory() && EXCLUDED_FILES.includes(entry.name))
|
|
3114
|
+
continue;
|
|
3115
|
+
const srcPath = join3(src, entry.name);
|
|
3116
|
+
const destPath = join3(dest, entry.name);
|
|
3117
|
+
if (entry.isSymbolicLink()) {
|
|
3118
|
+
continue;
|
|
3119
|
+
} else if (entry.isDirectory()) {
|
|
3120
|
+
await copyDir(srcPath, destPath);
|
|
3121
|
+
} else {
|
|
3122
|
+
const content = readFileSync3(srcPath, "utf-8");
|
|
3123
|
+
writeFileSync3(destPath, content);
|
|
3203
3124
|
}
|
|
3204
3125
|
}
|
|
3205
|
-
return "unknown";
|
|
3206
3126
|
}
|
|
3207
|
-
async function
|
|
3208
|
-
const
|
|
3127
|
+
async function copyOpenCodeOnly(templateRoot, targetDir) {
|
|
3128
|
+
const opencodeSrc = join3(templateRoot, ".opencode");
|
|
3129
|
+
const opencodeDest = join3(targetDir, ".opencode");
|
|
3130
|
+
if (!existsSync3(opencodeSrc)) {
|
|
3131
|
+
return false;
|
|
3132
|
+
}
|
|
3133
|
+
await copyDir(opencodeSrc, opencodeDest);
|
|
3134
|
+
return true;
|
|
3135
|
+
}
|
|
3136
|
+
async function initCommand(options = {}) {
|
|
3137
|
+
const targetDir = process.cwd();
|
|
3138
|
+
const mode = detectMode(targetDir);
|
|
3139
|
+
oe(import_picocolors7.default.bgCyan(import_picocolors7.default.black(" OpenCodeKit ")));
|
|
3140
|
+
if (mode === "already-initialized" && !options.force) {
|
|
3141
|
+
f2.warn("Already initialized (.opencode/ exists)");
|
|
3142
|
+
f2.info(`Use ${import_picocolors7.default.cyan("--force")} to reinitialize`);
|
|
3143
|
+
$e("Nothing to do");
|
|
3144
|
+
return;
|
|
3145
|
+
}
|
|
3146
|
+
const templateRoot = getTemplateRoot();
|
|
3147
|
+
if (!templateRoot) {
|
|
3148
|
+
f2.error("Template not found. Please reinstall opencodekit.");
|
|
3149
|
+
$e(import_picocolors7.default.red("Failed"));
|
|
3150
|
+
process.exit(1);
|
|
3151
|
+
}
|
|
3152
|
+
let projectName = basename(targetDir);
|
|
3153
|
+
if (mode === "scaffold") {
|
|
3154
|
+
const name = await te({
|
|
3155
|
+
message: "Project name",
|
|
3156
|
+
placeholder: projectName,
|
|
3157
|
+
defaultValue: projectName
|
|
3158
|
+
});
|
|
3159
|
+
if (lD(name)) {
|
|
3160
|
+
ue("Cancelled");
|
|
3161
|
+
process.exit(0);
|
|
3162
|
+
}
|
|
3163
|
+
projectName = name || projectName;
|
|
3164
|
+
}
|
|
3165
|
+
const s = de();
|
|
3166
|
+
if (mode === "scaffold") {
|
|
3167
|
+
s.start("Scaffolding project");
|
|
3168
|
+
mkdirSync2(targetDir, { recursive: true });
|
|
3169
|
+
} else if (mode === "add-config") {
|
|
3170
|
+
s.start("Adding OpenCodeKit");
|
|
3171
|
+
} else {
|
|
3172
|
+
s.start("Reinitializing");
|
|
3173
|
+
}
|
|
3174
|
+
const success = await copyOpenCodeOnly(templateRoot, targetDir);
|
|
3175
|
+
if (!success) {
|
|
3176
|
+
s.stop("Failed");
|
|
3177
|
+
$e(import_picocolors7.default.red("Template copy failed"));
|
|
3178
|
+
process.exit(1);
|
|
3179
|
+
}
|
|
3180
|
+
s.stop("Done");
|
|
3181
|
+
le(`cd .opencode && bun install`, "Next steps");
|
|
3182
|
+
$e(import_picocolors7.default.green("Ready to code!"));
|
|
3183
|
+
}
|
|
3184
|
+
|
|
3185
|
+
// src/commands/menu.ts
|
|
3186
|
+
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
3187
|
+
import { existsSync as existsSync6, readdirSync as readdirSync5, lstatSync as lstatSync3 } from "node:fs";
|
|
3188
|
+
import { join as join6, basename as basename2 } from "node:path";
|
|
3189
|
+
|
|
3190
|
+
// src/commands/skill.ts
|
|
3191
|
+
import { join as join4 } from "node:path";
|
|
3192
|
+
import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync4, lstatSync as lstatSync2 } from "node:fs";
|
|
3193
|
+
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
3194
|
+
async function skillCommand(action) {
|
|
3195
|
+
const opencodePath = join4(process.cwd(), ".opencode");
|
|
3196
|
+
if (!existsSync4(opencodePath)) {
|
|
3197
|
+
notInitialized();
|
|
3198
|
+
return;
|
|
3199
|
+
}
|
|
3200
|
+
switch (action) {
|
|
3201
|
+
case "list":
|
|
3202
|
+
await listSkills(opencodePath);
|
|
3203
|
+
break;
|
|
3204
|
+
case "add":
|
|
3205
|
+
await addSkill(opencodePath);
|
|
3206
|
+
break;
|
|
3207
|
+
case "view": {
|
|
3208
|
+
const skillName = process.argv[4];
|
|
3209
|
+
await viewSkill(opencodePath, skillName);
|
|
3210
|
+
break;
|
|
3211
|
+
}
|
|
3212
|
+
default:
|
|
3213
|
+
unknownAction(action, ["list", "add", "view"]);
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
function collectSkills(basePath) {
|
|
3217
|
+
const skills = [];
|
|
3218
|
+
if (!existsSync4(basePath))
|
|
3219
|
+
return skills;
|
|
3220
|
+
const tiers = ["core", "stack", "specialized"];
|
|
3221
|
+
let hasTiers = false;
|
|
3222
|
+
for (const tier of tiers) {
|
|
3223
|
+
const tierPath = join4(basePath, tier);
|
|
3224
|
+
if (existsSync4(tierPath)) {
|
|
3225
|
+
hasTiers = true;
|
|
3226
|
+
const entries = readdirSync3(tierPath);
|
|
3227
|
+
for (const entry of entries) {
|
|
3228
|
+
const entryPath = join4(tierPath, entry);
|
|
3229
|
+
if (lstatSync2(entryPath).isDirectory()) {
|
|
3230
|
+
skills.push({ name: entry, path: entryPath, tier });
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
if (!hasTiers) {
|
|
3236
|
+
const entries = readdirSync3(basePath);
|
|
3237
|
+
for (const entry of entries) {
|
|
3238
|
+
const entryPath = join4(basePath, entry);
|
|
3239
|
+
if (lstatSync2(entryPath).isDirectory()) {
|
|
3240
|
+
skills.push({ name: entry, path: entryPath });
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
return skills;
|
|
3245
|
+
}
|
|
3246
|
+
async function listSkills(opencodePath) {
|
|
3247
|
+
const locations = [
|
|
3248
|
+
{ path: join4(opencodePath, "superpowers", "skills"), name: "Superpowers" },
|
|
3249
|
+
{ path: join4(opencodePath, "skills"), name: "Project" }
|
|
3250
|
+
];
|
|
3251
|
+
let totalSkills = 0;
|
|
3252
|
+
for (const loc of locations) {
|
|
3253
|
+
const skills = collectSkills(loc.path);
|
|
3254
|
+
if (skills.length > 0) {
|
|
3255
|
+
f2.info(import_picocolors8.default.bold(loc.name));
|
|
3256
|
+
for (const skill of skills) {
|
|
3257
|
+
const label = skill.tier ? `${skill.tier}/${skill.name}` : skill.name;
|
|
3258
|
+
console.log(` ${import_picocolors8.default.cyan("•")} ${label}`);
|
|
3259
|
+
}
|
|
3260
|
+
totalSkills += skills.length;
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
if (totalSkills === 0) {
|
|
3264
|
+
showEmpty("skills", "ock skill add");
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
async function addSkill(opencodePath) {
|
|
3268
|
+
oe(import_picocolors8.default.bgYellow(import_picocolors8.default.black(" Add Skill ")));
|
|
3269
|
+
const superpowersPath = join4(opencodePath, "superpowers", "skills");
|
|
3270
|
+
const skills = collectSkills(superpowersPath);
|
|
3271
|
+
if (skills.length === 0) {
|
|
3272
|
+
showEmpty("skills available to install");
|
|
3273
|
+
$e("Done");
|
|
3274
|
+
return;
|
|
3275
|
+
}
|
|
3276
|
+
const selected = await ie({
|
|
3277
|
+
message: "Select skill to install",
|
|
3278
|
+
options: skills.map((s) => ({
|
|
3279
|
+
value: s.name,
|
|
3280
|
+
label: s.tier ? `${s.name} (${s.tier})` : s.name
|
|
3281
|
+
}))
|
|
3282
|
+
});
|
|
3283
|
+
if (lD(selected)) {
|
|
3284
|
+
ue("Cancelled");
|
|
3285
|
+
return;
|
|
3286
|
+
}
|
|
3287
|
+
const skill = skills.find((s) => s.name === selected);
|
|
3288
|
+
if (!skill)
|
|
3289
|
+
return;
|
|
3290
|
+
const skillMdPath = join4(skill.path, "SKILL.md");
|
|
3291
|
+
if (!existsSync4(skillMdPath)) {
|
|
3292
|
+
notFound("SKILL.md in", skill.name);
|
|
3293
|
+
$e(import_picocolors8.default.red("Failed"));
|
|
3294
|
+
return;
|
|
3295
|
+
}
|
|
3296
|
+
const content = readFileSync4(skillMdPath, "utf-8");
|
|
3297
|
+
const lines = content.split(`
|
|
3298
|
+
`).slice(0, 10);
|
|
3299
|
+
console.log();
|
|
3300
|
+
console.log(import_picocolors8.default.dim("─".repeat(40)));
|
|
3301
|
+
console.log(lines.join(`
|
|
3302
|
+
`));
|
|
3303
|
+
if (content.split(`
|
|
3304
|
+
`).length > 10) {
|
|
3305
|
+
console.log(import_picocolors8.default.dim("..."));
|
|
3306
|
+
}
|
|
3307
|
+
console.log(import_picocolors8.default.dim("─".repeat(40)));
|
|
3308
|
+
console.log();
|
|
3309
|
+
f2.success(`Skill "${skill.name}" is available at:`);
|
|
3310
|
+
f2.info(import_picocolors8.default.cyan(skill.path));
|
|
3311
|
+
le(`Skills in superpowers/ are auto-loaded.
|
|
3312
|
+
Use ${import_picocolors8.default.cyan("find_skills")} + ${import_picocolors8.default.cyan("use_skill")} in opencode.`, "Usage");
|
|
3313
|
+
$e(import_picocolors8.default.green("Done!"));
|
|
3314
|
+
}
|
|
3315
|
+
async function viewSkill(opencodePath, skillName) {
|
|
3316
|
+
const superpowersPath = join4(opencodePath, "superpowers", "skills");
|
|
3317
|
+
const skills = collectSkills(superpowersPath);
|
|
3318
|
+
if (skills.length === 0) {
|
|
3319
|
+
showEmpty("skills");
|
|
3320
|
+
return;
|
|
3321
|
+
}
|
|
3322
|
+
if (!skillName) {
|
|
3323
|
+
const selected = await ie({
|
|
3324
|
+
message: "Select skill to view",
|
|
3325
|
+
options: skills.map((s) => ({ value: s.name, label: s.name }))
|
|
3326
|
+
});
|
|
3327
|
+
if (lD(selected)) {
|
|
3328
|
+
return;
|
|
3329
|
+
}
|
|
3330
|
+
skillName = selected;
|
|
3331
|
+
}
|
|
3332
|
+
const skill = skills.find((s) => s.name === skillName);
|
|
3333
|
+
if (!skill) {
|
|
3334
|
+
notFound("Skill", skillName);
|
|
3335
|
+
return;
|
|
3336
|
+
}
|
|
3337
|
+
const skillMdPath = join4(skill.path, "SKILL.md");
|
|
3338
|
+
if (!existsSync4(skillMdPath)) {
|
|
3339
|
+
notFound("SKILL.md");
|
|
3340
|
+
return;
|
|
3341
|
+
}
|
|
3342
|
+
const content = readFileSync4(skillMdPath, "utf-8");
|
|
3343
|
+
console.log();
|
|
3344
|
+
console.log(import_picocolors8.default.dim("─".repeat(40)));
|
|
3345
|
+
console.log(content);
|
|
3346
|
+
console.log(import_picocolors8.default.dim("─".repeat(40)));
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
// src/commands/upgrade.ts
|
|
3350
|
+
import { join as join5, dirname as dirname2 } from "node:path";
|
|
3351
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3352
|
+
import {
|
|
3353
|
+
existsSync as existsSync5,
|
|
3354
|
+
readFileSync as readFileSync5,
|
|
3355
|
+
writeFileSync as writeFileSync4,
|
|
3356
|
+
readdirSync as readdirSync4,
|
|
3357
|
+
mkdirSync as mkdirSync3,
|
|
3358
|
+
copyFileSync
|
|
3359
|
+
} from "node:fs";
|
|
3360
|
+
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
3361
|
+
var PRESERVE_FILES = [
|
|
3362
|
+
"opencode.json"
|
|
3363
|
+
];
|
|
3364
|
+
var PRESERVE_DIRS = [
|
|
3365
|
+
"agent",
|
|
3366
|
+
"command",
|
|
3367
|
+
"memory"
|
|
3368
|
+
];
|
|
3369
|
+
var SKIP_DIRS = ["node_modules", ".git", "dist", "coverage"];
|
|
3370
|
+
function getTemplateRoot2() {
|
|
3371
|
+
const __filename2 = fileURLToPath2(import.meta.url);
|
|
3372
|
+
const __dirname2 = dirname2(__filename2);
|
|
3373
|
+
const possiblePaths = [
|
|
3374
|
+
join5(__dirname2, "template"),
|
|
3375
|
+
join5(__dirname2, "..", "..", ".opencode")
|
|
3376
|
+
];
|
|
3377
|
+
for (const path of possiblePaths) {
|
|
3378
|
+
const opencodeDir = join5(path, ".opencode");
|
|
3379
|
+
if (existsSync5(opencodeDir)) {
|
|
3380
|
+
return path;
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
return null;
|
|
3384
|
+
}
|
|
3385
|
+
function getCurrentVersion(opencodeDir) {
|
|
3386
|
+
const versionFile = join5(opencodeDir, ".version");
|
|
3387
|
+
if (existsSync5(versionFile)) {
|
|
3388
|
+
return readFileSync5(versionFile, "utf-8").trim();
|
|
3389
|
+
}
|
|
3390
|
+
return null;
|
|
3391
|
+
}
|
|
3392
|
+
function getPackageVersion() {
|
|
3393
|
+
const __filename2 = fileURLToPath2(import.meta.url);
|
|
3394
|
+
const __dirname2 = dirname2(__filename2);
|
|
3395
|
+
const pkgPaths = [
|
|
3396
|
+
join5(__dirname2, "..", "..", "package.json"),
|
|
3397
|
+
join5(__dirname2, "..", "package.json")
|
|
3398
|
+
];
|
|
3399
|
+
for (const pkgPath of pkgPaths) {
|
|
3400
|
+
if (existsSync5(pkgPath)) {
|
|
3401
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
|
|
3402
|
+
return pkg.version;
|
|
3403
|
+
}
|
|
3404
|
+
}
|
|
3405
|
+
return "unknown";
|
|
3406
|
+
}
|
|
3407
|
+
async function checkVersion(opencodeDir) {
|
|
3408
|
+
const current = getCurrentVersion(opencodeDir);
|
|
3209
3409
|
const latest = getPackageVersion();
|
|
3210
3410
|
return {
|
|
3211
3411
|
current,
|
|
@@ -3281,23 +3481,23 @@ async function upgradeCommand(options = {}) {
|
|
|
3281
3481
|
notInitialized();
|
|
3282
3482
|
return;
|
|
3283
3483
|
}
|
|
3284
|
-
oe(
|
|
3484
|
+
oe(import_picocolors9.default.bgCyan(import_picocolors9.default.black(" Upgrade ")));
|
|
3285
3485
|
const versionInfo = await checkVersion(opencodeDir);
|
|
3286
3486
|
console.log();
|
|
3287
|
-
console.log(` ${
|
|
3288
|
-
console.log(` ${
|
|
3487
|
+
console.log(` ${import_picocolors9.default.bold("Installed")} ${import_picocolors9.default.cyan(versionInfo.current || "unknown")}`);
|
|
3488
|
+
console.log(` ${import_picocolors9.default.bold("Latest")} ${import_picocolors9.default.cyan(versionInfo.latest || "unknown")}`);
|
|
3289
3489
|
console.log();
|
|
3290
3490
|
if (options.check) {
|
|
3291
3491
|
if (versionInfo.needsUpdate) {
|
|
3292
|
-
f2.info(`Update available: ${
|
|
3293
|
-
$e(`Run ${
|
|
3492
|
+
f2.info(`Update available: ${import_picocolors9.default.cyan(versionInfo.latest)}`);
|
|
3493
|
+
$e(`Run ${import_picocolors9.default.cyan("ock upgrade")} to update`);
|
|
3294
3494
|
} else {
|
|
3295
|
-
$e(
|
|
3495
|
+
$e(import_picocolors9.default.green("Already up to date"));
|
|
3296
3496
|
}
|
|
3297
3497
|
return;
|
|
3298
3498
|
}
|
|
3299
3499
|
if (!versionInfo.needsUpdate && !options.force) {
|
|
3300
|
-
$e(
|
|
3500
|
+
$e(import_picocolors9.default.green("Already up to date"));
|
|
3301
3501
|
return;
|
|
3302
3502
|
}
|
|
3303
3503
|
const templateRoot = getTemplateRoot2();
|
|
@@ -3333,205 +3533,10 @@ async function upgradeCommand(options = {}) {
|
|
|
3333
3533
|
f2.info(`Preserved ${result.preserved.length} user files`);
|
|
3334
3534
|
}
|
|
3335
3535
|
le("cd .opencode && bun install", "Run if dependencies changed");
|
|
3336
|
-
$e(
|
|
3337
|
-
}
|
|
3338
|
-
|
|
3339
|
-
// src/commands/completion.ts
|
|
3340
|
-
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
3341
|
-
var BASH_COMPLETION = `# ock bash completion
|
|
3342
|
-
_ock_completion() {
|
|
3343
|
-
local cur prev commands
|
|
3344
|
-
COMPREPLY=()
|
|
3345
|
-
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
3346
|
-
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
3347
|
-
|
|
3348
|
-
commands="init config upgrade agent skill doctor status help"
|
|
3349
|
-
|
|
3350
|
-
case "\${prev}" in
|
|
3351
|
-
ock)
|
|
3352
|
-
COMPREPLY=( $(compgen -W "\${commands}" -- "\${cur}") )
|
|
3353
|
-
return 0
|
|
3354
|
-
;;
|
|
3355
|
-
agent)
|
|
3356
|
-
COMPREPLY=( $(compgen -W "list add view" -- "\${cur}") )
|
|
3357
|
-
return 0
|
|
3358
|
-
;;
|
|
3359
|
-
skill)
|
|
3360
|
-
COMPREPLY=( $(compgen -W "list add view" -- "\${cur}") )
|
|
3361
|
-
return 0
|
|
3362
|
-
;;
|
|
3363
|
-
config)
|
|
3364
|
-
COMPREPLY=( $(compgen -W "model mcp permission keybinds show" -- "\${cur}") )
|
|
3365
|
-
return 0
|
|
3366
|
-
;;
|
|
3367
|
-
init)
|
|
3368
|
-
COMPREPLY=( $(compgen -W "--force" -- "\${cur}") )
|
|
3369
|
-
return 0
|
|
3370
|
-
;;
|
|
3371
|
-
upgrade)
|
|
3372
|
-
COMPREPLY=( $(compgen -W "--force --check" -- "\${cur}") )
|
|
3373
|
-
return 0
|
|
3374
|
-
;;
|
|
3375
|
-
*)
|
|
3376
|
-
;;
|
|
3377
|
-
esac
|
|
3378
|
-
}
|
|
3379
|
-
complete -F _ock_completion ock
|
|
3380
|
-
`;
|
|
3381
|
-
var ZSH_COMPLETION = `#compdef ock
|
|
3382
|
-
|
|
3383
|
-
_ock() {
|
|
3384
|
-
local -a commands
|
|
3385
|
-
local -a agent_actions
|
|
3386
|
-
local -a skill_actions
|
|
3387
|
-
local -a config_actions
|
|
3388
|
-
|
|
3389
|
-
commands=(
|
|
3390
|
-
'init:Initialize OpenCodeKit in current directory'
|
|
3391
|
-
'config:Edit opencode.json'
|
|
3392
|
-
'upgrade:Update templates to latest version'
|
|
3393
|
-
'agent:Manage agents'
|
|
3394
|
-
'skill:Manage skills'
|
|
3395
|
-
'doctor:Check project health'
|
|
3396
|
-
'status:Show project overview'
|
|
3397
|
-
'help:Show help'
|
|
3398
|
-
)
|
|
3399
|
-
|
|
3400
|
-
agent_actions=(
|
|
3401
|
-
'list:List all agents'
|
|
3402
|
-
'add:Create a new agent'
|
|
3403
|
-
'view:View agent details'
|
|
3404
|
-
)
|
|
3405
|
-
|
|
3406
|
-
skill_actions=(
|
|
3407
|
-
'list:List all skills'
|
|
3408
|
-
'add:Install a skill'
|
|
3409
|
-
'view:View skill details'
|
|
3410
|
-
)
|
|
3411
|
-
|
|
3412
|
-
config_actions=(
|
|
3413
|
-
'model:Change default model'
|
|
3414
|
-
'mcp:Manage MCP servers'
|
|
3415
|
-
'permission:Edit permissions'
|
|
3416
|
-
'keybinds:Edit keyboard shortcuts'
|
|
3417
|
-
'show:View current config'
|
|
3418
|
-
)
|
|
3419
|
-
|
|
3420
|
-
case "$words[2]" in
|
|
3421
|
-
agent)
|
|
3422
|
-
_describe -t actions 'agent action' agent_actions
|
|
3423
|
-
;;
|
|
3424
|
-
skill)
|
|
3425
|
-
_describe -t actions 'skill action' skill_actions
|
|
3426
|
-
;;
|
|
3427
|
-
config)
|
|
3428
|
-
_describe -t actions 'config action' config_actions
|
|
3429
|
-
;;
|
|
3430
|
-
init)
|
|
3431
|
-
_arguments '--force[Reinitialize even if already exists]'
|
|
3432
|
-
;;
|
|
3433
|
-
upgrade)
|
|
3434
|
-
_arguments \\
|
|
3435
|
-
'--force[Force upgrade even if up to date]' \\
|
|
3436
|
-
'--check[Check for updates only]'
|
|
3437
|
-
;;
|
|
3438
|
-
*)
|
|
3439
|
-
_describe -t commands 'command' commands
|
|
3440
|
-
;;
|
|
3441
|
-
esac
|
|
3442
|
-
}
|
|
3443
|
-
|
|
3444
|
-
_ock "$@"
|
|
3445
|
-
`;
|
|
3446
|
-
var FISH_COMPLETION = `# ock fish completion
|
|
3447
|
-
complete -c ock -n "__fish_use_subcommand" -a "init" -d "Initialize OpenCodeKit"
|
|
3448
|
-
complete -c ock -n "__fish_use_subcommand" -a "config" -d "Edit opencode.json"
|
|
3449
|
-
complete -c ock -n "__fish_use_subcommand" -a "upgrade" -d "Update templates"
|
|
3450
|
-
complete -c ock -n "__fish_use_subcommand" -a "agent" -d "Manage agents"
|
|
3451
|
-
complete -c ock -n "__fish_use_subcommand" -a "skill" -d "Manage skills"
|
|
3452
|
-
complete -c ock -n "__fish_use_subcommand" -a "doctor" -d "Check project health"
|
|
3453
|
-
complete -c ock -n "__fish_use_subcommand" -a "status" -d "Show project overview"
|
|
3454
|
-
|
|
3455
|
-
# agent subcommands
|
|
3456
|
-
complete -c ock -n "__fish_seen_subcommand_from agent" -a "list" -d "List agents"
|
|
3457
|
-
complete -c ock -n "__fish_seen_subcommand_from agent" -a "add" -d "Add agent"
|
|
3458
|
-
complete -c ock -n "__fish_seen_subcommand_from agent" -a "view" -d "View agent"
|
|
3459
|
-
|
|
3460
|
-
# skill subcommands
|
|
3461
|
-
complete -c ock -n "__fish_seen_subcommand_from skill" -a "list" -d "List skills"
|
|
3462
|
-
complete -c ock -n "__fish_seen_subcommand_from skill" -a "add" -d "Add skill"
|
|
3463
|
-
complete -c ock -n "__fish_seen_subcommand_from skill" -a "view" -d "View skill"
|
|
3464
|
-
|
|
3465
|
-
# config subcommands
|
|
3466
|
-
complete -c ock -n "__fish_seen_subcommand_from config" -a "model" -d "Change model"
|
|
3467
|
-
complete -c ock -n "__fish_seen_subcommand_from config" -a "mcp" -d "Manage MCP"
|
|
3468
|
-
complete -c ock -n "__fish_seen_subcommand_from config" -a "permission" -d "Edit permissions"
|
|
3469
|
-
complete -c ock -n "__fish_seen_subcommand_from config" -a "keybinds" -d "Edit keybinds"
|
|
3470
|
-
complete -c ock -n "__fish_seen_subcommand_from config" -a "show" -d "View config"
|
|
3471
|
-
|
|
3472
|
-
# init options
|
|
3473
|
-
complete -c ock -n "__fish_seen_subcommand_from init" -l force -d "Reinitialize"
|
|
3474
|
-
|
|
3475
|
-
# upgrade options
|
|
3476
|
-
complete -c ock -n "__fish_seen_subcommand_from upgrade" -l force -d "Force upgrade"
|
|
3477
|
-
complete -c ock -n "__fish_seen_subcommand_from upgrade" -l check -d "Check only"
|
|
3478
|
-
`;
|
|
3479
|
-
async function completionCommand(shell) {
|
|
3480
|
-
if (!shell) {
|
|
3481
|
-
oe(import_picocolors9.default.bgCyan(import_picocolors9.default.black(" Shell Completion ")));
|
|
3482
|
-
const selected = await ie({
|
|
3483
|
-
message: "Select your shell",
|
|
3484
|
-
options: [
|
|
3485
|
-
{ value: "bash", label: "Bash" },
|
|
3486
|
-
{ value: "zsh", label: "Zsh" },
|
|
3487
|
-
{ value: "fish", label: "Fish" }
|
|
3488
|
-
]
|
|
3489
|
-
});
|
|
3490
|
-
if (lD(selected)) {
|
|
3491
|
-
ue("Cancelled");
|
|
3492
|
-
return;
|
|
3493
|
-
}
|
|
3494
|
-
shell = selected;
|
|
3495
|
-
}
|
|
3496
|
-
let script;
|
|
3497
|
-
let setupInstructions;
|
|
3498
|
-
switch (shell) {
|
|
3499
|
-
case "bash":
|
|
3500
|
-
script = BASH_COMPLETION;
|
|
3501
|
-
setupInstructions = `Add to ~/.bashrc:
|
|
3502
|
-
source <(ock completion bash)
|
|
3503
|
-
|
|
3504
|
-
Or save to file:
|
|
3505
|
-
ock completion bash > ~/.local/share/bash-completion/completions/ock`;
|
|
3506
|
-
break;
|
|
3507
|
-
case "zsh":
|
|
3508
|
-
script = ZSH_COMPLETION;
|
|
3509
|
-
setupInstructions = `Add to ~/.zshrc (before compinit):
|
|
3510
|
-
source <(ock completion zsh)
|
|
3511
|
-
|
|
3512
|
-
Or save to fpath:
|
|
3513
|
-
ock completion zsh > ~/.zsh/completions/_ock
|
|
3514
|
-
# Then add to ~/.zshrc: fpath=(~/.zsh/completions $fpath)`;
|
|
3515
|
-
break;
|
|
3516
|
-
case "fish":
|
|
3517
|
-
script = FISH_COMPLETION;
|
|
3518
|
-
setupInstructions = `Save to fish completions:
|
|
3519
|
-
ock completion fish > ~/.config/fish/completions/ock.fish`;
|
|
3520
|
-
break;
|
|
3521
|
-
default:
|
|
3522
|
-
f2.error(`Unknown shell: ${shell}`);
|
|
3523
|
-
return;
|
|
3524
|
-
}
|
|
3525
|
-
console.log(script);
|
|
3526
|
-
console.error();
|
|
3527
|
-
console.error(import_picocolors9.default.bold("Setup:"));
|
|
3528
|
-
console.error(import_picocolors9.default.dim(setupInstructions));
|
|
3536
|
+
$e(import_picocolors9.default.green(`Upgraded to ${versionInfo.latest}`));
|
|
3529
3537
|
}
|
|
3530
3538
|
|
|
3531
3539
|
// src/commands/menu.ts
|
|
3532
|
-
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
3533
|
-
import { existsSync as existsSync6, readdirSync as readdirSync5, lstatSync as lstatSync3 } from "node:fs";
|
|
3534
|
-
import { join as join6, basename as basename2 } from "node:path";
|
|
3535
3540
|
async function interactiveMenu(version) {
|
|
3536
3541
|
oe(import_picocolors10.default.bgCyan(import_picocolors10.default.black(` OpenCodeKit v${version} `)));
|
|
3537
3542
|
const action = await ie({
|