opencodekit 0.6.7 → 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 +654 -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 +489 -491
- 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,66 +1900,66 @@ async function configCommand(action) {
|
|
|
1999
1900
|
}
|
|
2000
1901
|
}
|
|
2001
1902
|
function loadConfig(configPath) {
|
|
2002
|
-
const content =
|
|
1903
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
2003
1904
|
const jsonWithoutComments = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
|
|
2004
1905
|
return JSON.parse(jsonWithoutComments);
|
|
2005
1906
|
}
|
|
2006
1907
|
function saveConfig(configPath, config) {
|
|
2007
|
-
|
|
1908
|
+
writeFileSync2(configPath, JSON.stringify(config, null, 2) + `
|
|
2008
1909
|
`);
|
|
2009
1910
|
}
|
|
2010
1911
|
function showConfig(configPath) {
|
|
2011
1912
|
const config = loadConfig(configPath);
|
|
2012
1913
|
console.log();
|
|
2013
|
-
console.log(
|
|
2014
|
-
console.log(` ${
|
|
1914
|
+
console.log(import_picocolors6.default.bold(" Model"));
|
|
1915
|
+
console.log(` ${import_picocolors6.default.cyan(config.model || "not set")}`);
|
|
2015
1916
|
if (config.small_model) {
|
|
2016
|
-
console.log(
|
|
2017
|
-
console.log(` ${
|
|
1917
|
+
console.log(import_picocolors6.default.bold(" Small Model"));
|
|
1918
|
+
console.log(` ${import_picocolors6.default.cyan(config.small_model)}`);
|
|
2018
1919
|
}
|
|
2019
|
-
console.log(
|
|
2020
|
-
console.log(` ${
|
|
2021
|
-
console.log(
|
|
2022
|
-
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")}`);
|
|
2023
1924
|
const autoupdateDisplay = config.autoupdate === "notify" ? "notify" : config.autoupdate === false ? "disabled" : "enabled";
|
|
2024
|
-
console.log(
|
|
2025
|
-
console.log(` ${
|
|
1925
|
+
console.log(import_picocolors6.default.bold(" Autoupdate"));
|
|
1926
|
+
console.log(` ${import_picocolors6.default.cyan(autoupdateDisplay)}`);
|
|
2026
1927
|
if (config.tui && Object.keys(config.tui).length > 0) {
|
|
2027
|
-
console.log(
|
|
1928
|
+
console.log(import_picocolors6.default.bold(" TUI"));
|
|
2028
1929
|
if (config.tui.scroll_speed !== undefined) {
|
|
2029
|
-
console.log(` scroll_speed: ${
|
|
1930
|
+
console.log(` scroll_speed: ${import_picocolors6.default.cyan(String(config.tui.scroll_speed))}`);
|
|
2030
1931
|
}
|
|
2031
1932
|
if (config.tui.scroll_acceleration !== undefined) {
|
|
2032
|
-
console.log(` scroll_acceleration: ${
|
|
1933
|
+
console.log(` scroll_acceleration: ${import_picocolors6.default.cyan(String(config.tui.scroll_acceleration))}`);
|
|
2033
1934
|
}
|
|
2034
1935
|
if (config.tui.diff_style) {
|
|
2035
|
-
console.log(` diff_style: ${
|
|
1936
|
+
console.log(` diff_style: ${import_picocolors6.default.cyan(config.tui.diff_style)}`);
|
|
2036
1937
|
}
|
|
2037
1938
|
}
|
|
2038
1939
|
if (config.mcp && Object.keys(config.mcp).length > 0) {
|
|
2039
|
-
console.log(
|
|
1940
|
+
console.log(import_picocolors6.default.bold(" MCP Servers"));
|
|
2040
1941
|
for (const [name, server] of Object.entries(config.mcp)) {
|
|
2041
|
-
const status = server.enabled === false ?
|
|
1942
|
+
const status = server.enabled === false ? import_picocolors6.default.dim("off") : import_picocolors6.default.green("on");
|
|
2042
1943
|
console.log(` ${status} ${name}`);
|
|
2043
1944
|
}
|
|
2044
1945
|
}
|
|
2045
1946
|
if (config.tools && Object.keys(config.tools).length > 0) {
|
|
2046
|
-
console.log(
|
|
1947
|
+
console.log(import_picocolors6.default.bold(" Tools"));
|
|
2047
1948
|
for (const [tool, enabled] of Object.entries(config.tools)) {
|
|
2048
|
-
const status = enabled === false ?
|
|
1949
|
+
const status = enabled === false ? import_picocolors6.default.red("off") : import_picocolors6.default.green("on");
|
|
2049
1950
|
console.log(` ${status} ${tool}`);
|
|
2050
1951
|
}
|
|
2051
1952
|
}
|
|
2052
1953
|
if (config.keybinds && Object.keys(config.keybinds).length > 0) {
|
|
2053
|
-
console.log(
|
|
1954
|
+
console.log(import_picocolors6.default.bold(" Keybinds"));
|
|
2054
1955
|
for (const [action, key] of Object.entries(config.keybinds)) {
|
|
2055
|
-
console.log(` ${
|
|
1956
|
+
console.log(` ${import_picocolors6.default.dim(action)}: ${import_picocolors6.default.cyan(key)}`);
|
|
2056
1957
|
}
|
|
2057
1958
|
}
|
|
2058
1959
|
console.log();
|
|
2059
1960
|
}
|
|
2060
1961
|
async function configMenu(configPath) {
|
|
2061
|
-
oe(
|
|
1962
|
+
oe(import_picocolors6.default.bgCyan(import_picocolors6.default.black(" Configuration ")));
|
|
2062
1963
|
while (true) {
|
|
2063
1964
|
const action = await ie({
|
|
2064
1965
|
message: "What do you want to configure?",
|
|
@@ -2133,8 +2034,8 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2133
2034
|
const config = loadConfig(configPath);
|
|
2134
2035
|
const currentModel = config[modelType] || "not set";
|
|
2135
2036
|
const modelLabel = modelType === "small_model" ? "Small Model" : "Model";
|
|
2136
|
-
f2.info(`Current ${modelLabel}: ${
|
|
2137
|
-
f2.info(
|
|
2037
|
+
f2.info(`Current ${modelLabel}: ${import_picocolors6.default.cyan(currentModel)}`);
|
|
2038
|
+
f2.info(import_picocolors6.default.dim("Fetching models from models.dev..."));
|
|
2138
2039
|
const modelsDevData = await fetchFromModelsDev();
|
|
2139
2040
|
if (!modelsDevData || Object.keys(modelsDevData).length === 0) {
|
|
2140
2041
|
f2.warn("models.dev unavailable - please enter manually");
|
|
@@ -2155,7 +2056,7 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2155
2056
|
}
|
|
2156
2057
|
config[modelType] = newModel;
|
|
2157
2058
|
saveConfig(configPath, config);
|
|
2158
|
-
f2.success(`${modelLabel} set to ${
|
|
2059
|
+
f2.success(`${modelLabel} set to ${import_picocolors6.default.cyan(newModel)}`);
|
|
2159
2060
|
return;
|
|
2160
2061
|
}
|
|
2161
2062
|
f2.success("Fetched models from models.dev");
|
|
@@ -2218,7 +2119,7 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2218
2119
|
}
|
|
2219
2120
|
config[modelType] = customModel;
|
|
2220
2121
|
saveConfig(configPath, config);
|
|
2221
|
-
f2.success(`${modelLabel} set to ${
|
|
2122
|
+
f2.success(`${modelLabel} set to ${import_picocolors6.default.cyan(customModel)}`);
|
|
2222
2123
|
return;
|
|
2223
2124
|
}
|
|
2224
2125
|
if (providerId === "__search__") {
|
|
@@ -2283,7 +2184,7 @@ async function editModel(configPath, modelType = "model") {
|
|
|
2283
2184
|
const fullModelId = `${providerId}/${selectedModel}`;
|
|
2284
2185
|
config[modelType] = fullModelId;
|
|
2285
2186
|
saveConfig(configPath, config);
|
|
2286
|
-
f2.success(`${modelLabel} set to ${
|
|
2187
|
+
f2.success(`${modelLabel} set to ${import_picocolors6.default.cyan(fullModelId)}`);
|
|
2287
2188
|
}
|
|
2288
2189
|
function getModelsForProvider(provider) {
|
|
2289
2190
|
const options = [];
|
|
@@ -2331,7 +2232,7 @@ async function editAgentModel(configPath) {
|
|
|
2331
2232
|
let agentNames = [];
|
|
2332
2233
|
const agentInfoMap = new Map;
|
|
2333
2234
|
if (serverAgents && serverAgents.length > 0) {
|
|
2334
|
-
f2.info(
|
|
2235
|
+
f2.info(import_picocolors6.default.dim("Fetched agents from OpenCode server"));
|
|
2335
2236
|
for (const agent of serverAgents) {
|
|
2336
2237
|
agentNames.push(agent.name);
|
|
2337
2238
|
agentInfoMap.set(agent.name, {
|
|
@@ -2355,14 +2256,14 @@ async function editAgentModel(configPath) {
|
|
|
2355
2256
|
return;
|
|
2356
2257
|
}
|
|
2357
2258
|
console.log();
|
|
2358
|
-
console.log(
|
|
2259
|
+
console.log(import_picocolors6.default.bold(" Agent Models"));
|
|
2359
2260
|
for (const name of agentNames) {
|
|
2360
2261
|
const info = agentInfoMap.get(name);
|
|
2361
|
-
const model = info?.model ||
|
|
2362
|
-
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]") : "";
|
|
2363
2264
|
const localConfig = config.agent[name];
|
|
2364
|
-
const disabled = localConfig?.disable ?
|
|
2365
|
-
console.log(` ${
|
|
2265
|
+
const disabled = localConfig?.disable ? import_picocolors6.default.red(" [disabled]") : "";
|
|
2266
|
+
console.log(` ${import_picocolors6.default.cyan(name)}: ${model}${builtIn}${disabled}`);
|
|
2366
2267
|
}
|
|
2367
2268
|
console.log();
|
|
2368
2269
|
const agentOptions = [
|
|
@@ -2410,7 +2311,7 @@ async function editAgentModel(configPath) {
|
|
|
2410
2311
|
}
|
|
2411
2312
|
config.agent[agentName].disable = !currentAgent.disable;
|
|
2412
2313
|
saveConfig(configPath, config);
|
|
2413
|
-
const status = config.agent[agentName].disable ?
|
|
2314
|
+
const status = config.agent[agentName].disable ? import_picocolors6.default.red("disabled") : import_picocolors6.default.green("enabled");
|
|
2414
2315
|
f2.success(`Agent ${agentName}: ${status}`);
|
|
2415
2316
|
return;
|
|
2416
2317
|
}
|
|
@@ -2431,8 +2332,8 @@ async function editAgentModel(configPath) {
|
|
|
2431
2332
|
return;
|
|
2432
2333
|
}
|
|
2433
2334
|
const agentInfo = agentInfoMap.get(agentName);
|
|
2434
|
-
f2.info(`Current model: ${
|
|
2435
|
-
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..."));
|
|
2436
2337
|
const modelsDevData = await fetchFromModelsDev();
|
|
2437
2338
|
if (!modelsDevData || Object.keys(modelsDevData).length === 0) {
|
|
2438
2339
|
f2.warn("models.dev unavailable - please enter manually");
|
|
@@ -2454,7 +2355,7 @@ async function editAgentModel(configPath) {
|
|
|
2454
2355
|
}
|
|
2455
2356
|
config.agent[agentName].model = newModel;
|
|
2456
2357
|
saveConfig(configPath, config);
|
|
2457
|
-
f2.success(`${agentName} model set to ${
|
|
2358
|
+
f2.success(`${agentName} model set to ${import_picocolors6.default.cyan(newModel)}`);
|
|
2458
2359
|
return;
|
|
2459
2360
|
}
|
|
2460
2361
|
const localProviders = config.provider || {};
|
|
@@ -2512,7 +2413,7 @@ async function editAgentModel(configPath) {
|
|
|
2512
2413
|
agentConfig.model = undefined;
|
|
2513
2414
|
}
|
|
2514
2415
|
saveConfig(configPath, config);
|
|
2515
|
-
f2.success(`${agentName} model set to ${
|
|
2416
|
+
f2.success(`${agentName} model set to ${import_picocolors6.default.cyan("(default)")}`);
|
|
2516
2417
|
return;
|
|
2517
2418
|
}
|
|
2518
2419
|
if (providerId === "__custom__") {
|
|
@@ -2534,7 +2435,7 @@ async function editAgentModel(configPath) {
|
|
|
2534
2435
|
}
|
|
2535
2436
|
config.agent[agentName].model = customModel;
|
|
2536
2437
|
saveConfig(configPath, config);
|
|
2537
|
-
f2.success(`${agentName} model set to ${
|
|
2438
|
+
f2.success(`${agentName} model set to ${import_picocolors6.default.cyan(customModel)}`);
|
|
2538
2439
|
return;
|
|
2539
2440
|
}
|
|
2540
2441
|
if (providerId === "__search__") {
|
|
@@ -2589,7 +2490,7 @@ async function editAgentModel(configPath) {
|
|
|
2589
2490
|
}
|
|
2590
2491
|
config.agent[agentName].model = fullModelId;
|
|
2591
2492
|
saveConfig(configPath, config);
|
|
2592
|
-
f2.success(`${agentName} model set to ${
|
|
2493
|
+
f2.success(`${agentName} model set to ${import_picocolors6.default.cyan(fullModelId)}`);
|
|
2593
2494
|
}
|
|
2594
2495
|
async function editMCP(configPath) {
|
|
2595
2496
|
const config = loadConfig(configPath);
|
|
@@ -2608,11 +2509,11 @@ async function editMCP(configPath) {
|
|
|
2608
2509
|
return;
|
|
2609
2510
|
}
|
|
2610
2511
|
console.log();
|
|
2611
|
-
console.log(
|
|
2512
|
+
console.log(import_picocolors6.default.bold(" MCP Servers"));
|
|
2612
2513
|
for (const [name, server] of Object.entries(config.mcp)) {
|
|
2613
|
-
const status = server.enabled === false ?
|
|
2614
|
-
const type = server.type === "remote" ?
|
|
2615
|
-
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(" ")}`);
|
|
2616
2517
|
console.log(` ${status} ${name} ${type}${endpoint}`);
|
|
2617
2518
|
}
|
|
2618
2519
|
console.log();
|
|
@@ -2658,7 +2559,7 @@ async function toggleMCP(configPath, config) {
|
|
|
2658
2559
|
const wasEnabled = server.enabled !== false;
|
|
2659
2560
|
server.enabled = !wasEnabled;
|
|
2660
2561
|
saveConfig(configPath, config);
|
|
2661
|
-
const status = server.enabled ?
|
|
2562
|
+
const status = server.enabled ? import_picocolors6.default.green("enabled") : import_picocolors6.default.dim("disabled");
|
|
2662
2563
|
f2.success(`${serverName}: ${status}`);
|
|
2663
2564
|
}
|
|
2664
2565
|
async function addMCPServer(configPath, config) {
|
|
@@ -2724,7 +2625,7 @@ async function addMCPServer(configPath, config) {
|
|
|
2724
2625
|
};
|
|
2725
2626
|
}
|
|
2726
2627
|
saveConfig(configPath, config);
|
|
2727
|
-
f2.success(`Added MCP server: ${
|
|
2628
|
+
f2.success(`Added MCP server: ${import_picocolors6.default.cyan(serverName)}`);
|
|
2728
2629
|
}
|
|
2729
2630
|
async function removeMCP(configPath, config) {
|
|
2730
2631
|
const servers = Object.keys(config.mcp || {}).map((name) => ({
|
|
@@ -2755,13 +2656,13 @@ async function editPermissions(configPath) {
|
|
|
2755
2656
|
config.permission = {};
|
|
2756
2657
|
}
|
|
2757
2658
|
console.log();
|
|
2758
|
-
console.log(
|
|
2759
|
-
console.log(` edit: ${
|
|
2760
|
-
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")}`);
|
|
2761
2662
|
if (config.permission.bash) {
|
|
2762
|
-
console.log(
|
|
2663
|
+
console.log(import_picocolors6.default.bold(" Bash"));
|
|
2763
2664
|
for (const [pattern, perm] of Object.entries(config.permission.bash)) {
|
|
2764
|
-
console.log(` ${
|
|
2665
|
+
console.log(` ${import_picocolors6.default.dim(pattern)}: ${import_picocolors6.default.cyan(perm)}`);
|
|
2765
2666
|
}
|
|
2766
2667
|
}
|
|
2767
2668
|
console.log();
|
|
@@ -2823,9 +2724,9 @@ async function editKeybinds(configPath) {
|
|
|
2823
2724
|
}
|
|
2824
2725
|
if (Object.keys(config.keybinds).length > 0) {
|
|
2825
2726
|
console.log();
|
|
2826
|
-
console.log(
|
|
2727
|
+
console.log(import_picocolors6.default.bold(" Current Keybinds"));
|
|
2827
2728
|
for (const [action2, key] of Object.entries(config.keybinds)) {
|
|
2828
|
-
console.log(` ${
|
|
2729
|
+
console.log(` ${import_picocolors6.default.dim(action2)}: ${import_picocolors6.default.cyan(key)}`);
|
|
2829
2730
|
}
|
|
2830
2731
|
console.log();
|
|
2831
2732
|
}
|
|
@@ -2878,7 +2779,7 @@ async function editKeybinds(configPath) {
|
|
|
2878
2779
|
}
|
|
2879
2780
|
config.keybinds[keybindName] = newKey;
|
|
2880
2781
|
saveConfig(configPath, config);
|
|
2881
|
-
f2.success(`${keybindName} → ${
|
|
2782
|
+
f2.success(`${keybindName} → ${import_picocolors6.default.cyan(newKey)}`);
|
|
2882
2783
|
}
|
|
2883
2784
|
var OPENCODE_THEMES = [
|
|
2884
2785
|
{ value: "system", label: "System", hint: "follows OS preference" },
|
|
@@ -2918,7 +2819,7 @@ var OPENCODE_THEMES = [
|
|
|
2918
2819
|
async function editTheme(configPath) {
|
|
2919
2820
|
const config = loadConfig(configPath);
|
|
2920
2821
|
const currentTheme = config.theme || "system";
|
|
2921
|
-
f2.info(`Current theme: ${
|
|
2822
|
+
f2.info(`Current theme: ${import_picocolors6.default.cyan(currentTheme)}`);
|
|
2922
2823
|
const validTheme = OPENCODE_THEMES.some((t) => t.value === currentTheme) ? currentTheme : "system";
|
|
2923
2824
|
const selectedTheme = await ie({
|
|
2924
2825
|
message: "Select theme",
|
|
@@ -2935,7 +2836,7 @@ async function editTheme(configPath) {
|
|
|
2935
2836
|
}
|
|
2936
2837
|
config.theme = selectedTheme;
|
|
2937
2838
|
saveConfig(configPath, config);
|
|
2938
|
-
f2.success(`Theme set to ${
|
|
2839
|
+
f2.success(`Theme set to ${import_picocolors6.default.cyan(selectedTheme)}`);
|
|
2939
2840
|
}
|
|
2940
2841
|
async function editTui(configPath) {
|
|
2941
2842
|
const config = loadConfig(configPath);
|
|
@@ -2983,7 +2884,7 @@ async function editTui(configPath) {
|
|
|
2983
2884
|
}
|
|
2984
2885
|
config.tui.diff_style = style;
|
|
2985
2886
|
saveConfig(configPath, config);
|
|
2986
|
-
f2.success(`Diff style set to ${
|
|
2887
|
+
f2.success(`Diff style set to ${import_picocolors6.default.cyan(style)}`);
|
|
2987
2888
|
} else {
|
|
2988
2889
|
const settingKey = setting;
|
|
2989
2890
|
const value = await te({
|
|
@@ -3000,7 +2901,7 @@ async function editTui(configPath) {
|
|
|
3000
2901
|
}
|
|
3001
2902
|
config.tui[settingKey] = value ? Number(value) : undefined;
|
|
3002
2903
|
saveConfig(configPath, config);
|
|
3003
|
-
f2.success(`${settingKey} set to ${
|
|
2904
|
+
f2.success(`${settingKey} set to ${import_picocolors6.default.cyan(value || "default")}`);
|
|
3004
2905
|
}
|
|
3005
2906
|
}
|
|
3006
2907
|
async function editTools(configPath) {
|
|
@@ -3020,9 +2921,9 @@ async function editTools(configPath) {
|
|
|
3020
2921
|
"todoread"
|
|
3021
2922
|
];
|
|
3022
2923
|
console.log();
|
|
3023
|
-
console.log(
|
|
2924
|
+
console.log(import_picocolors6.default.bold(" Tool Status"));
|
|
3024
2925
|
for (const tool of commonTools) {
|
|
3025
|
-
const status = config.tools[tool] === false ?
|
|
2926
|
+
const status = config.tools[tool] === false ? import_picocolors6.default.red("off") : import_picocolors6.default.green("on");
|
|
3026
2927
|
console.log(` ${status} ${tool}`);
|
|
3027
2928
|
}
|
|
3028
2929
|
console.log();
|
|
@@ -3056,7 +2957,7 @@ async function editTools(configPath) {
|
|
|
3056
2957
|
const wasEnabled = config.tools[toolName] !== false;
|
|
3057
2958
|
config.tools[toolName] = !wasEnabled;
|
|
3058
2959
|
saveConfig(configPath, config);
|
|
3059
|
-
const status = config.tools[toolName] ?
|
|
2960
|
+
const status = config.tools[toolName] ? import_picocolors6.default.green("enabled") : import_picocolors6.default.red("disabled");
|
|
3060
2961
|
f2.success(`${toolName}: ${status}`);
|
|
3061
2962
|
} else {
|
|
3062
2963
|
const toolName = await te({
|
|
@@ -3079,13 +2980,13 @@ async function editTools(configPath) {
|
|
|
3079
2980
|
}
|
|
3080
2981
|
config.tools[toolName] = enabled;
|
|
3081
2982
|
saveConfig(configPath, config);
|
|
3082
|
-
f2.success(`Added ${toolName}: ${enabled ?
|
|
2983
|
+
f2.success(`Added ${toolName}: ${enabled ? import_picocolors6.default.green("on") : import_picocolors6.default.red("off")}`);
|
|
3083
2984
|
}
|
|
3084
2985
|
}
|
|
3085
2986
|
async function editShare(configPath) {
|
|
3086
2987
|
const config = loadConfig(configPath);
|
|
3087
2988
|
const current = config.share || "manual";
|
|
3088
|
-
f2.info(`Current share setting: ${
|
|
2989
|
+
f2.info(`Current share setting: ${import_picocolors6.default.cyan(current)}`);
|
|
3089
2990
|
const selected = await ie({
|
|
3090
2991
|
message: "Share setting",
|
|
3091
2992
|
options: [
|
|
@@ -3108,13 +3009,13 @@ async function editShare(configPath) {
|
|
|
3108
3009
|
const shareValue = selected;
|
|
3109
3010
|
config.share = shareValue;
|
|
3110
3011
|
saveConfig(configPath, config);
|
|
3111
|
-
f2.success(`Share set to ${
|
|
3012
|
+
f2.success(`Share set to ${import_picocolors6.default.cyan(shareValue)}`);
|
|
3112
3013
|
}
|
|
3113
3014
|
async function editAutoupdate(configPath) {
|
|
3114
3015
|
const config = loadConfig(configPath);
|
|
3115
3016
|
const current = config.autoupdate ?? true;
|
|
3116
3017
|
const display = current === "notify" ? "notify" : current ? "enabled" : "disabled";
|
|
3117
|
-
f2.info(`Current autoupdate: ${
|
|
3018
|
+
f2.info(`Current autoupdate: ${import_picocolors6.default.cyan(display)}`);
|
|
3118
3019
|
const selected = await ie({
|
|
3119
3020
|
message: "Autoupdate behavior",
|
|
3120
3021
|
options: [
|
|
@@ -3145,69 +3046,366 @@ async function editAutoupdate(configPath) {
|
|
|
3145
3046
|
config.autoupdate = selectedValue === "true";
|
|
3146
3047
|
}
|
|
3147
3048
|
saveConfig(configPath, config);
|
|
3148
|
-
f2.success(`Autoupdate set to ${
|
|
3049
|
+
f2.success(`Autoupdate set to ${import_picocolors6.default.cyan(selectedValue)}`);
|
|
3149
3050
|
}
|
|
3150
3051
|
|
|
3151
|
-
// src/commands/
|
|
3152
|
-
import { join as join5, dirname as dirname2 } from "node:path";
|
|
3153
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3052
|
+
// src/commands/init.ts
|
|
3154
3053
|
import {
|
|
3155
|
-
existsSync as
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
copyFileSync
|
|
3054
|
+
existsSync as existsSync3,
|
|
3055
|
+
mkdirSync as mkdirSync2,
|
|
3056
|
+
readFileSync as readFileSync3,
|
|
3057
|
+
writeFileSync as writeFileSync3,
|
|
3058
|
+
readdirSync as readdirSync2
|
|
3161
3059
|
} from "node:fs";
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
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"
|
|
3165
3071
|
];
|
|
3166
|
-
var
|
|
3167
|
-
"
|
|
3168
|
-
"
|
|
3169
|
-
"
|
|
3072
|
+
var EXCLUDED_FILES = [
|
|
3073
|
+
"bun.lock",
|
|
3074
|
+
"package-lock.json",
|
|
3075
|
+
"yarn.lock",
|
|
3076
|
+
"pnpm-lock.yaml"
|
|
3170
3077
|
];
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
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);
|
|
3175
3095
|
const possiblePaths = [
|
|
3176
|
-
|
|
3177
|
-
|
|
3096
|
+
join3(__dirname2, "template"),
|
|
3097
|
+
join3(__dirname2, "..", "..", ".opencode")
|
|
3178
3098
|
];
|
|
3179
3099
|
for (const path of possiblePaths) {
|
|
3180
|
-
const opencodeDir =
|
|
3181
|
-
if (
|
|
3100
|
+
const opencodeDir = join3(path, ".opencode");
|
|
3101
|
+
if (existsSync3(opencodeDir)) {
|
|
3182
3102
|
return path;
|
|
3183
3103
|
}
|
|
3184
3104
|
}
|
|
3185
3105
|
return null;
|
|
3186
3106
|
}
|
|
3187
|
-
function
|
|
3188
|
-
const
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
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);
|
|
3205
3124
|
}
|
|
3206
3125
|
}
|
|
3207
|
-
return "unknown";
|
|
3208
3126
|
}
|
|
3209
|
-
async function
|
|
3210
|
-
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);
|
|
3211
3409
|
const latest = getPackageVersion();
|
|
3212
3410
|
return {
|
|
3213
3411
|
current,
|
|
@@ -3283,23 +3481,23 @@ async function upgradeCommand(options = {}) {
|
|
|
3283
3481
|
notInitialized();
|
|
3284
3482
|
return;
|
|
3285
3483
|
}
|
|
3286
|
-
oe(
|
|
3484
|
+
oe(import_picocolors9.default.bgCyan(import_picocolors9.default.black(" Upgrade ")));
|
|
3287
3485
|
const versionInfo = await checkVersion(opencodeDir);
|
|
3288
3486
|
console.log();
|
|
3289
|
-
console.log(` ${
|
|
3290
|
-
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")}`);
|
|
3291
3489
|
console.log();
|
|
3292
3490
|
if (options.check) {
|
|
3293
3491
|
if (versionInfo.needsUpdate) {
|
|
3294
|
-
f2.info(`Update available: ${
|
|
3295
|
-
$e(`Run ${
|
|
3492
|
+
f2.info(`Update available: ${import_picocolors9.default.cyan(versionInfo.latest)}`);
|
|
3493
|
+
$e(`Run ${import_picocolors9.default.cyan("ock upgrade")} to update`);
|
|
3296
3494
|
} else {
|
|
3297
|
-
$e(
|
|
3495
|
+
$e(import_picocolors9.default.green("Already up to date"));
|
|
3298
3496
|
}
|
|
3299
3497
|
return;
|
|
3300
3498
|
}
|
|
3301
3499
|
if (!versionInfo.needsUpdate && !options.force) {
|
|
3302
|
-
$e(
|
|
3500
|
+
$e(import_picocolors9.default.green("Already up to date"));
|
|
3303
3501
|
return;
|
|
3304
3502
|
}
|
|
3305
3503
|
const templateRoot = getTemplateRoot2();
|
|
@@ -3335,205 +3533,10 @@ async function upgradeCommand(options = {}) {
|
|
|
3335
3533
|
f2.info(`Preserved ${result.preserved.length} user files`);
|
|
3336
3534
|
}
|
|
3337
3535
|
le("cd .opencode && bun install", "Run if dependencies changed");
|
|
3338
|
-
$e(
|
|
3339
|
-
}
|
|
3340
|
-
|
|
3341
|
-
// src/commands/completion.ts
|
|
3342
|
-
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
3343
|
-
var BASH_COMPLETION = `# ock bash completion
|
|
3344
|
-
_ock_completion() {
|
|
3345
|
-
local cur prev commands
|
|
3346
|
-
COMPREPLY=()
|
|
3347
|
-
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
3348
|
-
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
3349
|
-
|
|
3350
|
-
commands="init config upgrade agent skill doctor status help"
|
|
3351
|
-
|
|
3352
|
-
case "\${prev}" in
|
|
3353
|
-
ock)
|
|
3354
|
-
COMPREPLY=( $(compgen -W "\${commands}" -- "\${cur}") )
|
|
3355
|
-
return 0
|
|
3356
|
-
;;
|
|
3357
|
-
agent)
|
|
3358
|
-
COMPREPLY=( $(compgen -W "list add view" -- "\${cur}") )
|
|
3359
|
-
return 0
|
|
3360
|
-
;;
|
|
3361
|
-
skill)
|
|
3362
|
-
COMPREPLY=( $(compgen -W "list add view" -- "\${cur}") )
|
|
3363
|
-
return 0
|
|
3364
|
-
;;
|
|
3365
|
-
config)
|
|
3366
|
-
COMPREPLY=( $(compgen -W "model mcp permission keybinds show" -- "\${cur}") )
|
|
3367
|
-
return 0
|
|
3368
|
-
;;
|
|
3369
|
-
init)
|
|
3370
|
-
COMPREPLY=( $(compgen -W "--force" -- "\${cur}") )
|
|
3371
|
-
return 0
|
|
3372
|
-
;;
|
|
3373
|
-
upgrade)
|
|
3374
|
-
COMPREPLY=( $(compgen -W "--force --check" -- "\${cur}") )
|
|
3375
|
-
return 0
|
|
3376
|
-
;;
|
|
3377
|
-
*)
|
|
3378
|
-
;;
|
|
3379
|
-
esac
|
|
3380
|
-
}
|
|
3381
|
-
complete -F _ock_completion ock
|
|
3382
|
-
`;
|
|
3383
|
-
var ZSH_COMPLETION = `#compdef ock
|
|
3384
|
-
|
|
3385
|
-
_ock() {
|
|
3386
|
-
local -a commands
|
|
3387
|
-
local -a agent_actions
|
|
3388
|
-
local -a skill_actions
|
|
3389
|
-
local -a config_actions
|
|
3390
|
-
|
|
3391
|
-
commands=(
|
|
3392
|
-
'init:Initialize OpenCodeKit in current directory'
|
|
3393
|
-
'config:Edit opencode.json'
|
|
3394
|
-
'upgrade:Update templates to latest version'
|
|
3395
|
-
'agent:Manage agents'
|
|
3396
|
-
'skill:Manage skills'
|
|
3397
|
-
'doctor:Check project health'
|
|
3398
|
-
'status:Show project overview'
|
|
3399
|
-
'help:Show help'
|
|
3400
|
-
)
|
|
3401
|
-
|
|
3402
|
-
agent_actions=(
|
|
3403
|
-
'list:List all agents'
|
|
3404
|
-
'add:Create a new agent'
|
|
3405
|
-
'view:View agent details'
|
|
3406
|
-
)
|
|
3407
|
-
|
|
3408
|
-
skill_actions=(
|
|
3409
|
-
'list:List all skills'
|
|
3410
|
-
'add:Install a skill'
|
|
3411
|
-
'view:View skill details'
|
|
3412
|
-
)
|
|
3413
|
-
|
|
3414
|
-
config_actions=(
|
|
3415
|
-
'model:Change default model'
|
|
3416
|
-
'mcp:Manage MCP servers'
|
|
3417
|
-
'permission:Edit permissions'
|
|
3418
|
-
'keybinds:Edit keyboard shortcuts'
|
|
3419
|
-
'show:View current config'
|
|
3420
|
-
)
|
|
3421
|
-
|
|
3422
|
-
case "$words[2]" in
|
|
3423
|
-
agent)
|
|
3424
|
-
_describe -t actions 'agent action' agent_actions
|
|
3425
|
-
;;
|
|
3426
|
-
skill)
|
|
3427
|
-
_describe -t actions 'skill action' skill_actions
|
|
3428
|
-
;;
|
|
3429
|
-
config)
|
|
3430
|
-
_describe -t actions 'config action' config_actions
|
|
3431
|
-
;;
|
|
3432
|
-
init)
|
|
3433
|
-
_arguments '--force[Reinitialize even if already exists]'
|
|
3434
|
-
;;
|
|
3435
|
-
upgrade)
|
|
3436
|
-
_arguments \\
|
|
3437
|
-
'--force[Force upgrade even if up to date]' \\
|
|
3438
|
-
'--check[Check for updates only]'
|
|
3439
|
-
;;
|
|
3440
|
-
*)
|
|
3441
|
-
_describe -t commands 'command' commands
|
|
3442
|
-
;;
|
|
3443
|
-
esac
|
|
3444
|
-
}
|
|
3445
|
-
|
|
3446
|
-
_ock "$@"
|
|
3447
|
-
`;
|
|
3448
|
-
var FISH_COMPLETION = `# ock fish completion
|
|
3449
|
-
complete -c ock -n "__fish_use_subcommand" -a "init" -d "Initialize OpenCodeKit"
|
|
3450
|
-
complete -c ock -n "__fish_use_subcommand" -a "config" -d "Edit opencode.json"
|
|
3451
|
-
complete -c ock -n "__fish_use_subcommand" -a "upgrade" -d "Update templates"
|
|
3452
|
-
complete -c ock -n "__fish_use_subcommand" -a "agent" -d "Manage agents"
|
|
3453
|
-
complete -c ock -n "__fish_use_subcommand" -a "skill" -d "Manage skills"
|
|
3454
|
-
complete -c ock -n "__fish_use_subcommand" -a "doctor" -d "Check project health"
|
|
3455
|
-
complete -c ock -n "__fish_use_subcommand" -a "status" -d "Show project overview"
|
|
3456
|
-
|
|
3457
|
-
# agent subcommands
|
|
3458
|
-
complete -c ock -n "__fish_seen_subcommand_from agent" -a "list" -d "List agents"
|
|
3459
|
-
complete -c ock -n "__fish_seen_subcommand_from agent" -a "add" -d "Add agent"
|
|
3460
|
-
complete -c ock -n "__fish_seen_subcommand_from agent" -a "view" -d "View agent"
|
|
3461
|
-
|
|
3462
|
-
# skill subcommands
|
|
3463
|
-
complete -c ock -n "__fish_seen_subcommand_from skill" -a "list" -d "List skills"
|
|
3464
|
-
complete -c ock -n "__fish_seen_subcommand_from skill" -a "add" -d "Add skill"
|
|
3465
|
-
complete -c ock -n "__fish_seen_subcommand_from skill" -a "view" -d "View skill"
|
|
3466
|
-
|
|
3467
|
-
# config subcommands
|
|
3468
|
-
complete -c ock -n "__fish_seen_subcommand_from config" -a "model" -d "Change model"
|
|
3469
|
-
complete -c ock -n "__fish_seen_subcommand_from config" -a "mcp" -d "Manage MCP"
|
|
3470
|
-
complete -c ock -n "__fish_seen_subcommand_from config" -a "permission" -d "Edit permissions"
|
|
3471
|
-
complete -c ock -n "__fish_seen_subcommand_from config" -a "keybinds" -d "Edit keybinds"
|
|
3472
|
-
complete -c ock -n "__fish_seen_subcommand_from config" -a "show" -d "View config"
|
|
3473
|
-
|
|
3474
|
-
# init options
|
|
3475
|
-
complete -c ock -n "__fish_seen_subcommand_from init" -l force -d "Reinitialize"
|
|
3476
|
-
|
|
3477
|
-
# upgrade options
|
|
3478
|
-
complete -c ock -n "__fish_seen_subcommand_from upgrade" -l force -d "Force upgrade"
|
|
3479
|
-
complete -c ock -n "__fish_seen_subcommand_from upgrade" -l check -d "Check only"
|
|
3480
|
-
`;
|
|
3481
|
-
async function completionCommand(shell) {
|
|
3482
|
-
if (!shell) {
|
|
3483
|
-
oe(import_picocolors9.default.bgCyan(import_picocolors9.default.black(" Shell Completion ")));
|
|
3484
|
-
const selected = await ie({
|
|
3485
|
-
message: "Select your shell",
|
|
3486
|
-
options: [
|
|
3487
|
-
{ value: "bash", label: "Bash" },
|
|
3488
|
-
{ value: "zsh", label: "Zsh" },
|
|
3489
|
-
{ value: "fish", label: "Fish" }
|
|
3490
|
-
]
|
|
3491
|
-
});
|
|
3492
|
-
if (lD(selected)) {
|
|
3493
|
-
ue("Cancelled");
|
|
3494
|
-
return;
|
|
3495
|
-
}
|
|
3496
|
-
shell = selected;
|
|
3497
|
-
}
|
|
3498
|
-
let script;
|
|
3499
|
-
let setupInstructions;
|
|
3500
|
-
switch (shell) {
|
|
3501
|
-
case "bash":
|
|
3502
|
-
script = BASH_COMPLETION;
|
|
3503
|
-
setupInstructions = `Add to ~/.bashrc:
|
|
3504
|
-
source <(ock completion bash)
|
|
3505
|
-
|
|
3506
|
-
Or save to file:
|
|
3507
|
-
ock completion bash > ~/.local/share/bash-completion/completions/ock`;
|
|
3508
|
-
break;
|
|
3509
|
-
case "zsh":
|
|
3510
|
-
script = ZSH_COMPLETION;
|
|
3511
|
-
setupInstructions = `Add to ~/.zshrc (before compinit):
|
|
3512
|
-
source <(ock completion zsh)
|
|
3513
|
-
|
|
3514
|
-
Or save to fpath:
|
|
3515
|
-
ock completion zsh > ~/.zsh/completions/_ock
|
|
3516
|
-
# Then add to ~/.zshrc: fpath=(~/.zsh/completions $fpath)`;
|
|
3517
|
-
break;
|
|
3518
|
-
case "fish":
|
|
3519
|
-
script = FISH_COMPLETION;
|
|
3520
|
-
setupInstructions = `Save to fish completions:
|
|
3521
|
-
ock completion fish > ~/.config/fish/completions/ock.fish`;
|
|
3522
|
-
break;
|
|
3523
|
-
default:
|
|
3524
|
-
f2.error(`Unknown shell: ${shell}`);
|
|
3525
|
-
return;
|
|
3526
|
-
}
|
|
3527
|
-
console.log(script);
|
|
3528
|
-
console.error();
|
|
3529
|
-
console.error(import_picocolors9.default.bold("Setup:"));
|
|
3530
|
-
console.error(import_picocolors9.default.dim(setupInstructions));
|
|
3536
|
+
$e(import_picocolors9.default.green(`Upgraded to ${versionInfo.latest}`));
|
|
3531
3537
|
}
|
|
3532
3538
|
|
|
3533
3539
|
// src/commands/menu.ts
|
|
3534
|
-
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
3535
|
-
import { existsSync as existsSync6, readdirSync as readdirSync5, lstatSync as lstatSync3 } from "node:fs";
|
|
3536
|
-
import { join as join6, basename as basename2 } from "node:path";
|
|
3537
3540
|
async function interactiveMenu(version) {
|
|
3538
3541
|
oe(import_picocolors10.default.bgCyan(import_picocolors10.default.black(` OpenCodeKit v${version} `)));
|
|
3539
3542
|
const action = await ie({
|