@cardor/agent-harness-kit 2.0.0 → 2.1.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/cli.js CHANGED
@@ -380,6 +380,17 @@ function mergeCodexConfigToml(filePath, port, cwd2, pm = "npm") {
380
380
  content = mergeTomlSection(content, "mcp_servers.agent-harness-kit", sectionBody);
381
381
  writeFileSync2(filePath, content, "utf8");
382
382
  }
383
+ function mergeGrokConfigToml(filePath, port, cwd2, pm = "npm") {
384
+ mkdirSync2(dirname2(filePath), { recursive: true });
385
+ let content = "";
386
+ if (existsSync4(filePath)) {
387
+ content = readFileSync3(filePath, "utf8");
388
+ }
389
+ const [command, ...args] = getMcpCommandParts(pm, port, cwd2);
390
+ const sectionBody = [`command = ${JSON.stringify(command)}`, `args = ${JSON.stringify(args)}`].join("\n");
391
+ content = mergeTomlSection(content, "mcp_servers.agent-harness-kit", sectionBody);
392
+ writeFileSync2(filePath, content, "utf8");
393
+ }
383
394
 
384
395
  // src/core/materializer/scaffold-utils.ts
385
396
  import { createHash } from "crypto";
@@ -420,6 +431,9 @@ These tools may still appear available to you. The sandbox will reject the call.
420
431
  function codexRestrictionNotice(agentName) {
421
432
  return restrictionFor(agentName) === "no-write" ? CODEX_READ_ONLY_NOTICE : "";
422
433
  }
434
+ function grokToolsAllowlist(agentName) {
435
+ return restrictionFor(agentName) === "no-write" ? ["Bash", "Read", "NotebookRead", "Grep", "Glob", "WebFetch", "WebSearch", "search_tool", "use_tool"] : [];
436
+ }
423
437
 
424
438
  // src/core/materializer/templates.ts
425
439
  var __dirname = dirname3(fileURLToPath2(import.meta.url));
@@ -849,6 +863,11 @@ function translateFrontmatterForOpenCode(md, agentName) {
849
863
  result = stripFrontmatterBlockSequence(result, "disallowedTools");
850
864
  return appendFrontmatterMapping(result, "permission", opencodePermissions(agentName));
851
865
  }
866
+ function translateFrontmatterForGrok(md, agentName) {
867
+ let result = stripFrontmatterBlockSequence(md, "tools");
868
+ result = stripFrontmatterBlockSequence(result, "disallowedTools");
869
+ return appendFrontmatterBlockSequence(result, "tools", grokToolsAllowlist(agentName));
870
+ }
852
871
  var GITIGNORE_ENTRIES = `
853
872
  # agent-harness-kit
854
873
  .harness/harness.db
@@ -1163,9 +1182,73 @@ No tasks in progress.
1163
1182
  }
1164
1183
  };
1165
1184
 
1166
- // src/core/materializer/opencode.ts
1185
+ // src/core/materializer/grok.ts
1167
1186
  import { existsSync as existsSync8, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5 } from "fs";
1168
1187
  import { join as join9, resolve as resolve4 } from "path";
1188
+ function grokAgentFiles(config) {
1189
+ const projectName = config.project.name;
1190
+ return [
1191
+ { relPath: ".grok/agents/lead.md", content: translateFrontmatterForGrok(agentLead({ projectName }), "lead") },
1192
+ { relPath: ".grok/agents/explorer.md", content: translateFrontmatterForGrok(agentExplorer({ projectName }), "explorer") },
1193
+ { relPath: ".grok/agents/consultant.md", content: translateFrontmatterForGrok(agentConsultant({ projectName }), "consultant") },
1194
+ { relPath: ".grok/agents/builder.md", content: translateFrontmatterForGrok(agentBuilder({ projectName }), "builder") },
1195
+ { relPath: ".grok/agents/reviewer.md", content: translateFrontmatterForGrok(agentReviewer({ projectName }), "reviewer") }
1196
+ ];
1197
+ }
1198
+ var GrokMaterializer = class {
1199
+ async scaffold(config, opts) {
1200
+ const { cwd: cwd2 } = opts;
1201
+ const write2 = (relPath, content, mode) => {
1202
+ const abs = join9(cwd2, relPath);
1203
+ mkdirSync5(resolve4(abs, ".."), { recursive: true });
1204
+ writeFileSync5(abs, content, { encoding: "utf8", mode });
1205
+ };
1206
+ write2("AGENTS.md", stampGenerated(agentsMd(config)));
1207
+ if (!existsSync8(join9(cwd2, "health.sh"))) {
1208
+ write2("health.sh", HEALTH_SH, 493);
1209
+ }
1210
+ if (config.storage.scope === "local" && !existsSync8(join9(cwd2, config.storage.markdownFallback.path))) {
1211
+ write2(
1212
+ config.storage.markdownFallback.path,
1213
+ `<!-- AUTO-GENERATED by agent-harness-kit \u2014 DO NOT EDIT MANUALLY -->
1214
+ <!-- Run ahk status to refresh -->
1215
+
1216
+ # Current Session
1217
+
1218
+ No tasks in progress.
1219
+ `
1220
+ );
1221
+ }
1222
+ writeAgentFiles(cwd2, grokAgentFiles(config));
1223
+ mergeGrokConfigToml(join9(cwd2, ".grok/config.toml"), config.tools.mcp.port, cwd2, detectPackageManager(cwd2));
1224
+ appendGitignore(cwd2);
1225
+ writeSkills(cwd2, ".grok/skills");
1226
+ }
1227
+ async build(config, cwd2, opts = {}) {
1228
+ const derived = reconcileGeneratedFiles(
1229
+ cwd2,
1230
+ [{ relPath: "AGENTS.md", content: agentsMd(config) }],
1231
+ { force: opts.force, backupRoot: join9(cwd2, config.storage.dir, "backups") }
1232
+ );
1233
+ const agents = writeAgentFiles(cwd2, grokAgentFiles(config), {
1234
+ force: opts.force,
1235
+ backupRoot: join9(cwd2, config.storage.dir, "backups")
1236
+ });
1237
+ mergeGrokConfigToml(join9(cwd2, ".grok/config.toml"), config.tools.mcp.port, cwd2, detectPackageManager(cwd2));
1238
+ writeSkills(cwd2, ".grok/skills");
1239
+ return { agents, derived };
1240
+ }
1241
+ async migrate(config, _to, _cwd) {
1242
+ void config;
1243
+ }
1244
+ async syncPermissions(_cwd) {
1245
+ console.log(" Permissions sync not needed for grok-cli \u2014 skipping");
1246
+ }
1247
+ };
1248
+
1249
+ // src/core/materializer/opencode.ts
1250
+ import { existsSync as existsSync9, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "fs";
1251
+ import { join as join10, resolve as resolve5 } from "path";
1169
1252
  function opencodeAgentFiles(config) {
1170
1253
  const projectName = config.project.name;
1171
1254
  return [
@@ -1180,15 +1263,15 @@ var OpenCodeMaterializer = class {
1180
1263
  async scaffold(config, opts) {
1181
1264
  const { cwd: cwd2 } = opts;
1182
1265
  const write2 = (relPath, content, mode) => {
1183
- const abs = join9(cwd2, relPath);
1184
- mkdirSync5(resolve4(abs, ".."), { recursive: true });
1185
- writeFileSync5(abs, content, { encoding: "utf8", mode });
1266
+ const abs = join10(cwd2, relPath);
1267
+ mkdirSync6(resolve5(abs, ".."), { recursive: true });
1268
+ writeFileSync6(abs, content, { encoding: "utf8", mode });
1186
1269
  };
1187
1270
  write2("AGENTS.md", stampGenerated(agentsMd(config)));
1188
- if (!existsSync8(join9(cwd2, "health.sh"))) {
1271
+ if (!existsSync9(join10(cwd2, "health.sh"))) {
1189
1272
  write2("health.sh", HEALTH_SH, 493);
1190
1273
  }
1191
- if (config.storage.scope === "local" && !existsSync8(join9(cwd2, config.storage.markdownFallback.path))) {
1274
+ if (config.storage.scope === "local" && !existsSync9(join10(cwd2, config.storage.markdownFallback.path))) {
1192
1275
  write2(
1193
1276
  config.storage.markdownFallback.path,
1194
1277
  `<!-- AUTO-GENERATED by agent-harness-kit \u2014 DO NOT EDIT MANUALLY -->
@@ -1201,7 +1284,7 @@ No tasks in progress.
1201
1284
  );
1202
1285
  }
1203
1286
  writeAgentFiles(cwd2, opencodeAgentFiles(config));
1204
- mergeOpencodeJson(join9(cwd2, "opencode.json"), config.tools.mcp.port, cwd2, detectPackageManager(cwd2));
1287
+ mergeOpencodeJson(join10(cwd2, "opencode.json"), config.tools.mcp.port, cwd2, detectPackageManager(cwd2));
1205
1288
  appendGitignore(cwd2);
1206
1289
  writeSkills(cwd2, ".opencode/skills");
1207
1290
  }
@@ -1209,13 +1292,13 @@ No tasks in progress.
1209
1292
  const derived = reconcileGeneratedFiles(
1210
1293
  cwd2,
1211
1294
  [{ relPath: "AGENTS.md", content: agentsMd(config) }],
1212
- { force: opts.force, backupRoot: join9(cwd2, config.storage.dir, "backups") }
1295
+ { force: opts.force, backupRoot: join10(cwd2, config.storage.dir, "backups") }
1213
1296
  );
1214
1297
  const agents = writeAgentFiles(cwd2, opencodeAgentFiles(config), {
1215
1298
  force: opts.force,
1216
- backupRoot: join9(cwd2, config.storage.dir, "backups")
1299
+ backupRoot: join10(cwd2, config.storage.dir, "backups")
1217
1300
  });
1218
- mergeOpencodeJson(join9(cwd2, "opencode.json"), config.tools.mcp.port, cwd2, detectPackageManager(cwd2));
1301
+ mergeOpencodeJson(join10(cwd2, "opencode.json"), config.tools.mcp.port, cwd2, detectPackageManager(cwd2));
1219
1302
  writeSkills(cwd2, ".opencode/skills");
1220
1303
  return { agents, derived };
1221
1304
  }
@@ -1236,6 +1319,8 @@ function getMaterializer(provider) {
1236
1319
  return new OpenCodeMaterializer();
1237
1320
  case "codex-cli":
1238
1321
  return new CodexCliMaterializer();
1322
+ case "grok-cli":
1323
+ return new GrokMaterializer();
1239
1324
  default:
1240
1325
  throw new Error(`Unknown provider: ${provider}`);
1241
1326
  }
@@ -1335,14 +1420,14 @@ async function buildOnce(cwd2, force) {
1335
1420
 
1336
1421
  // src/commands/dashboard.ts
1337
1422
  import { homedir } from "os";
1338
- import { dirname as dirname5, join as join11 } from "path";
1423
+ import { dirname as dirname5, join as join12 } from "path";
1339
1424
  import { fileURLToPath as fileURLToPath4 } from "url";
1340
1425
  import pc3 from "picocolors";
1341
1426
 
1342
1427
  // src/core/dashboard-server.ts
1343
1428
  import { watch as watch2 } from "fs";
1344
- import { existsSync as existsSync9, readFileSync as readFileSync6 } from "fs";
1345
- import { extname, join as join10 } from "path";
1429
+ import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
1430
+ import { extname, join as join11 } from "path";
1346
1431
  import { serve } from "@hono/node-server";
1347
1432
  import { Hono } from "hono";
1348
1433
  import { WebSocketServer } from "ws";
@@ -1351,11 +1436,11 @@ import { WebSocketServer } from "ws";
1351
1436
  import { createServer } from "net";
1352
1437
  var DASHBOARD_BIND_HOST = void 0;
1353
1438
  function isPortFree(port, host = DASHBOARD_BIND_HOST) {
1354
- return new Promise((resolve11) => {
1439
+ return new Promise((resolve12) => {
1355
1440
  const server = createServer();
1356
- server.once("error", () => resolve11(false));
1441
+ server.once("error", () => resolve12(false));
1357
1442
  server.once("listening", () => {
1358
- server.close(() => resolve11(true));
1443
+ server.close(() => resolve12(true));
1359
1444
  });
1360
1445
  server.listen(port, host);
1361
1446
  });
@@ -1398,7 +1483,7 @@ function fileResponse(filePath) {
1398
1483
  });
1399
1484
  }
1400
1485
  function awaitServerListening(server, port) {
1401
- return new Promise((resolve11, reject) => {
1486
+ return new Promise((resolve12, reject) => {
1402
1487
  const closeQuietly = () => {
1403
1488
  try {
1404
1489
  server.close(() => {
@@ -1421,7 +1506,7 @@ function awaitServerListening(server, port) {
1421
1506
  };
1422
1507
  const onListening = () => {
1423
1508
  server.off("error", onError);
1424
- resolve11();
1509
+ resolve12();
1425
1510
  };
1426
1511
  server.once("error", onError);
1427
1512
  server.once("listening", onListening);
@@ -1527,15 +1612,15 @@ async function startDashboardServer(db, dbPath, staticPath, port) {
1527
1612
  app.get("/*", (c) => {
1528
1613
  const urlPath = c.req.path;
1529
1614
  if (urlPath !== "/") {
1530
- const candidate = join10(staticPath, urlPath);
1531
- if (existsSync9(candidate)) {
1615
+ const candidate = join11(staticPath, urlPath);
1616
+ if (existsSync10(candidate)) {
1532
1617
  try {
1533
1618
  return fileResponse(candidate);
1534
1619
  } catch {
1535
1620
  }
1536
1621
  }
1537
1622
  }
1538
- return fileResponse(join10(staticPath, "index.html"));
1623
+ return fileResponse(join11(staticPath, "index.html"));
1539
1624
  });
1540
1625
  const resolvedPort = await findFreePort(port, { host: DASHBOARD_BIND_HOST });
1541
1626
  if (resolvedPort !== port) {
@@ -1574,7 +1659,7 @@ async function startDashboardServer(db, dbPath, staticPath, port) {
1574
1659
  let watcher = null;
1575
1660
  if (dbPath) {
1576
1661
  const walPath = `${dbPath}-wal`;
1577
- const watchTarget = existsSync9(walPath) ? walPath : dbPath;
1662
+ const watchTarget = existsSync10(walPath) ? walPath : dbPath;
1578
1663
  watcher = watch2(watchTarget, broadcast);
1579
1664
  }
1580
1665
  return {
@@ -1594,7 +1679,7 @@ async function runDashboard(cwd2, opts) {
1594
1679
  const config = await loadConfig(cwd2);
1595
1680
  const db = await openDB(config, cwd2);
1596
1681
  const dbPath = config.database.type === "sqlite" ? resolveSqlitePath(config, cwd2, homedir()) : null;
1597
- const staticPath = join11(__dirname3, "dashboard-dist");
1682
+ const staticPath = join12(__dirname3, "dashboard-dist");
1598
1683
  const { url } = await startDashboardServer(db, dbPath, staticPath, opts.port);
1599
1684
  console.log(pc3.green(`\u2713`) + ` Dashboard running at ${pc3.bold(pc3.cyan(url))}`);
1600
1685
  console.log(pc3.dim(` WebSocket live updates enabled`));
@@ -1614,8 +1699,8 @@ async function runDashboard(cwd2, opts) {
1614
1699
  import pc4 from "picocolors";
1615
1700
 
1616
1701
  // src/core/doctor.ts
1617
- import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
1618
- import { dirname as dirname6, join as join12 } from "path";
1702
+ import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
1703
+ import { dirname as dirname6, join as join13 } from "path";
1619
1704
  import { fileURLToPath as fileURLToPath5 } from "url";
1620
1705
  var REGISTRY_URL = `https://registry.npmjs.org/${pkg.name}/latest`;
1621
1706
  var TIMEOUT_MS = 2e3;
@@ -1664,19 +1749,21 @@ function getProviderAgentInfo(provider) {
1664
1749
  return { agentsDir: ".opencode/agents", ext: ".md" };
1665
1750
  case "codex-cli":
1666
1751
  return { agentsDir: ".codex/agents", ext: ".toml" };
1752
+ case "grok-cli":
1753
+ return { agentsDir: ".grok/agents", ext: ".md" };
1667
1754
  default:
1668
1755
  return { agentsDir: ".claude/agents", ext: ".md" };
1669
1756
  }
1670
1757
  }
1671
1758
  function checkAgentFilesAtRoot(agentsRoot, ext) {
1672
1759
  return AGENT_NAMES.map((name) => {
1673
- const filePath = join12(agentsRoot, `${name}${ext}`);
1674
- return { name, status: existsSync10(filePath) ? "ok" : "missing" };
1760
+ const filePath = join13(agentsRoot, `${name}${ext}`);
1761
+ return { name, status: existsSync11(filePath) ? "ok" : "missing" };
1675
1762
  });
1676
1763
  }
1677
1764
  function checkAgentFiles(cwd2, provider) {
1678
1765
  const { agentsDir, ext } = getProviderAgentInfo(provider);
1679
- return checkAgentFilesAtRoot(join12(cwd2, agentsDir), ext);
1766
+ return checkAgentFilesAtRoot(join13(cwd2, agentsDir), ext);
1680
1767
  }
1681
1768
  function getProviderSkillsDir(provider) {
1682
1769
  switch (provider) {
@@ -1686,16 +1773,18 @@ function getProviderSkillsDir(provider) {
1686
1773
  return ".opencode/skills";
1687
1774
  case "codex-cli":
1688
1775
  return ".agents/skills";
1776
+ case "grok-cli":
1777
+ return ".grok/skills";
1689
1778
  default:
1690
1779
  return ".claude/skills";
1691
1780
  }
1692
1781
  }
1693
1782
  function checkSkillsAtRoot(skillsRoot) {
1694
- const skillSourceBase = join12(__dirname4, "skills");
1783
+ const skillSourceBase = join13(__dirname4, "skills");
1695
1784
  return SKILL_NAMES.map((name) => {
1696
- const livePath = join12(skillsRoot, name, "SKILL.md");
1697
- const sourcePath = join12(skillSourceBase, name, "SKILL.md");
1698
- if (!existsSync10(livePath)) {
1785
+ const livePath = join13(skillsRoot, name, "SKILL.md");
1786
+ const sourcePath = join13(skillSourceBase, name, "SKILL.md");
1787
+ if (!existsSync11(livePath)) {
1699
1788
  return { name, status: "missing" };
1700
1789
  }
1701
1790
  try {
@@ -1709,7 +1798,7 @@ function checkSkillsAtRoot(skillsRoot) {
1709
1798
  }
1710
1799
  function checkSkills(cwd2, provider) {
1711
1800
  const skillsDir = getProviderSkillsDir(provider);
1712
- return checkSkillsAtRoot(join12(cwd2, skillsDir));
1801
+ return checkSkillsAtRoot(join13(cwd2, skillsDir));
1713
1802
  }
1714
1803
  async function getDoctorStatus(cwd2) {
1715
1804
  const lib = await checkLibVersion();
@@ -1810,7 +1899,7 @@ async function runDoctor(cwd2) {
1810
1899
  }
1811
1900
 
1812
1901
  // src/commands/export.ts
1813
- import { writeFileSync as writeFileSync6 } from "fs";
1902
+ import { writeFileSync as writeFileSync7 } from "fs";
1814
1903
  import pc5 from "picocolors";
1815
1904
  async function runExport(cwd2, opts) {
1816
1905
  if (!opts.sql && !opts.json) {
@@ -1824,7 +1913,7 @@ async function runExport(cwd2, opts) {
1824
1913
  const data = await db.exportJson();
1825
1914
  const out = JSON.stringify(data, null, 2) + "\n";
1826
1915
  if (opts.output) {
1827
- writeFileSync6(opts.output, out, "utf8");
1916
+ writeFileSync7(opts.output, out, "utf8");
1828
1917
  console.log(pc5.green(`\u2713 Exported JSON \u2192 ${opts.output}`));
1829
1918
  } else {
1830
1919
  process.stdout.write(out);
@@ -1841,9 +1930,9 @@ async function runExport(cwd2, opts) {
1841
1930
 
1842
1931
  // src/commands/health.ts
1843
1932
  import { spawnSync } from "child_process";
1844
- import { existsSync as existsSync11 } from "fs";
1933
+ import { existsSync as existsSync12 } from "fs";
1845
1934
  import { homedir as homedir2 } from "os";
1846
- import { join as join13, resolve as resolve5 } from "path";
1935
+ import { join as join14, resolve as resolve6 } from "path";
1847
1936
  import pc6 from "picocolors";
1848
1937
  function checkLine(label, ok3, message, indent = 0) {
1849
1938
  const prefix = label ? pc6.cyan(`[${label}] `) : " ".repeat(indent);
@@ -1862,7 +1951,7 @@ async function runHealth(cwd2) {
1862
1951
  let dbOk;
1863
1952
  if (config.database.type === "sqlite") {
1864
1953
  const dbPath = resolveSqlitePath(config, cwd2, homedir2());
1865
- dbOk = existsSync11(dbPath);
1954
+ dbOk = existsSync12(dbPath);
1866
1955
  checkLine("checking DB", dbOk, `${dbPath} reachable`);
1867
1956
  } else {
1868
1957
  dbOk = true;
@@ -1875,8 +1964,8 @@ async function runHealth(cwd2) {
1875
1964
  const agentsLabelWidth = "[checking agents] ".length;
1876
1965
  for (let i = 0; i < agentNames.length; i++) {
1877
1966
  const name = agentNames[i];
1878
- const agentPath = join13(cwd2, agentsDir, `${name}${providerFiles.agentExtension}`);
1879
- const ok3 = existsSync11(agentPath);
1967
+ const agentPath = join14(cwd2, agentsDir, `${name}${providerFiles.agentExtension}`);
1968
+ const ok3 = existsSync12(agentPath);
1880
1969
  checkLine(
1881
1970
  i === 0 ? "checking agents" : null,
1882
1971
  ok3,
@@ -1887,8 +1976,8 @@ async function runHealth(cwd2) {
1887
1976
  }
1888
1977
  if (config.tools.mcp.enabled) {
1889
1978
  const mcpFile = providerFiles.mcpFile;
1890
- const mcpPath = resolve5(cwd2, mcpFile);
1891
- const mcpOk = existsSync11(mcpPath);
1979
+ const mcpPath = resolve6(cwd2, mcpFile);
1980
+ const mcpOk = existsSync12(mcpPath);
1892
1981
  checkLine("checking MCP", mcpOk, `${mcpFile} valid`);
1893
1982
  if (!mcpOk) allOk = false;
1894
1983
  }
@@ -1897,8 +1986,8 @@ async function runHealth(cwd2) {
1897
1986
  console.error(pc6.red("\u2717 Harness checks failed \u2014 fix the above before running health.sh"));
1898
1987
  process.exit(1);
1899
1988
  }
1900
- const scriptPath = resolve5(cwd2, config.health.scriptPath);
1901
- if (!existsSync11(scriptPath)) {
1989
+ const scriptPath = resolve6(cwd2, config.health.scriptPath);
1990
+ if (!existsSync12(scriptPath)) {
1902
1991
  console.error(pc6.red(`\u2717 health.sh not found: ${scriptPath}`));
1903
1992
  console.error(" Run ahk init first.");
1904
1993
  process.exit(1);
@@ -1928,14 +2017,16 @@ function getProviderHealthFiles(provider) {
1928
2017
  return { agentsDir: ".opencode/agents", agentExtension: ".md", mcpFile: "opencode.json" };
1929
2018
  case "codex-cli":
1930
2019
  return { agentsDir: ".codex/agents", agentExtension: ".toml", mcpFile: ".codex/config.toml" };
2020
+ case "grok-cli":
2021
+ return { agentsDir: ".grok/agents", agentExtension: ".md", mcpFile: ".grok/config.toml" };
1931
2022
  default:
1932
2023
  throw new Error(`Unknown provider: ${provider}`);
1933
2024
  }
1934
2025
  }
1935
2026
 
1936
2027
  // src/commands/init.ts
1937
- import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
1938
- import { join as join15 } from "path";
2028
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "fs";
2029
+ import { join as join16 } from "path";
1939
2030
  import * as p3 from "@clack/prompts";
1940
2031
  import pc8 from "picocolors";
1941
2032
 
@@ -1990,13 +2081,13 @@ var cliFormWithRetry = async (formFn, schema) => {
1990
2081
 
1991
2082
  // src/commands/init-helpers.ts
1992
2083
  import { randomUUID } from "crypto";
1993
- import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
1994
- import { join as join14 } from "path";
2084
+ import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
2085
+ import { join as join15 } from "path";
1995
2086
  import pc7 from "picocolors";
1996
2087
  function readProjectNameFromPackageJson(cwd2) {
1997
2088
  try {
1998
- const pkgPath2 = join14(cwd2, "package.json");
1999
- if (!existsSync12(pkgPath2)) return null;
2089
+ const pkgPath2 = join15(cwd2, "package.json");
2090
+ if (!existsSync13(pkgPath2)) return null;
2000
2091
  const content = readFileSync8(pkgPath2, "utf8");
2001
2092
  const pkg2 = JSON.parse(content);
2002
2093
  const name = pkg2?.name;
@@ -2009,9 +2100,9 @@ function readProjectNameFromPackageJson(cwd2) {
2009
2100
  function detectConfigExtension(cwd2) {
2010
2101
  if (!isLocalInstallSatisfied(cwd2)) return "json";
2011
2102
  try {
2012
- if (existsSync12(join14(cwd2, "tsconfig.json"))) return "ts";
2013
- const pkgPath2 = join14(cwd2, "package.json");
2014
- if (!existsSync12(pkgPath2)) return "mjs";
2103
+ if (existsSync13(join15(cwd2, "tsconfig.json"))) return "ts";
2104
+ const pkgPath2 = join15(cwd2, "package.json");
2105
+ if (!existsSync13(pkgPath2)) return "mjs";
2015
2106
  const pkg2 = JSON.parse(readFileSync8(pkgPath2, "utf8"));
2016
2107
  if (pkg2?.type === "module") return "mjs";
2017
2108
  } catch {
@@ -2092,10 +2183,10 @@ function printWelcomeMessage(projectName) {
2092
2183
 
2093
2184
  // src/commands/init.ts
2094
2185
  async function reconcileFeatureList(db, installDir, storageDir, firstTask) {
2095
- const featureListPath = join15(installDir, storageDir, "feature_list.json");
2186
+ const featureListPath = join16(installDir, storageDir, "feature_list.json");
2096
2187
  let existingSeeds = [];
2097
2188
  let parseFailed = false;
2098
- if (existsSync13(featureListPath)) {
2189
+ if (existsSync14(featureListPath)) {
2099
2190
  try {
2100
2191
  const parsed = JSON.parse(readFileSync9(featureListPath, "utf8"));
2101
2192
  if (!Array.isArray(parsed)) throw new Error("feature_list.json is not a JSON array");
@@ -2169,7 +2260,7 @@ async function runInit(cwd2, flags) {
2169
2260
  return val;
2170
2261
  }, initDescriptionSchema);
2171
2262
  let provider;
2172
- if (flags.provider && ["claude-code", "opencode"].includes(flags.provider)) {
2263
+ if (flags.provider && ["claude-code", "opencode", "codex-cli", "grok-cli"].includes(flags.provider)) {
2173
2264
  provider = flags.provider;
2174
2265
  } else {
2175
2266
  const val = await p3.select({
@@ -2177,7 +2268,8 @@ async function runInit(cwd2, flags) {
2177
2268
  options: [
2178
2269
  { value: "opencode", label: "OpenCode" },
2179
2270
  { value: "claude-code", label: "Claude Code" },
2180
- { value: "codex-cli", label: "Codex CLI" }
2271
+ { value: "codex-cli", label: "Codex CLI" },
2272
+ { value: "grok-cli", label: "Grok CLI" }
2181
2273
  ]
2182
2274
  });
2183
2275
  if (p3.isCancel(val)) {
@@ -2332,14 +2424,14 @@ async function runInit(cwd2, flags) {
2332
2424
  scope: config.storage.scope,
2333
2425
  projectId: config.storage.projectId
2334
2426
  });
2335
- writeFileSync7(join15(installDir, configFileName), configContent, "utf8");
2336
- mkdirSync6(join15(installDir, config.storage.dir), { recursive: true });
2427
+ writeFileSync8(join16(installDir, configFileName), configContent, "utf8");
2428
+ mkdirSync7(join16(installDir, config.storage.dir), { recursive: true });
2337
2429
  const db = await openDB(config, installDir);
2338
2430
  await db.writeStorageState(installDir);
2339
2431
  await materializer.scaffold(config, { cwd: installDir, firstTask, claudeAgentModels });
2340
2432
  const { parseFailed } = await reconcileFeatureList(db, installDir, config.storage.dir, firstTask);
2341
2433
  if (parseFailed) {
2342
- featureListParseFailedPath = join15(config.storage.dir, "feature_list.json");
2434
+ featureListParseFailedPath = join16(config.storage.dir, "feature_list.json");
2343
2435
  }
2344
2436
  await db.close();
2345
2437
  spinner6.stop("");
@@ -2354,8 +2446,13 @@ async function runInit(cwd2, flags) {
2354
2446
  );
2355
2447
  }
2356
2448
  console.log(pc8.green("\u2713 Scaffolded harness in current directory"));
2357
- const agentsDir = provider === "claude-code" ? ".claude/agents/" : ".opencode/agents/";
2358
- const mcpFile = provider === "claude-code" ? ".claude/mcp.json" : "./opencode.json";
2449
+ const PROVIDER_SUMMARY_INFO = {
2450
+ "claude-code": { agentsDir: ".claude/agents/", mcpFile: ".mcp.json" },
2451
+ opencode: { agentsDir: ".opencode/agents/", mcpFile: "./opencode.json" },
2452
+ "codex-cli": { agentsDir: ".codex/agents/", mcpFile: ".codex/config.toml" },
2453
+ "grok-cli": { agentsDir: ".grok/agents/", mcpFile: ".grok/config.toml" }
2454
+ };
2455
+ const { agentsDir, mcpFile } = PROVIDER_SUMMARY_INFO[provider];
2359
2456
  console.log("");
2360
2457
  console.log(pc8.green(`\u2713 agent-harness-kit.config.${configExt}`));
2361
2458
  console.log(pc8.green("\u2713 AGENTS.md"));
@@ -2397,7 +2494,7 @@ import pc9 from "picocolors";
2397
2494
  async function runMigrate(cwd2, opts) {
2398
2495
  const config = await loadConfig(cwd2);
2399
2496
  let target;
2400
- if (opts.to && ["claude-code", "opencode", "codex-cli"].includes(opts.to)) {
2497
+ if (opts.to && ["claude-code", "opencode", "codex-cli", "grok-cli"].includes(opts.to)) {
2401
2498
  target = opts.to;
2402
2499
  } else {
2403
2500
  const val = await p4.select({
@@ -2405,7 +2502,8 @@ async function runMigrate(cwd2, opts) {
2405
2502
  options: [
2406
2503
  { value: "claude-code", label: "Claude Code" },
2407
2504
  { value: "opencode", label: "OpenCode" },
2408
- { value: "codex-cli", label: "Codex CLI" }
2505
+ { value: "codex-cli", label: "Codex CLI" },
2506
+ { value: "grok-cli", label: "Grok CLI" }
2409
2507
  ]
2410
2508
  });
2411
2509
  if (p4.isCancel(val)) {
@@ -2434,9 +2532,9 @@ async function runMigrate(cwd2, opts) {
2434
2532
  }
2435
2533
 
2436
2534
  // src/commands/migrate-storage.ts
2437
- import { copyFileSync, existsSync as existsSync14, mkdirSync as mkdirSync7, rmSync, writeFileSync as writeFileSync8 } from "fs";
2535
+ import { copyFileSync, existsSync as existsSync15, mkdirSync as mkdirSync8, rmSync, writeFileSync as writeFileSync9 } from "fs";
2438
2536
  import { homedir as homedir3 } from "os";
2439
- import { dirname as dirname7, join as join16, resolve as resolve6 } from "path";
2537
+ import { dirname as dirname7, join as join17, resolve as resolve7 } from "path";
2440
2538
  import pc10 from "picocolors";
2441
2539
  function log5(msg) {
2442
2540
  console.log(msg);
@@ -2448,17 +2546,17 @@ function defaultMarkdownPathForConfig(config) {
2448
2546
  return config.storage.scope === "local" ? config.storage.markdownFallback.path : DEFAULT_MARKDOWN_PATH;
2449
2547
  }
2450
2548
  function currentMdPathForScope(scope, config, cwd2, homeDir) {
2451
- return scope === "global" ? join16(resolveGlobalStorageDir(config, homeDir), "current.md") : resolve6(cwd2, defaultMarkdownPathForConfig(config));
2549
+ return scope === "global" ? join17(resolveGlobalStorageDir(config, homeDir), "current.md") : resolve7(cwd2, defaultMarkdownPathForConfig(config));
2452
2550
  }
2453
2551
  function defaultSqlitePathForConfig(config) {
2454
2552
  return config.storage.scope === "local" && config.database.type === "sqlite" ? config.storage.sqlitePath ?? DEFAULT_SQLITE_PATH : DEFAULT_SQLITE_PATH;
2455
2553
  }
2456
2554
  async function backupDestination(cwd2, storageDir, data) {
2457
- const backupsDir = resolve6(cwd2, storageDir, "backups");
2458
- const path = join16(backupsDir, `pre-migrate-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.json`);
2555
+ const backupsDir = resolve7(cwd2, storageDir, "backups");
2556
+ const path = join17(backupsDir, `pre-migrate-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.json`);
2459
2557
  try {
2460
- mkdirSync7(backupsDir, { recursive: true });
2461
- writeFileSync8(path, JSON.stringify(data, null, 2) + "\n", "utf8");
2558
+ mkdirSync8(backupsDir, { recursive: true });
2559
+ writeFileSync9(path, JSON.stringify(data, null, 2) + "\n", "utf8");
2462
2560
  } catch (err) {
2463
2561
  throw new Error(
2464
2562
  `Could not write destination backup to ${path} (${err instanceof Error ? err.message : String(err)}). Aborting migration WITHOUT touching the destination \u2014 nothing was overwritten.`
@@ -2467,14 +2565,14 @@ async function backupDestination(cwd2, storageDir, data) {
2467
2565
  return path;
2468
2566
  }
2469
2567
  function copySqliteFile(srcPath, destPath) {
2470
- mkdirSync7(dirname7(destPath), { recursive: true });
2568
+ mkdirSync8(dirname7(destPath), { recursive: true });
2471
2569
  copyFileSync(srcPath, destPath);
2472
2570
  for (const suffix of ["-wal", "-shm"]) {
2473
- if (existsSync14(`${srcPath}${suffix}`)) {
2571
+ if (existsSync15(`${srcPath}${suffix}`)) {
2474
2572
  copyFileSync(`${srcPath}${suffix}`, `${destPath}${suffix}`);
2475
2573
  }
2476
2574
  }
2477
- if (!existsSync14(destPath)) {
2575
+ if (!existsSync15(destPath)) {
2478
2576
  throw new Error(`Copy verification failed: ${destPath} does not exist after copy.`);
2479
2577
  }
2480
2578
  }
@@ -2533,7 +2631,7 @@ async function runMigrateStorage(cwd2, opts, homeDir = homedir3()) {
2533
2631
  return migrateAcrossDbType(cwd2, config, homeDir, realScope, opts);
2534
2632
  }
2535
2633
  async function probeTaskCount(dbPath) {
2536
- if (!existsSync14(dbPath)) return 0;
2634
+ if (!existsSync15(dbPath)) return 0;
2537
2635
  const { SQLiteDriver } = await import("./sqlite-5OWKTUUZ.js");
2538
2636
  const driver = new SQLiteDriver(dbPath);
2539
2637
  try {
@@ -2550,10 +2648,10 @@ async function migrateScopeOnly(cwd2, config, homeDir, fromScope, toScope, opts)
2550
2648
  const destDb = resolveSqlitePathForScope(toScope, sqlitePath, cwd2, config, homeDir);
2551
2649
  const srcMd = currentMdPathForScope(fromScope, config, cwd2, homeDir);
2552
2650
  const destMd = currentMdPathForScope(toScope, config, cwd2, homeDir);
2553
- if (!existsSync14(srcDb)) {
2651
+ if (!existsSync15(srcDb)) {
2554
2652
  fail(`Source database not found at ${srcDb} (expected ${fromScope} scope) \u2014 nothing to move.`);
2555
2653
  }
2556
- const destExists = existsSync14(destDb);
2654
+ const destExists = existsSync15(destDb);
2557
2655
  if (destExists) {
2558
2656
  const { SQLiteDriver } = await import("./sqlite-5OWKTUUZ.js");
2559
2657
  const destDriver = new SQLiteDriver(destDb);
@@ -2591,15 +2689,15 @@ async function migrateScopeOnly(cwd2, config, homeDir, fromScope, toScope, opts)
2591
2689
  }
2592
2690
  copySqliteFile(srcDb, destDb);
2593
2691
  log5(pc10.green(`\u2713 Copied database ${srcDb} \u2192 ${destDb}`));
2594
- if (existsSync14(srcMd)) {
2595
- mkdirSync7(dirname7(destMd), { recursive: true });
2692
+ if (existsSync15(srcMd)) {
2693
+ mkdirSync8(dirname7(destMd), { recursive: true });
2596
2694
  copyFileSync(srcMd, destMd);
2597
2695
  log5(pc10.green(`\u2713 Copied current.md ${srcMd} \u2192 ${destMd}`));
2598
2696
  }
2599
2697
  rmSync(srcDb, { force: true });
2600
2698
  rmSync(`${srcDb}-wal`, { force: true });
2601
2699
  rmSync(`${srcDb}-shm`, { force: true });
2602
- if (existsSync14(srcMd) && srcMd !== destMd) rmSync(srcMd, { force: true });
2700
+ if (existsSync15(srcMd) && srcMd !== destMd) rmSync(srcMd, { force: true });
2603
2701
  const db = await openDB(config, cwd2, homeDir);
2604
2702
  try {
2605
2703
  await db.writeStorageState(cwd2);
@@ -2611,7 +2709,7 @@ async function migrateScopeOnly(cwd2, config, homeDir, fromScope, toScope, opts)
2611
2709
  async function migrateAcrossDbType(cwd2, config, homeDir, sourceScope, opts) {
2612
2710
  const sqlitePath = defaultSqlitePathForConfig(config);
2613
2711
  const srcPath = resolveSqlitePathForScope(sourceScope, sqlitePath, cwd2, config, homeDir);
2614
- if (!existsSync14(srcPath)) {
2712
+ if (!existsSync15(srcPath)) {
2615
2713
  fail(`Source sqlite database not found at ${srcPath} (expected ${sourceScope} scope) \u2014 nothing to migrate.`);
2616
2714
  }
2617
2715
  const { SQLiteDriver } = await import("./sqlite-5OWKTUUZ.js");
@@ -2674,16 +2772,29 @@ async function migrateAcrossDbType(cwd2, config, homeDir, sourceScope, opts) {
2674
2772
  }
2675
2773
 
2676
2774
  // src/commands/reset.ts
2677
- import { existsSync as existsSync15, readdirSync, rmSync as rmSync2 } from "fs";
2775
+ import { existsSync as existsSync16, readdirSync, rmSync as rmSync2 } from "fs";
2678
2776
  import { homedir as homedir4 } from "os";
2679
- import { join as join17, resolve as resolve7 } from "path";
2777
+ import { join as join18, resolve as resolve8 } from "path";
2680
2778
  import * as p5 from "@clack/prompts";
2681
2779
  import pc11 from "picocolors";
2682
2780
  var AGENT_MD_FILES = ["lead", "explorer", "consultant", "builder", "reviewer"];
2781
+ var PROVIDER_AGENT_DIRS = {
2782
+ "claude-code": ".claude/agents",
2783
+ opencode: ".opencode/agents",
2784
+ "codex-cli": ".codex/agents",
2785
+ "grok-cli": ".grok/agents"
2786
+ };
2787
+ var PROVIDER_AGENT_EXT = {
2788
+ "claude-code": ".md",
2789
+ opencode: ".md",
2790
+ "codex-cli": ".toml",
2791
+ "grok-cli": ".md"
2792
+ };
2683
2793
  async function resetAgentMds(cwd2, provider) {
2684
- const agentDir = provider === "claude-code" ? ".claude/agents" : ".opencode/agents";
2685
- const agentDirPath = resolve7(cwd2, agentDir);
2686
- if (!existsSync15(agentDirPath)) {
2794
+ const agentDir = PROVIDER_AGENT_DIRS[provider];
2795
+ const agentDirPath = resolve8(cwd2, agentDir);
2796
+ const agentExt = PROVIDER_AGENT_EXT[provider];
2797
+ if (!existsSync16(agentDirPath)) {
2687
2798
  console.log(pc11.yellow(` Skipping agent files \u2014 directory not found: ${agentDirPath}`));
2688
2799
  return;
2689
2800
  }
@@ -2691,7 +2802,7 @@ async function resetAgentMds(cwd2, provider) {
2691
2802
  try {
2692
2803
  const files = readdirSync(agentDirPath);
2693
2804
  for (const f of files) {
2694
- if (f.endsWith(".md") && AGENT_MD_FILES.includes(f.replace(".md", ""))) {
2805
+ if (f.endsWith(agentExt) && AGENT_MD_FILES.includes(f.replace(agentExt, ""))) {
2695
2806
  existingFiles.push(f);
2696
2807
  }
2697
2808
  }
@@ -2714,7 +2825,7 @@ async function resetAgentMds(cwd2, provider) {
2714
2825
  }
2715
2826
  if (confirm3) {
2716
2827
  try {
2717
- const filePath = join17(agentDirPath, file);
2828
+ const filePath = join18(agentDirPath, file);
2718
2829
  rmSync2(filePath, { force: true });
2719
2830
  console.log(pc11.green(` Removed ${file}`));
2720
2831
  } catch {
@@ -2735,11 +2846,11 @@ async function runReset(cwd2, opts) {
2735
2846
  }
2736
2847
  const storageDir = config.storage.dir || ".harness";
2737
2848
  const dbPath = config.database.type === "sqlite" ? resolveSqlitePath(config, cwd2, homedir4()) : null;
2738
- const featureListPath = resolve7(cwd2, storageDir, "feature_list.json");
2849
+ const featureListPath = resolve8(cwd2, storageDir, "feature_list.json");
2739
2850
  let resetDb = false;
2740
2851
  let resetFeatureList = false;
2741
2852
  let resetAgentMdsFlag = false;
2742
- if (dbPath && existsSync15(dbPath)) {
2853
+ if (dbPath && existsSync16(dbPath)) {
2743
2854
  if (opts.force) {
2744
2855
  resetDb = true;
2745
2856
  } else {
@@ -2761,7 +2872,7 @@ async function runReset(cwd2, opts) {
2761
2872
  } else if (!dbPath) {
2762
2873
  console.log(pc11.dim(` Skipping DB reset \u2014 remote ${config.database.type} database is not managed by this command.`));
2763
2874
  }
2764
- if (existsSync15(featureListPath)) {
2875
+ if (existsSync16(featureListPath)) {
2765
2876
  if (opts.force) {
2766
2877
  resetFeatureList = true;
2767
2878
  } else {
@@ -2810,8 +2921,8 @@ async function runReset(cwd2, opts) {
2810
2921
  }
2811
2922
 
2812
2923
  // src/core/mcp-server.ts
2813
- import { existsSync as existsSync17, mkdirSync as mkdirSync8, readdirSync as readdirSync2, readFileSync as readFileSync10, statSync, writeFileSync as writeFileSync9 } from "fs";
2814
- import { join as join19, resolve as resolve8 } from "path";
2924
+ import { existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync as readdirSync2, readFileSync as readFileSync10, statSync, writeFileSync as writeFileSync10 } from "fs";
2925
+ import { join as join20, resolve as resolve9 } from "path";
2815
2926
  import { Server } from "@modelcontextprotocol/sdk/server";
2816
2927
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2817
2928
  import {
@@ -2820,8 +2931,8 @@ import {
2820
2931
  } from "@modelcontextprotocol/sdk/types.js";
2821
2932
 
2822
2933
  // src/core/permissions-check.ts
2823
- import { existsSync as existsSync16 } from "fs";
2824
- import { join as join18 } from "path";
2934
+ import { existsSync as existsSync17 } from "fs";
2935
+ import { join as join19 } from "path";
2825
2936
  var AGENTS = ["lead", "explorer", "consultant", "builder", "reviewer"];
2826
2937
  function checkPermissionsSync(cwd2, config) {
2827
2938
  if (config.provider !== "claude-code") {
@@ -2830,8 +2941,8 @@ function checkPermissionsSync(cwd2, config) {
2830
2941
  const agents = {};
2831
2942
  let in_sync = true;
2832
2943
  for (const agent of AGENTS) {
2833
- const filePath = join18(cwd2, ".claude", "agents", `${agent}.md`);
2834
- const exists = existsSync16(filePath);
2944
+ const filePath = join19(cwd2, ".claude", "agents", `${agent}.md`);
2945
+ const exists = existsSync17(filePath);
2835
2946
  if (!exists) in_sync = false;
2836
2947
  agents[agent] = exists ? { ok: true } : { ok: false, reason: "missing_file" };
2837
2948
  }
@@ -3129,7 +3240,7 @@ var TOOLS = [
3129
3240
  ];
3130
3241
  async function startMcpServer(config, cwd2) {
3131
3242
  const db = await openDB(config, cwd2);
3132
- const docsPath = resolve8(cwd2, config.project.docsPath);
3243
+ const docsPath = resolve9(cwd2, config.project.docsPath);
3133
3244
  const server = new Server(
3134
3245
  { name: "agent-harness-kit", version: VERSION },
3135
3246
  { capabilities: { tools: {} } }
@@ -3292,8 +3403,8 @@ async function dispatch(name, args, db, docsPath, cwd2, config) {
3292
3403
  return ok2(JSON.stringify(result));
3293
3404
  }
3294
3405
  case "deps.snapshot": {
3295
- const pkgPath2 = join19(cwd2, "package.json");
3296
- if (!existsSync17(pkgPath2)) {
3406
+ const pkgPath2 = join20(cwd2, "package.json");
3407
+ if (!existsSync18(pkgPath2)) {
3297
3408
  return ok2("package.json not found in project root", true);
3298
3409
  }
3299
3410
  const pkg2 = JSON.parse(readFileSync10(pkgPath2, "utf8"));
@@ -3302,9 +3413,9 @@ async function dispatch(name, args, db, docsPath, cwd2, config) {
3302
3413
  dependencies: pkg2.dependencies ?? {},
3303
3414
  devDependencies: pkg2.devDependencies ?? {}
3304
3415
  };
3305
- const harnessDir = join19(cwd2, ".harness");
3306
- mkdirSync8(harnessDir, { recursive: true });
3307
- writeFileSync9(join19(harnessDir, "deps-lock.json"), JSON.stringify(snapshot, null, 2), "utf8");
3416
+ const harnessDir = join20(cwd2, ".harness");
3417
+ mkdirSync9(harnessDir, { recursive: true });
3418
+ writeFileSync10(join20(harnessDir, "deps-lock.json"), JSON.stringify(snapshot, null, 2), "utf8");
3308
3419
  return ok2(
3309
3420
  JSON.stringify({
3310
3421
  message: "Snapshot saved to .harness/deps-lock.json",
@@ -3313,12 +3424,12 @@ async function dispatch(name, args, db, docsPath, cwd2, config) {
3313
3424
  );
3314
3425
  }
3315
3426
  case "deps.check": {
3316
- const pkgPath2 = join19(cwd2, "package.json");
3317
- const lockPath = join19(cwd2, ".harness", "deps-lock.json");
3318
- if (!existsSync17(pkgPath2)) {
3427
+ const pkgPath2 = join20(cwd2, "package.json");
3428
+ const lockPath = join20(cwd2, ".harness", "deps-lock.json");
3429
+ if (!existsSync18(pkgPath2)) {
3319
3430
  return ok2("package.json not found in project root", true);
3320
3431
  }
3321
- if (!existsSync17(lockPath)) {
3432
+ if (!existsSync18(lockPath)) {
3322
3433
  return ok2(
3323
3434
  JSON.stringify({
3324
3435
  status: "no-snapshot",
@@ -3420,7 +3531,7 @@ function collectMarkdownFiles(dir) {
3420
3531
  const files = [];
3421
3532
  try {
3422
3533
  for (const entry of readdirSync2(dir)) {
3423
- const full = join19(dir, entry);
3534
+ const full = join20(dir, entry);
3424
3535
  const stat = statSync(full);
3425
3536
  if (stat.isDirectory()) {
3426
3537
  files.push(...collectMarkdownFiles(full));
@@ -3550,13 +3661,13 @@ async function runStatus(cwd2, opts) {
3550
3661
  }
3551
3662
 
3552
3663
  // src/commands/sync.ts
3553
- import { existsSync as existsSync18, readFileSync as readFileSync11 } from "fs";
3554
- import { join as join20, resolve as resolve9 } from "path";
3664
+ import { existsSync as existsSync19, readFileSync as readFileSync11 } from "fs";
3665
+ import { join as join21, resolve as resolve10 } from "path";
3555
3666
  import pc13 from "picocolors";
3556
3667
  async function runSync(cwd2, opts) {
3557
3668
  const config = await loadConfig(cwd2);
3558
3669
  const direction = opts.direction ?? "both";
3559
- const featureListPath = resolve9(join20(cwd2, config.storage.dir, "feature_list.json"));
3670
+ const featureListPath = resolve10(join21(cwd2, config.storage.dir, "feature_list.json"));
3560
3671
  const db = await openDB(config, cwd2);
3561
3672
  try {
3562
3673
  if (direction === "in" || direction === "both") {
@@ -3570,7 +3681,7 @@ async function runSync(cwd2, opts) {
3570
3681
  }
3571
3682
  }
3572
3683
  async function syncIn(featureListPath, db, dryRun) {
3573
- if (!existsSync18(featureListPath)) {
3684
+ if (!existsSync19(featureListPath)) {
3574
3685
  console.log(pc13.dim(`feature_list.json not found at ${featureListPath} \u2014 skipping in-sync`));
3575
3686
  return;
3576
3687
  }
@@ -3661,14 +3772,14 @@ async function runTaskAdd(cwd2) {
3661
3772
 
3662
3773
  // src/commands/task/done.ts
3663
3774
  import { spawnSync as spawnSync2 } from "child_process";
3664
- import { existsSync as existsSync19 } from "fs";
3665
- import { resolve as resolve10 } from "path";
3775
+ import { existsSync as existsSync20 } from "fs";
3776
+ import { resolve as resolve11 } from "path";
3666
3777
  import pc15 from "picocolors";
3667
3778
  async function runTaskDone(cwd2, idOrSlug) {
3668
3779
  const config = await loadConfig(cwd2);
3669
3780
  if (config.health.required) {
3670
- const scriptPath = resolve10(cwd2, config.health.scriptPath);
3671
- if (existsSync19(scriptPath)) {
3781
+ const scriptPath = resolve11(cwd2, config.health.scriptPath);
3782
+ if (existsSync20(scriptPath)) {
3672
3783
  const result = spawnSync2("bash", [scriptPath], { cwd: cwd2, stdio: "pipe", encoding: "utf8" });
3673
3784
  if (result.status !== 0) {
3674
3785
  console.error(pc15.red("\u2717 Health check failed \u2014 cannot mark task as done."));
@@ -3841,7 +3952,7 @@ async function runTaskList(cwd2, opts) {
3841
3952
 
3842
3953
  // src/core/path-probe.ts
3843
3954
  import { accessSync, constants, readdirSync as readdirSync3 } from "fs";
3844
- import { join as join21 } from "path";
3955
+ import { join as join22 } from "path";
3845
3956
  import pc18 from "picocolors";
3846
3957
  var DEFAULT_PATHEXT = [".COM", ".EXE", ".BAT", ".CMD"];
3847
3958
  function defaultIsExecutable(filePath) {
@@ -3886,7 +3997,7 @@ function resolveOnPath(name, options = {}) {
3886
3997
  }
3887
3998
  for (const dir of dirs) {
3888
3999
  try {
3889
- if (isExecutable(join21(dir, name))) return true;
4000
+ if (isExecutable(join22(dir, name))) return true;
3890
4001
  } catch {
3891
4002
  continue;
3892
4003
  }
@@ -3910,15 +4021,15 @@ import pc19 from "picocolors";
3910
4021
  var REGISTRY_URL2 = `https://registry.npmjs.org/${pkg.name}/latest`;
3911
4022
  var TIMEOUT_MS2 = 2500;
3912
4023
  function checkForUpdate(currentVersion) {
3913
- return new Promise((resolve11) => {
3914
- const timer = setTimeout(() => resolve11(null), TIMEOUT_MS2);
4024
+ return new Promise((resolve12) => {
4025
+ const timer = setTimeout(() => resolve12(null), TIMEOUT_MS2);
3915
4026
  fetch(REGISTRY_URL2).then((res) => res.json()).then((data) => {
3916
4027
  clearTimeout(timer);
3917
4028
  const latest = data.version;
3918
- resolve11(isNewer2(latest, currentVersion) ? { current: currentVersion, latest } : null);
4029
+ resolve12(isNewer2(latest, currentVersion) ? { current: currentVersion, latest } : null);
3919
4030
  }).catch(() => {
3920
4031
  clearTimeout(timer);
3921
- resolve11(null);
4032
+ resolve12(null);
3922
4033
  });
3923
4034
  });
3924
4035
  }
@@ -3955,7 +4066,7 @@ function parsePort(raw) {
3955
4066
  var updateCheck = checkForUpdate(pkg.version);
3956
4067
  var program = new Command();
3957
4068
  program.name("ahk").description("agent-harness-kit \u2014 CLI scaffolding for multi-agent harness systems").version(pkg.version, "-v, --version");
3958
- program.command("init").description("Scaffold a harness interactively in the current directory").option("--name <name>", "Project name (skip prompt)").option("--provider <provider>", "AI provider: claude-code | opencode (skip prompt)").option("--docs <path>", "Docs folder path (skip prompt)").option("--tasks <adapter>", "Task adapter: local | jira | linear (skip prompt)").option("--storage-scope <scope>", "Storage scope: local | global (skip prompt)").action(async (opts) => {
4069
+ program.command("init").description("Scaffold a harness interactively in the current directory").option("--name <name>", "Project name (skip prompt)").option("--provider <provider>", "AI provider: claude-code | opencode | codex-cli | grok-cli (skip prompt)").option("--docs <path>", "Docs folder path (skip prompt)").option("--tasks <adapter>", "Task adapter: local | jira | linear (skip prompt)").option("--storage-scope <scope>", "Storage scope: local | global (skip prompt)").action(async (opts) => {
3959
4070
  await runInit(cwd, opts);
3960
4071
  });
3961
4072
  program.command("build").description("Regenerate AGENTS.md and provider files from agent-harness-kit.config.ts").option("--watch", "Rebuild on config changes").option("--sync", "Sync tools: frontmatter in existing .claude/agents/*.md to match current permission constants").option(
@@ -3993,7 +4104,7 @@ program.command("dashboard").description("Open web dashboard to visualize harnes
3993
4104
  await runDashboard(cwd, { port: opts.port, open: opts.open });
3994
4105
  });
3995
4106
  var migrate = program.command("migrate").description("Migrate provider files to a different provider, or migrate harness storage (see subcommands)");
3996
- migrate.command("provider").description("Migrate provider-specific files to a different provider").option("--to <provider>", "Target provider: claude-code | opencode | codex-cli").action(async (opts) => {
4107
+ migrate.command("provider").description("Migrate provider-specific files to a different provider").option("--to <provider>", "Target provider: claude-code | opencode | codex-cli | grok-cli").action(async (opts) => {
3997
4108
  await runMigrate(cwd, opts);
3998
4109
  });
3999
4110
  migrate.command("storage").description(
@@ -4009,7 +4120,7 @@ migrate.command("storage").description(
4009
4120
  program.command("export").description("Export the database").option("--sql", "SQL dump").option("--json", "JSON export of tasks and actions").option("--output <path>", "Output file path (default: stdout)").action(async (opts) => {
4010
4121
  await runExport(cwd, opts);
4011
4122
  });
4012
- program.command("reset").description("Reset/clear harness data (DB, feature list, agent files)").option("--force", "Skip confirmation prompts").option("--provider <claude-code|opencode>", "Reset agent MD files for specified provider").action(async (opts) => {
4123
+ program.command("reset").description("Reset/clear harness data (DB, feature list, agent files)").option("--force", "Skip confirmation prompts").option("--provider <claude-code|opencode|codex-cli|grok-cli>", "Reset agent MD files for specified provider").action(async (opts) => {
4013
4124
  await runReset(cwd, opts);
4014
4125
  });
4015
4126
  program.command("doctor").description("Check lib version, agent files, and harness skills sync status").action(async () => {