clikit-plugin 0.3.4 → 0.3.6

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 CHANGED
@@ -3386,7 +3386,7 @@ var require_parse = __commonJS((exports, module) => {
3386
3386
 
3387
3387
  // node_modules/gray-matter/index.js
3388
3388
  var require_gray_matter = __commonJS((exports, module) => {
3389
- var fs = __require("fs");
3389
+ var fs2 = __require("fs");
3390
3390
  var sections = require_section_matter();
3391
3391
  var defaults = require_defaults();
3392
3392
  var stringify = require_stringify();
@@ -3473,7 +3473,7 @@ var require_gray_matter = __commonJS((exports, module) => {
3473
3473
  return stringify(file2, data, options2);
3474
3474
  };
3475
3475
  matter.read = function(filepath, options2) {
3476
- const str2 = fs.readFileSync(filepath, "utf8");
3476
+ const str2 = fs2.readFileSync(filepath, "utf8");
3477
3477
  const file2 = matter(str2, options2);
3478
3478
  file2.path = filepath;
3479
3479
  return file2;
@@ -3500,6 +3500,369 @@ var require_gray_matter = __commonJS((exports, module) => {
3500
3500
  module.exports = matter;
3501
3501
  });
3502
3502
 
3503
+ // src/cli.ts
3504
+ import * as fs from "fs";
3505
+ import * as path from "path";
3506
+ import * as os from "os";
3507
+ import { fileURLToPath } from "url";
3508
+ var PLUGIN_NAME = "clikit-plugin";
3509
+ var DCP_PLUGIN_ENTRY = "@tarquinen/opencode-dcp@beta";
3510
+ var VERSION = "0.0.0";
3511
+ function getPackageRoot() {
3512
+ const currentFile = fileURLToPath(import.meta.url);
3513
+ const currentDir = path.dirname(currentFile);
3514
+ if (path.basename(currentDir) === "dist") {
3515
+ return path.dirname(currentDir);
3516
+ }
3517
+ return path.dirname(currentDir);
3518
+ }
3519
+ function getPackageVersion() {
3520
+ const packageJsonPath = path.join(getPackageRoot(), "package.json");
3521
+ try {
3522
+ const raw = fs.readFileSync(packageJsonPath, "utf-8");
3523
+ const parsed = JSON.parse(raw);
3524
+ return parsed.version || VERSION;
3525
+ } catch {
3526
+ return VERSION;
3527
+ }
3528
+ }
3529
+ function getPluginEntry() {
3530
+ return `${PLUGIN_NAME}@latest`;
3531
+ }
3532
+ function resolveProjectDir(env = process.env, cwd = process.cwd()) {
3533
+ const candidates = [env.INIT_CWD, env.PWD, cwd].filter((value) => typeof value === "string" && value.trim().length > 0);
3534
+ for (const candidate of candidates) {
3535
+ const resolved = path.resolve(candidate);
3536
+ try {
3537
+ if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
3538
+ return resolved;
3539
+ }
3540
+ } catch {}
3541
+ }
3542
+ return cwd;
3543
+ }
3544
+ function upsertPluginEntry(existingPlugins, pluginEntry) {
3545
+ let pluginName;
3546
+ if (pluginEntry.startsWith("@")) {
3547
+ const versionAt = pluginEntry.indexOf("@", 1);
3548
+ pluginName = versionAt === -1 ? pluginEntry : pluginEntry.slice(0, versionAt);
3549
+ } else {
3550
+ pluginName = pluginEntry.split("@")[0] || pluginEntry;
3551
+ }
3552
+ const filteredPlugins = existingPlugins.filter((p) => p !== pluginName && !p.startsWith(`${pluginName}@`));
3553
+ filteredPlugins.push(pluginEntry);
3554
+ return filteredPlugins;
3555
+ }
3556
+ function copyFileIfMissing(sourcePath, targetPath, stats) {
3557
+ if (!fs.existsSync(sourcePath)) {
3558
+ stats.missingSources.push(sourcePath);
3559
+ return;
3560
+ }
3561
+ if (fs.existsSync(targetPath)) {
3562
+ stats.skipped += 1;
3563
+ return;
3564
+ }
3565
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
3566
+ fs.copyFileSync(sourcePath, targetPath);
3567
+ stats.copied += 1;
3568
+ }
3569
+ function copyDirectoryFilesIfMissing(sourceDir, targetDir, stats) {
3570
+ if (!fs.existsSync(sourceDir)) {
3571
+ stats.missingSources.push(sourceDir);
3572
+ return;
3573
+ }
3574
+ fs.mkdirSync(targetDir, { recursive: true });
3575
+ const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
3576
+ for (const entry of entries) {
3577
+ const sourcePath = path.join(sourceDir, entry.name);
3578
+ const targetPath = path.join(targetDir, entry.name);
3579
+ if (entry.isDirectory()) {
3580
+ copyDirectoryFilesIfMissing(sourcePath, targetPath, stats);
3581
+ continue;
3582
+ }
3583
+ if (entry.isFile()) {
3584
+ copyFileIfMissing(sourcePath, targetPath, stats);
3585
+ }
3586
+ }
3587
+ }
3588
+ function scaffoldProjectOpencode(projectDir, packageRoot = getPackageRoot()) {
3589
+ const projectOpencodeDir = path.join(projectDir, ".opencode");
3590
+ const stats = {
3591
+ copied: 0,
3592
+ skipped: 0,
3593
+ missingSources: []
3594
+ };
3595
+ fs.mkdirSync(projectOpencodeDir, { recursive: true });
3596
+ copyFileIfMissing(path.join(packageRoot, "AGENTS.md"), path.join(projectOpencodeDir, "AGENTS.md"), stats);
3597
+ copyDirectoryFilesIfMissing(path.join(packageRoot, "command"), path.join(projectOpencodeDir, "command"), stats);
3598
+ copyDirectoryFilesIfMissing(path.join(packageRoot, "skill"), path.join(projectOpencodeDir, "skill"), stats);
3599
+ copyDirectoryFilesIfMissing(path.join(packageRoot, "memory", "_templates"), path.join(projectOpencodeDir, "memory", "_templates"), stats);
3600
+ copyDirectoryFilesIfMissing(path.join(packageRoot, "src", "agents"), path.join(projectOpencodeDir, "src", "agents"), stats);
3601
+ copyFileIfMissing(path.join(packageRoot, "README.md"), path.join(projectOpencodeDir, "README-clikit.md"), stats);
3602
+ const indexPath = path.join(projectOpencodeDir, "index.ts");
3603
+ if (!fs.existsSync(indexPath)) {
3604
+ fs.writeFileSync(indexPath, `import CliKitPlugin from "${PLUGIN_NAME}";
3605
+
3606
+ export default CliKitPlugin;
3607
+ `);
3608
+ stats.copied += 1;
3609
+ } else {
3610
+ stats.skipped += 1;
3611
+ }
3612
+ return stats;
3613
+ }
3614
+ function getShellRcFiles() {
3615
+ const home = getRealHome();
3616
+ const rcFiles = [];
3617
+ const shell = process.env.SHELL || "";
3618
+ if (shell.includes("zsh")) {
3619
+ rcFiles.push(path.join(home, ".zshrc"));
3620
+ } else if (shell.includes("fish")) {
3621
+ rcFiles.push(path.join(home, ".config", "fish", "config.fish"));
3622
+ } else {
3623
+ rcFiles.push(path.join(home, ".bashrc"));
3624
+ const bashProfile = path.join(home, ".bash_profile");
3625
+ if (fs.existsSync(bashProfile)) {
3626
+ rcFiles.push(bashProfile);
3627
+ }
3628
+ }
3629
+ return rcFiles;
3630
+ }
3631
+ function ensureEnvInShellRc(key, value) {
3632
+ const exportLine = `export ${key}=${value}`;
3633
+ const marker = `# Added by clikit-plugin`;
3634
+ const block = `
3635
+ ${marker}
3636
+ ${exportLine}
3637
+ `;
3638
+ const rcFiles = getShellRcFiles();
3639
+ for (const rcFile of rcFiles) {
3640
+ try {
3641
+ const existing = fs.existsSync(rcFile) ? fs.readFileSync(rcFile, "utf-8") : "";
3642
+ if (existing.includes(`export ${key}=`) || existing.includes(`${key}=`)) {
3643
+ console.log(`\u2713 ${key} already set in ${rcFile}`);
3644
+ continue;
3645
+ }
3646
+ fs.appendFileSync(rcFile, block, "utf-8");
3647
+ console.log(`\u2713 Added ${exportLine} to ${rcFile}`);
3648
+ } catch (err) {
3649
+ console.warn(`\u26A0 Could not write to ${rcFile}: ${err}`);
3650
+ }
3651
+ }
3652
+ }
3653
+ function removeLegacyGlobalPluginAssets(configDir) {
3654
+ const legacyPluginPath = path.join(configDir, "plugins", "clikit.js");
3655
+ const legacyAgentsDir = path.join(configDir, "plugins", "agents");
3656
+ const legacyCommandDir = path.join(configDir, "command");
3657
+ const legacyStatusPath = path.join(legacyCommandDir, "status.md");
3658
+ const legacyStatusBeadsPath = path.join(legacyCommandDir, "status-beads.md");
3659
+ if (fs.existsSync(legacyPluginPath)) {
3660
+ fs.rmSync(legacyPluginPath, { force: true });
3661
+ console.log(`\u2713 Removed legacy local plugin file: ${legacyPluginPath}`);
3662
+ }
3663
+ if (fs.existsSync(legacyAgentsDir)) {
3664
+ fs.rmSync(legacyAgentsDir, { recursive: true, force: true });
3665
+ console.log(`\u2713 Removed legacy local agents directory: ${legacyAgentsDir}`);
3666
+ }
3667
+ if (fs.existsSync(legacyStatusPath)) {
3668
+ fs.rmSync(legacyStatusPath, { force: true });
3669
+ console.log(`\u2713 Removed legacy command file: ${legacyStatusPath}`);
3670
+ }
3671
+ if (fs.existsSync(legacyStatusBeadsPath)) {
3672
+ fs.rmSync(legacyStatusBeadsPath, { force: true });
3673
+ console.log(`\u2713 Removed legacy command file: ${legacyStatusBeadsPath}`);
3674
+ }
3675
+ }
3676
+ function getRealHome() {
3677
+ if (process.env.SNAP_REAL_HOME) {
3678
+ return process.env.SNAP_REAL_HOME;
3679
+ }
3680
+ const home = os.homedir();
3681
+ const snapMatch = home.match(/^(\/home\/[^/]+)\/snap\//);
3682
+ if (snapMatch) {
3683
+ return snapMatch[1];
3684
+ }
3685
+ return home;
3686
+ }
3687
+ function getConfigDir() {
3688
+ if (process.env.OPENCODE_CONFIG_DIR) {
3689
+ return process.env.OPENCODE_CONFIG_DIR;
3690
+ }
3691
+ const home = getRealHome();
3692
+ return path.join(process.env.XDG_CONFIG_HOME || path.join(home, ".config"), "opencode");
3693
+ }
3694
+ function getConfigPath() {
3695
+ const configDir = getConfigDir();
3696
+ const jsonPath = path.join(configDir, "opencode.json");
3697
+ const jsoncPath = path.join(configDir, "opencode.jsonc");
3698
+ if (fs.existsSync(jsoncPath))
3699
+ return jsoncPath;
3700
+ if (fs.existsSync(jsonPath))
3701
+ return jsonPath;
3702
+ return jsonPath;
3703
+ }
3704
+ function getCliKitConfigPath(configDir = getConfigDir()) {
3705
+ const candidates = ["clikit.jsonc", "clikit.json", "clikit.config.json"];
3706
+ for (const name of candidates) {
3707
+ const fullPath = path.join(configDir, name);
3708
+ if (fs.existsSync(fullPath)) {
3709
+ return fullPath;
3710
+ }
3711
+ }
3712
+ return path.join(configDir, "clikit.json");
3713
+ }
3714
+ function ensureConfigDir() {
3715
+ const configDir = getConfigDir();
3716
+ if (!fs.existsSync(configDir)) {
3717
+ fs.mkdirSync(configDir, { recursive: true });
3718
+ }
3719
+ }
3720
+ function parseConfig(configPath) {
3721
+ try {
3722
+ if (!fs.existsSync(configPath)) {
3723
+ return { config: {}, raw: "", parseError: null };
3724
+ }
3725
+ const content = fs.readFileSync(configPath, "utf-8");
3726
+ try {
3727
+ const parsed = JSON.parse(content);
3728
+ return { config: parsed, raw: content, parseError: null };
3729
+ } catch {
3730
+ const cleaned = content.replace(/\/\*[\s\S]*?\*\//g, "");
3731
+ const cleanedTrailing = cleaned.replace(/,\s*([}\]])/g, "$1");
3732
+ const parsed = JSON.parse(cleanedTrailing);
3733
+ return { config: parsed, raw: content, parseError: null };
3734
+ }
3735
+ } catch (err) {
3736
+ const raw = fs.existsSync(configPath) ? fs.readFileSync(configPath, "utf-8") : "";
3737
+ return { config: {}, raw, parseError: String(err) };
3738
+ }
3739
+ }
3740
+ function writeConfig(configPath, config) {
3741
+ ensureConfigDir();
3742
+ const tmpPath = `${configPath}.tmp`;
3743
+ const content = JSON.stringify(config, null, 2) + `
3744
+ `;
3745
+ fs.writeFileSync(tmpPath, content);
3746
+ fs.renameSync(tmpPath, configPath);
3747
+ }
3748
+ async function install(options2) {
3749
+ const pluginEntry = getPluginEntry();
3750
+ try {
3751
+ ensureConfigDir();
3752
+ const configPath = getConfigPath();
3753
+ const result = parseConfig(configPath);
3754
+ if (result.parseError && result.raw.trim()) {
3755
+ console.error(`\u2717 Config file has syntax errors and cannot be safely modified.`);
3756
+ console.error(` Error: ${result.parseError}`);
3757
+ console.error(` Please fix the config file manually.`);
3758
+ return 1;
3759
+ }
3760
+ const config = result.config;
3761
+ const existingPlugins = Array.isArray(config.plugin) ? config.plugin.filter((p) => typeof p === "string") : [];
3762
+ const filteredPlugins = upsertPluginEntry(existingPlugins, pluginEntry);
3763
+ const finalPlugins = upsertPluginEntry(filteredPlugins, DCP_PLUGIN_ENTRY);
3764
+ const pluginMergedConfig = { ...config, plugin: finalPlugins };
3765
+ writeConfig(configPath, pluginMergedConfig);
3766
+ if (options2.includeProjectScaffold) {
3767
+ const projectDir = resolveProjectDir();
3768
+ scaffoldProjectOpencode(projectDir);
3769
+ }
3770
+ removeLegacyGlobalPluginAssets(getConfigDir());
3771
+ ensureEnvInShellRc("OPENCODE_ENABLE_EXA", "1");
3772
+ const memoryDir = path.join(getConfigDir(), "memory");
3773
+ const memorySubdirs = ["specs", "plans", "research", "reviews", "handoffs", "beads", "prds"];
3774
+ for (const subdir of memorySubdirs) {
3775
+ const dir = path.join(memoryDir, subdir);
3776
+ if (!fs.existsSync(dir)) {
3777
+ fs.mkdirSync(dir, { recursive: true });
3778
+ }
3779
+ }
3780
+ const clikitConfigPath = getCliKitConfigPath();
3781
+ if (!fs.existsSync(clikitConfigPath)) {
3782
+ const defaultConfig = {
3783
+ $schema: `https://unpkg.com/${PLUGIN_NAME}@latest/schema.json`,
3784
+ disabled_agents: [],
3785
+ disabled_commands: [],
3786
+ disabled_skills: [],
3787
+ agents: {},
3788
+ commands: {},
3789
+ skills: {
3790
+ enable: [],
3791
+ disable: []
3792
+ },
3793
+ hooks: {}
3794
+ };
3795
+ writeConfig(clikitConfigPath, defaultConfig);
3796
+ }
3797
+ console.log(`\u2713 CliKit installed (${pluginEntry})`);
3798
+ console.log(`\u2713 DCP installed (${DCP_PLUGIN_ENTRY})`);
3799
+ console.log(`\u2713 Config: ${configPath}`);
3800
+ console.log("\u2713 Restart OpenCode");
3801
+ return 0;
3802
+ } catch (err) {
3803
+ console.error(`\u2717 Install failed: ${err}`);
3804
+ return 1;
3805
+ }
3806
+ }
3807
+ function help() {
3808
+ console.log(`
3809
+ CliKit - OpenCode Plugin
3810
+
3811
+ Usage:
3812
+ bun x clikit-plugin <command>
3813
+
3814
+ Commands:
3815
+ install Install CliKit globally for OpenCode
3816
+ help Show this help message
3817
+ version Show version
3818
+
3819
+ Install options:
3820
+ --project Also scaffold project .opencode files (default: disabled)
3821
+
3822
+ Examples:
3823
+ bun x clikit-plugin install
3824
+ bun x clikit-plugin install --project
3825
+ `);
3826
+ }
3827
+ function version() {
3828
+ console.log(`clikit-plugin v${getPackageVersion()}`);
3829
+ }
3830
+ async function main() {
3831
+ const args = process.argv.slice(2);
3832
+ const command = args[0] || "help";
3833
+ const flags = args.slice(1);
3834
+ let exitCode = 0;
3835
+ switch (command) {
3836
+ case "install":
3837
+ case "i":
3838
+ exitCode = await install({
3839
+ includeProjectScaffold: flags.includes("--project")
3840
+ });
3841
+ break;
3842
+ case "help":
3843
+ case "-h":
3844
+ case "--help":
3845
+ help();
3846
+ break;
3847
+ case "version":
3848
+ case "-v":
3849
+ case "--version":
3850
+ version();
3851
+ break;
3852
+ default:
3853
+ console.error(`Unknown command: ${command}`);
3854
+ help();
3855
+ exitCode = 1;
3856
+ }
3857
+ process.exit(exitCode);
3858
+ }
3859
+ if (import.meta.main) {
3860
+ main().catch((err) => {
3861
+ console.error(err);
3862
+ process.exit(1);
3863
+ });
3864
+ }
3865
+
3503
3866
  // node_modules/zod/v4/classic/external.js
3504
3867
  var exports_external = {};
3505
3868
  __export(exports_external, {
@@ -3733,7 +4096,7 @@ __export(exports_external, {
3733
4096
  // node_modules/zod/v4/core/index.js
3734
4097
  var exports_core2 = {};
3735
4098
  __export(exports_core2, {
3736
- version: () => version,
4099
+ version: () => version2,
3737
4100
  util: () => exports_util,
3738
4101
  treeifyError: () => treeifyError,
3739
4102
  toJSONSchema: () => toJSONSchema,
@@ -4229,10 +4592,10 @@ function mergeDefs(...defs) {
4229
4592
  function cloneDef(schema) {
4230
4593
  return mergeDefs(schema._zod.def);
4231
4594
  }
4232
- function getElementAtPath(obj, path) {
4233
- if (!path)
4595
+ function getElementAtPath(obj, path2) {
4596
+ if (!path2)
4234
4597
  return obj;
4235
- return path.reduce((acc, key) => acc?.[key], obj);
4598
+ return path2.reduce((acc, key) => acc?.[key], obj);
4236
4599
  }
4237
4600
  function promiseAllObject(promisesObj) {
4238
4601
  const keys = Object.keys(promisesObj);
@@ -4591,11 +4954,11 @@ function aborted(x, startIndex = 0) {
4591
4954
  }
4592
4955
  return false;
4593
4956
  }
4594
- function prefixIssues(path, issues) {
4957
+ function prefixIssues(path2, issues) {
4595
4958
  return issues.map((iss) => {
4596
4959
  var _a;
4597
4960
  (_a = iss).path ?? (_a.path = []);
4598
- iss.path.unshift(path);
4961
+ iss.path.unshift(path2);
4599
4962
  return iss;
4600
4963
  });
4601
4964
  }
@@ -4763,7 +5126,7 @@ function treeifyError(error, _mapper) {
4763
5126
  return issue2.message;
4764
5127
  };
4765
5128
  const result = { errors: [] };
4766
- const processError = (error2, path = []) => {
5129
+ const processError = (error2, path2 = []) => {
4767
5130
  var _a, _b;
4768
5131
  for (const issue2 of error2.issues) {
4769
5132
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -4773,7 +5136,7 @@ function treeifyError(error, _mapper) {
4773
5136
  } else if (issue2.code === "invalid_element") {
4774
5137
  processError({ issues: issue2.issues }, issue2.path);
4775
5138
  } else {
4776
- const fullpath = [...path, ...issue2.path];
5139
+ const fullpath = [...path2, ...issue2.path];
4777
5140
  if (fullpath.length === 0) {
4778
5141
  result.errors.push(mapper(issue2));
4779
5142
  continue;
@@ -4805,8 +5168,8 @@ function treeifyError(error, _mapper) {
4805
5168
  }
4806
5169
  function toDotPath(_path) {
4807
5170
  const segs = [];
4808
- const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
4809
- for (const seg of path) {
5171
+ const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
5172
+ for (const seg of path2) {
4810
5173
  if (typeof seg === "number")
4811
5174
  segs.push(`[${seg}]`);
4812
5175
  else if (typeof seg === "symbol")
@@ -4990,10 +5353,10 @@ var nanoid = /^[a-zA-Z0-9_-]{21}$/;
4990
5353
  var duration = /^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
4991
5354
  var extendedDuration = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
4992
5355
  var guid = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
4993
- var uuid = (version) => {
4994
- if (!version)
5356
+ var uuid = (version2) => {
5357
+ if (!version2)
4995
5358
  return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
4996
- return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
5359
+ return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version2}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
4997
5360
  };
4998
5361
  var uuid4 = /* @__PURE__ */ uuid(4);
4999
5362
  var uuid6 = /* @__PURE__ */ uuid(6);
@@ -5652,7 +6015,7 @@ class Doc {
5652
6015
  }
5653
6016
 
5654
6017
  // node_modules/zod/v4/core/versions.js
5655
- var version = {
6018
+ var version2 = {
5656
6019
  major: 4,
5657
6020
  minor: 1,
5658
6021
  patch: 8
@@ -5664,7 +6027,7 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
5664
6027
  inst ?? (inst = {});
5665
6028
  inst._zod.def = def;
5666
6029
  inst._zod.bag = inst._zod.bag || {};
5667
- inst._zod.version = version;
6030
+ inst._zod.version = version2;
5668
6031
  const checks = [...inst._zod.def.checks ?? []];
5669
6032
  if (inst._zod.traits.has("$ZodCheck")) {
5670
6033
  checks.unshift(inst);
@@ -15823,15 +16186,18 @@ tool.schema = exports_external;
15823
16186
  // src/index.ts
15824
16187
  import { execFile as execFile3 } from "child_process";
15825
16188
  import { promisify as promisify3 } from "util";
16189
+ import * as fs11 from "fs";
16190
+ import * as path11 from "path";
16191
+ import * as os3 from "os";
15826
16192
 
15827
16193
  // src/agents/index.ts
15828
16194
  var import_gray_matter = __toESM(require_gray_matter(), 1);
15829
- import * as fs2 from "fs";
15830
- import * as path2 from "path";
16195
+ import * as fs3 from "fs";
16196
+ import * as path3 from "path";
15831
16197
 
15832
16198
  // src/hooks/error-logger.ts
15833
- import * as fs from "fs";
15834
- import * as path from "path";
16199
+ import * as fs2 from "fs";
16200
+ import * as path2 from "path";
15835
16201
  var BLOCKED_TOOL_ERROR_PREFIX = "[CliKit] Blocked tool execution:";
15836
16202
  var _initErrorBuffer = [];
15837
16203
  function bufferInitError(source, level, message, context) {
@@ -15874,10 +16240,10 @@ function formatHookErrorLog(hookName, error45, context) {
15874
16240
  }
15875
16241
  function writeErrorLog(hookName, error45, projectDir, context) {
15876
16242
  try {
15877
- const logDir = path.join(projectDir, ".opencode");
15878
- const logPath = path.join(logDir, "error-log.txt");
15879
- if (!fs.existsSync(logDir)) {
15880
- fs.mkdirSync(logDir, { recursive: true });
16243
+ const logDir = path2.join(projectDir, ".opencode");
16244
+ const logPath = path2.join(logDir, "error-log.txt");
16245
+ if (!fs2.existsSync(logDir)) {
16246
+ fs2.mkdirSync(logDir, { recursive: true });
15881
16247
  }
15882
16248
  const timestamp = new Date().toISOString();
15883
16249
  const message = getErrorMessage(error45);
@@ -15894,15 +16260,15 @@ ${stack}`] : [],
15894
16260
  ""
15895
16261
  ].join(`
15896
16262
  `);
15897
- fs.appendFileSync(logPath, entry, "utf-8");
16263
+ fs2.appendFileSync(logPath, entry, "utf-8");
15898
16264
  } catch {}
15899
16265
  }
15900
16266
  function writeBufferedErrorLog(entry, projectDir) {
15901
16267
  try {
15902
- const logDir = path.join(projectDir, ".opencode");
15903
- const logPath = path.join(logDir, "error-log.txt");
15904
- if (!fs.existsSync(logDir)) {
15905
- fs.mkdirSync(logDir, { recursive: true });
16268
+ const logDir = path2.join(projectDir, ".opencode");
16269
+ const logPath = path2.join(logDir, "error-log.txt");
16270
+ if (!fs2.existsSync(logDir)) {
16271
+ fs2.mkdirSync(logDir, { recursive: true });
15906
16272
  }
15907
16273
  const timestamp = new Date().toISOString();
15908
16274
  const contextStr = entry.context && Object.keys(entry.context).length > 0 ? `context: ${JSON.stringify(entry.context, null, 2)}` : "";
@@ -15915,29 +16281,29 @@ function writeBufferedErrorLog(entry, projectDir) {
15915
16281
  ""
15916
16282
  ].join(`
15917
16283
  `);
15918
- fs.appendFileSync(logPath, line, "utf-8");
16284
+ fs2.appendFileSync(logPath, line, "utf-8");
15919
16285
  } catch {}
15920
16286
  }
15921
16287
 
15922
16288
  // src/agents/index.ts
15923
16289
  var AGENTS_DIR_CANDIDATES = [
15924
16290
  import.meta.dir,
15925
- path2.join(import.meta.dir, "../src/agents"),
15926
- path2.join(import.meta.dir, "../../src/agents"),
15927
- path2.join(import.meta.dir, "../agents")
16291
+ path3.join(import.meta.dir, "../src/agents"),
16292
+ path3.join(import.meta.dir, "../../src/agents"),
16293
+ path3.join(import.meta.dir, "../agents")
15928
16294
  ];
15929
16295
  function resolveAgentsDir() {
15930
16296
  for (const dir of AGENTS_DIR_CANDIDATES) {
15931
- if (!fs2.existsSync(dir))
16297
+ if (!fs3.existsSync(dir))
15932
16298
  continue;
15933
16299
  try {
15934
- const hasAgentFiles = fs2.readdirSync(dir).some((f) => f.endsWith(".md") && f !== "AGENTS.md");
16300
+ const hasAgentFiles = fs3.readdirSync(dir).some((f) => f.endsWith(".md") && f !== "AGENTS.md");
15935
16301
  if (hasAgentFiles)
15936
16302
  return dir;
15937
16303
  } catch {}
15938
16304
  }
15939
16305
  for (const dir of AGENTS_DIR_CANDIDATES) {
15940
- if (fs2.existsSync(dir)) {
16306
+ if (fs3.existsSync(dir)) {
15941
16307
  return dir;
15942
16308
  }
15943
16309
  }
@@ -15946,7 +16312,7 @@ function resolveAgentsDir() {
15946
16312
  var VALID_MODES = new Set(["subagent", "primary", "all"]);
15947
16313
  function validateFrontmatter(frontmatter, filePath) {
15948
16314
  const warnings = [];
15949
- const name = path2.basename(filePath, ".md");
16315
+ const name = path3.basename(filePath, ".md");
15950
16316
  if (!frontmatter.description) {
15951
16317
  warnings.push(`[${name}] Missing 'description' \u2014 agent will have empty description`);
15952
16318
  }
@@ -15969,7 +16335,7 @@ function validateFrontmatter(frontmatter, filePath) {
15969
16335
  }
15970
16336
  function parseAgentMarkdown(filePath) {
15971
16337
  try {
15972
- const content = fs2.readFileSync(filePath, "utf-8");
16338
+ const content = fs3.readFileSync(filePath, "utf-8");
15973
16339
  const { data: frontmatter, content: body } = import_gray_matter.default(content);
15974
16340
  const warnings = validateFrontmatter(frontmatter, filePath);
15975
16341
  for (const warning of warnings) {
@@ -16005,13 +16371,13 @@ function parseAgentMarkdown(filePath) {
16005
16371
  function loadAgents() {
16006
16372
  const agents = {};
16007
16373
  const agentsDir = resolveAgentsDir();
16008
- if (!fs2.existsSync(agentsDir)) {
16374
+ if (!fs3.existsSync(agentsDir)) {
16009
16375
  return agents;
16010
16376
  }
16011
- const files = fs2.readdirSync(agentsDir).filter((f) => f.endsWith(".md") && f !== "AGENTS.md").sort();
16377
+ const files = fs3.readdirSync(agentsDir).filter((f) => f.endsWith(".md") && f !== "AGENTS.md").sort();
16012
16378
  for (const file2 of files) {
16013
- const agentName = path2.basename(file2, ".md");
16014
- const agentPath = path2.join(agentsDir, file2);
16379
+ const agentName = path3.basename(file2, ".md");
16380
+ const agentPath = path3.join(agentsDir, file2);
16015
16381
  const agent = parseAgentMarkdown(agentPath);
16016
16382
  if (agent) {
16017
16383
  agents[agentName] = agent;
@@ -16022,10 +16388,10 @@ function loadAgents() {
16022
16388
  var _cachedAgents = null;
16023
16389
  var _cachedAgentsFingerprint = "";
16024
16390
  function getAgentsFingerprint(agentsDir) {
16025
- const files = fs2.readdirSync(agentsDir).filter((f) => f.endsWith(".md") && f !== "AGENTS.md").sort();
16391
+ const files = fs3.readdirSync(agentsDir).filter((f) => f.endsWith(".md") && f !== "AGENTS.md").sort();
16026
16392
  const parts = files.map((file2) => {
16027
- const fullPath = path2.join(agentsDir, file2);
16028
- const stat = fs2.statSync(fullPath);
16393
+ const fullPath = path3.join(agentsDir, file2);
16394
+ const stat = fs3.statSync(fullPath);
16029
16395
  const size = stat.size;
16030
16396
  return `${file2}:${stat.mtimeMs}:${size}`;
16031
16397
  });
@@ -16047,16 +16413,16 @@ function getBuiltinAgents() {
16047
16413
 
16048
16414
  // src/commands/index.ts
16049
16415
  var import_gray_matter2 = __toESM(require_gray_matter(), 1);
16050
- import * as fs3 from "fs";
16051
- import * as path3 from "path";
16416
+ import * as fs4 from "fs";
16417
+ import * as path4 from "path";
16052
16418
  var COMMANDS_DIR_CANDIDATES = [
16053
- path3.join(import.meta.dir, "../command"),
16054
- path3.join(import.meta.dir, "../../command"),
16055
- path3.join(import.meta.dir, "../../../command")
16419
+ path4.join(import.meta.dir, "../command"),
16420
+ path4.join(import.meta.dir, "../../command"),
16421
+ path4.join(import.meta.dir, "../../../command")
16056
16422
  ];
16057
16423
  function resolveCommandsDir() {
16058
16424
  for (const dir of COMMANDS_DIR_CANDIDATES) {
16059
- if (fs3.existsSync(dir)) {
16425
+ if (fs4.existsSync(dir)) {
16060
16426
  return dir;
16061
16427
  }
16062
16428
  }
@@ -16064,7 +16430,7 @@ function resolveCommandsDir() {
16064
16430
  }
16065
16431
  function parseCommandMarkdown(filePath) {
16066
16432
  try {
16067
- const content = fs3.readFileSync(filePath, "utf-8");
16433
+ const content = fs4.readFileSync(filePath, "utf-8");
16068
16434
  const { data: frontmatter, content: body } = import_gray_matter2.default(content);
16069
16435
  const config2 = {
16070
16436
  description: frontmatter.description || "",
@@ -16091,13 +16457,13 @@ function parseCommandMarkdown(filePath) {
16091
16457
  function loadCommands() {
16092
16458
  const commands = {};
16093
16459
  const commandsDir = resolveCommandsDir();
16094
- if (!fs3.existsSync(commandsDir)) {
16460
+ if (!fs4.existsSync(commandsDir)) {
16095
16461
  return commands;
16096
16462
  }
16097
- const files = fs3.readdirSync(commandsDir).filter((f) => f.endsWith(".md")).sort();
16463
+ const files = fs4.readdirSync(commandsDir).filter((f) => f.endsWith(".md")).sort();
16098
16464
  for (const file2 of files) {
16099
- const commandName = path3.basename(file2, ".md");
16100
- const commandPath = path3.join(commandsDir, file2);
16465
+ const commandName = path4.basename(file2, ".md");
16466
+ const commandPath = path4.join(commandsDir, file2);
16101
16467
  const command = parseCommandMarkdown(commandPath);
16102
16468
  if (command) {
16103
16469
  commands[commandName] = command;
@@ -16108,10 +16474,10 @@ function loadCommands() {
16108
16474
  var _cachedCommands = null;
16109
16475
  var _cachedCommandsFingerprint = "";
16110
16476
  function getCommandsFingerprint(commandsDir) {
16111
- const files = fs3.readdirSync(commandsDir).filter((f) => f.endsWith(".md")).sort();
16477
+ const files = fs4.readdirSync(commandsDir).filter((f) => f.endsWith(".md")).sort();
16112
16478
  const parts = files.map((file2) => {
16113
- const fullPath = path3.join(commandsDir, file2);
16114
- const stat = fs3.statSync(fullPath);
16479
+ const fullPath = path4.join(commandsDir, file2);
16480
+ const stat = fs4.statSync(fullPath);
16115
16481
  return `${file2}:${stat.mtimeMs}`;
16116
16482
  });
16117
16483
  return parts.join("|");
@@ -16132,16 +16498,16 @@ function getBuiltinCommands() {
16132
16498
 
16133
16499
  // src/skills/index.ts
16134
16500
  var import_gray_matter3 = __toESM(require_gray_matter(), 1);
16135
- import * as fs4 from "fs";
16136
- import * as path4 from "path";
16501
+ import * as fs5 from "fs";
16502
+ import * as path5 from "path";
16137
16503
  var SKILLS_DIR_CANDIDATES = [
16138
- path4.join(import.meta.dir, "../skill"),
16139
- path4.join(import.meta.dir, "../../skill"),
16140
- path4.join(import.meta.dir, "../../../skill")
16504
+ path5.join(import.meta.dir, "../skill"),
16505
+ path5.join(import.meta.dir, "../../skill"),
16506
+ path5.join(import.meta.dir, "../../../skill")
16141
16507
  ];
16142
16508
  function resolveSkillsDir() {
16143
16509
  for (const dir of SKILLS_DIR_CANDIDATES) {
16144
- if (fs4.existsSync(dir)) {
16510
+ if (fs5.existsSync(dir)) {
16145
16511
  return dir;
16146
16512
  }
16147
16513
  }
@@ -16150,23 +16516,23 @@ function resolveSkillsDir() {
16150
16516
  function getBuiltinSkills() {
16151
16517
  const skills = {};
16152
16518
  const skillsDir = resolveSkillsDir();
16153
- if (!fs4.existsSync(skillsDir)) {
16519
+ if (!fs5.existsSync(skillsDir)) {
16154
16520
  bufferInitError("skills", "warn", `Skills directory not found: ${skillsDir}`);
16155
16521
  return skills;
16156
16522
  }
16157
- const skillDirs = fs4.readdirSync(skillsDir, { withFileTypes: true });
16523
+ const skillDirs = fs5.readdirSync(skillsDir, { withFileTypes: true });
16158
16524
  for (const dirent of skillDirs) {
16159
16525
  if (!dirent.isDirectory())
16160
16526
  continue;
16161
16527
  const skillName = dirent.name;
16162
- const skillPath = path4.join(skillsDir, skillName);
16163
- const skillMdPath = path4.join(skillPath, "SKILL.md");
16164
- if (!fs4.existsSync(skillMdPath)) {
16528
+ const skillPath = path5.join(skillsDir, skillName);
16529
+ const skillMdPath = path5.join(skillPath, "SKILL.md");
16530
+ if (!fs5.existsSync(skillMdPath)) {
16165
16531
  bufferInitError("skills", "warn", `Missing SKILL.md for skill: ${skillName}`, { skillPath });
16166
16532
  continue;
16167
16533
  }
16168
16534
  try {
16169
- const fileContent = fs4.readFileSync(skillMdPath, "utf-8");
16535
+ const fileContent = fs5.readFileSync(skillMdPath, "utf-8");
16170
16536
  const { data, content } = import_gray_matter3.default(fileContent);
16171
16537
  skills[skillName] = {
16172
16538
  name: data.name || skillName,
@@ -16185,9 +16551,9 @@ function getBuiltinSkills() {
16185
16551
  }
16186
16552
 
16187
16553
  // src/config.ts
16188
- import * as fs5 from "fs";
16189
- import * as path5 from "path";
16190
- import * as os from "os";
16554
+ import * as fs6 from "fs";
16555
+ import * as path6 from "path";
16556
+ import * as os2 from "os";
16191
16557
  var DEFAULT_CONFIG = {
16192
16558
  disabled_agents: [],
16193
16559
  disabled_commands: [],
@@ -16277,15 +16643,15 @@ var DEFAULT_CONFIG = {
16277
16643
  };
16278
16644
  function getUserConfigDir() {
16279
16645
  if (process.platform === "win32") {
16280
- return process.env.APPDATA || path5.join(os.homedir(), "AppData", "Roaming");
16646
+ return process.env.APPDATA || path6.join(os2.homedir(), "AppData", "Roaming");
16281
16647
  }
16282
- return process.env.XDG_CONFIG_HOME || path5.join(os.homedir(), ".config");
16648
+ return process.env.XDG_CONFIG_HOME || path6.join(os2.homedir(), ".config");
16283
16649
  }
16284
16650
  function getOpenCodeConfigDir() {
16285
16651
  if (process.env.OPENCODE_CONFIG_DIR) {
16286
16652
  return process.env.OPENCODE_CONFIG_DIR;
16287
16653
  }
16288
- return path5.join(getUserConfigDir(), "opencode");
16654
+ return path6.join(getUserConfigDir(), "opencode");
16289
16655
  }
16290
16656
  function stripJsonComments(content) {
16291
16657
  let result = "";
@@ -16343,10 +16709,10 @@ function stripJsonComments(content) {
16343
16709
  }
16344
16710
  function loadJsonFile(filePath) {
16345
16711
  try {
16346
- if (!fs5.existsSync(filePath)) {
16712
+ if (!fs6.existsSync(filePath)) {
16347
16713
  return null;
16348
16714
  }
16349
- const content = fs5.readFileSync(filePath, "utf-8");
16715
+ const content = fs6.readFileSync(filePath, "utf-8");
16350
16716
  try {
16351
16717
  return JSON.parse(content);
16352
16718
  } catch {
@@ -16380,12 +16746,12 @@ function loadCliKitConfig(projectDirectory) {
16380
16746
  const userBaseDir = getOpenCodeConfigDir();
16381
16747
  const projectBaseDirs = [
16382
16748
  safeDir,
16383
- path5.join(safeDir, ".opencode")
16749
+ path6.join(safeDir, ".opencode")
16384
16750
  ];
16385
16751
  const configCandidates = ["clikit.jsonc", "clikit.json", "clikit.config.json"];
16386
16752
  let config2 = { ...DEFAULT_CONFIG };
16387
16753
  for (const candidate of configCandidates) {
16388
- const userConfigPath = path5.join(userBaseDir, candidate);
16754
+ const userConfigPath = path6.join(userBaseDir, candidate);
16389
16755
  const userConfig = loadJsonFile(userConfigPath);
16390
16756
  if (userConfig) {
16391
16757
  config2 = deepMerge(config2, userConfig);
@@ -16394,7 +16760,7 @@ function loadCliKitConfig(projectDirectory) {
16394
16760
  }
16395
16761
  for (const baseDir of projectBaseDirs) {
16396
16762
  for (const candidate of configCandidates) {
16397
- const projectConfigPath = path5.join(baseDir, candidate);
16763
+ const projectConfigPath = path6.join(baseDir, candidate);
16398
16764
  const projectConfig = loadJsonFile(projectConfigPath);
16399
16765
  if (projectConfig) {
16400
16766
  config2 = deepMerge(config2, projectConfig);
@@ -16904,8 +17270,8 @@ function formatTruncationLog(result) {
16904
17270
  return `[CliKit:truncator] Truncated output: ${result.originalLines} \u2192 ${result.truncatedLines} lines, saved ${(saved / 1024).toFixed(1)}KB`;
16905
17271
  }
16906
17272
  // src/hooks/memory-digest.ts
16907
- import * as fs6 from "fs";
16908
- import * as path6 from "path";
17273
+ import * as fs7 from "fs";
17274
+ import * as path7 from "path";
16909
17275
  import { Database } from "bun:sqlite";
16910
17276
  function parseJsonArray(value) {
16911
17277
  if (typeof value !== "string" || !value.trim())
@@ -16925,7 +17291,7 @@ function formatDate(iso) {
16925
17291
  }
16926
17292
  }
16927
17293
  function writeTopicFile(memoryDir, type, heading, rows) {
16928
- const topicPath = path6.join(memoryDir, `${type}.md`);
17294
+ const topicPath = path7.join(memoryDir, `${type}.md`);
16929
17295
  const lines = [];
16930
17296
  lines.push(`# ${heading}`);
16931
17297
  lines.push("");
@@ -16966,16 +17332,16 @@ function writeTopicFile(memoryDir, type, heading, rows) {
16966
17332
  lines.push("---");
16967
17333
  lines.push("");
16968
17334
  }
16969
- fs6.writeFileSync(topicPath, lines.join(`
17335
+ fs7.writeFileSync(topicPath, lines.join(`
16970
17336
  `), "utf-8");
16971
17337
  }
16972
17338
  function generateMemoryDigest(projectDir, config2) {
16973
17339
  const result = { written: false, path: "", counts: {} };
16974
17340
  if (typeof projectDir !== "string" || !projectDir)
16975
17341
  return result;
16976
- const memoryDir = path6.join(projectDir, ".opencode", "memory");
16977
- const dbPath = path6.join(memoryDir, "memory.db");
16978
- if (!fs6.existsSync(dbPath)) {
17342
+ const memoryDir = path7.join(projectDir, ".opencode", "memory");
17343
+ const dbPath = path7.join(memoryDir, "memory.db");
17344
+ if (!fs7.existsSync(dbPath)) {
16979
17345
  return result;
16980
17346
  }
16981
17347
  const compactMode = config2?.compact_mode !== false;
@@ -17040,14 +17406,14 @@ function generateMemoryDigest(projectDir, config2) {
17040
17406
  sections.push("*No observations found in memory database.*");
17041
17407
  sections.push("");
17042
17408
  }
17043
- const digestPath = path6.join(memoryDir, "_digest.md");
17409
+ const digestPath = path7.join(memoryDir, "_digest.md");
17044
17410
  const content = sections.join(`
17045
17411
  `);
17046
17412
  try {
17047
- if (!fs6.existsSync(memoryDir)) {
17048
- fs6.mkdirSync(memoryDir, { recursive: true });
17413
+ if (!fs7.existsSync(memoryDir)) {
17414
+ fs7.mkdirSync(memoryDir, { recursive: true });
17049
17415
  }
17050
- fs6.writeFileSync(digestPath, content, "utf-8");
17416
+ fs7.writeFileSync(digestPath, content, "utf-8");
17051
17417
  result.written = true;
17052
17418
  result.path = digestPath;
17053
17419
  } catch {}
@@ -17061,8 +17427,8 @@ function formatDigestLog(result) {
17061
17427
  return `[CliKit:memory-digest] Generated digest: ${parts || "empty"}`;
17062
17428
  }
17063
17429
  // src/hooks/todo-beads-sync.ts
17064
- import * as fs7 from "fs";
17065
- import * as path7 from "path";
17430
+ import * as fs8 from "fs";
17431
+ import * as path8 from "path";
17066
17432
  import { Database as Database2 } from "bun:sqlite";
17067
17433
  import { execFile } from "child_process";
17068
17434
  import { promisify } from "util";
@@ -17217,8 +17583,8 @@ function syncTodosToBeads(projectDirectory, sessionID, todos, config2) {
17217
17583
  skippedReason: "Todo sync disabled; Beads is authoritative"
17218
17584
  };
17219
17585
  }
17220
- const beadsDbPath = path7.join(projectDirectory, ".beads", "beads.db");
17221
- if (!fs7.existsSync(beadsDbPath)) {
17586
+ const beadsDbPath = path8.join(projectDirectory, ".beads", "beads.db");
17587
+ if (!fs8.existsSync(beadsDbPath)) {
17222
17588
  return {
17223
17589
  synced: false,
17224
17590
  sessionID,
@@ -17248,7 +17614,7 @@ function syncTodosToBeads(projectDirectory, sessionID, todos, config2) {
17248
17614
  throw lastError instanceof Error ? lastError : new Error("Todo-Beads sync failed after retries");
17249
17615
  }
17250
17616
  function flushBeadsJsonl(projectDirectory, result) {
17251
- const jsonlPath = path7.join(projectDirectory, ".beads", "issues.jsonl");
17617
+ const jsonlPath = path8.join(projectDirectory, ".beads", "issues.jsonl");
17252
17618
  execFileAsync("bd", ["export", "--force", "-o", jsonlPath], {
17253
17619
  cwd: projectDirectory,
17254
17620
  timeout: 5000
@@ -17265,8 +17631,8 @@ function formatTodoBeadsSyncLog(result) {
17265
17631
  return `[CliKit:todo-beads-sync] session=${result.sessionID} todos=${result.totalTodos} created=${result.created} updated=${result.updated} closed=${result.closed}`;
17266
17632
  }
17267
17633
  // src/hooks/beads-context.ts
17268
- import * as fs8 from "fs";
17269
- import * as path8 from "path";
17634
+ import * as fs9 from "fs";
17635
+ import * as path9 from "path";
17270
17636
  import { Database as Database3 } from "bun:sqlite";
17271
17637
  var BEADS_CONTEXT_BUSY_TIMEOUT_MS = 2000;
17272
17638
  var PRIORITY_LABELS = {
@@ -17282,8 +17648,8 @@ var STATUS_ICONS = {
17282
17648
  closed: "\u2713"
17283
17649
  };
17284
17650
  function openBeadsDbReadonly(projectDirectory) {
17285
- const beadsDbPath = path8.join(projectDirectory, ".beads", "beads.db");
17286
- if (!fs8.existsSync(beadsDbPath)) {
17651
+ const beadsDbPath = path9.join(projectDirectory, ".beads", "beads.db");
17652
+ if (!fs9.existsSync(beadsDbPath)) {
17287
17653
  return null;
17288
17654
  }
17289
17655
  try {
@@ -17440,8 +17806,8 @@ function shouldAttemptTilthForTool(toolName, toolInput) {
17440
17806
  const normalized = toolName.toLowerCase();
17441
17807
  if (!normalized.includes("read"))
17442
17808
  return false;
17443
- const path9 = extractFilePath(toolInput);
17444
- return typeof path9 === "string" && path9.length > 0;
17809
+ const path10 = extractFilePath(toolInput);
17810
+ return typeof path10 === "string" && path10.length > 0;
17445
17811
  }
17446
17812
  function extractFilePath(toolInput) {
17447
17813
  for (const key of ["filePath", "file_path", "path", "file"]) {
@@ -17527,12 +17893,12 @@ import { execFile as execFile2 } from "child_process";
17527
17893
  import { promisify as promisify2 } from "util";
17528
17894
 
17529
17895
  // src/tools/memory-db.ts
17530
- import * as fs9 from "fs";
17531
- import * as path9 from "path";
17896
+ import * as fs10 from "fs";
17897
+ import * as path10 from "path";
17532
17898
  import { Database as Database4 } from "bun:sqlite";
17533
17899
  function getMemoryPaths(projectDir = process.cwd()) {
17534
- const memoryDir = path9.join(projectDir, ".opencode", "memory");
17535
- const memoryDbPath = path9.join(memoryDir, "memory.db");
17900
+ const memoryDir = path10.join(projectDir, ".opencode", "memory");
17901
+ const memoryDbPath = path10.join(memoryDir, "memory.db");
17536
17902
  return { memoryDir, memoryDbPath };
17537
17903
  }
17538
17904
  function ensureObservationSchema(db) {
@@ -17594,8 +17960,8 @@ function ensureObservationSchema(db) {
17594
17960
  function openMemoryDb(options2 = {}) {
17595
17961
  const { projectDir, readonly: readonly2 = false } = options2;
17596
17962
  const { memoryDir, memoryDbPath } = getMemoryPaths(projectDir);
17597
- if (!readonly2 && !fs9.existsSync(memoryDir)) {
17598
- fs9.mkdirSync(memoryDir, { recursive: true });
17963
+ if (!readonly2 && !fs10.existsSync(memoryDir)) {
17964
+ fs10.mkdirSync(memoryDir, { recursive: true });
17599
17965
  }
17600
17966
  const db = new Database4(memoryDbPath, readonly2 ? { readonly: true } : undefined);
17601
17967
  if (!readonly2) {
@@ -17953,6 +18319,49 @@ function buildSummary(sections, maxTokens) {
17953
18319
 
17954
18320
  // src/index.ts
17955
18321
  var execFileAsync3 = promisify3(execFile3);
18322
+ var DCP_PLUGIN_ENTRY2 = "@tarquinen/opencode-dcp@beta";
18323
+ var DCP_PLUGIN_BASE = "@tarquinen/opencode-dcp";
18324
+ function ensureDcpInConfig() {
18325
+ try {
18326
+ const configDir = (() => {
18327
+ if (process.env.OPENCODE_CONFIG_DIR)
18328
+ return process.env.OPENCODE_CONFIG_DIR;
18329
+ const home = (() => {
18330
+ if (process.env.SNAP_REAL_HOME)
18331
+ return process.env.SNAP_REAL_HOME;
18332
+ const h = os3.homedir();
18333
+ const m = h.match(/^(\/home\/[^/]+)\/snap\//);
18334
+ return m ? m[1] : h;
18335
+ })();
18336
+ if (process.platform === "win32") {
18337
+ return path11.join(process.env.APPDATA || path11.join(home, "AppData", "Roaming"), "opencode");
18338
+ }
18339
+ return path11.join(process.env.XDG_CONFIG_HOME || path11.join(home, ".config"), "opencode");
18340
+ })();
18341
+ const jsoncPath = path11.join(configDir, "opencode.jsonc");
18342
+ const jsonPath = path11.join(configDir, "opencode.json");
18343
+ const configPath = fs11.existsSync(jsoncPath) ? jsoncPath : jsonPath;
18344
+ if (!fs11.existsSync(configPath))
18345
+ return;
18346
+ const raw = fs11.readFileSync(configPath, "utf-8");
18347
+ let config2;
18348
+ try {
18349
+ config2 = JSON.parse(raw);
18350
+ } catch {
18351
+ const cleaned = raw.replace(/\/\*[\s\S]*?\*\//g, "").replace(/,\s*([}\]])/g, "$1");
18352
+ config2 = JSON.parse(cleaned);
18353
+ }
18354
+ const plugins = Array.isArray(config2.plugin) ? config2.plugin.filter((p) => typeof p === "string") : [];
18355
+ const hasDcp = plugins.some((p) => p === DCP_PLUGIN_BASE || p.startsWith(`${DCP_PLUGIN_BASE}@`));
18356
+ if (hasDcp)
18357
+ return;
18358
+ const updated = upsertPluginEntry(plugins, DCP_PLUGIN_ENTRY2);
18359
+ const tmpPath = `${configPath}.tmp`;
18360
+ fs11.writeFileSync(tmpPath, JSON.stringify({ ...config2, plugin: updated }, null, 2) + `
18361
+ `);
18362
+ fs11.renameSync(tmpPath, configPath);
18363
+ } catch {}
18364
+ }
17956
18365
  var CliKitPlugin = async (ctx) => {
17957
18366
  const todosBySession = new Map;
17958
18367
  const defaultMcpEntries = {
@@ -18209,6 +18618,7 @@ ${(content || "").trim()}`.trim();
18209
18618
  ].join(`
18210
18619
  `);
18211
18620
  }
18621
+ ensureDcpInConfig();
18212
18622
  const pluginConfig = loadCliKitConfig(ctx.directory) ?? {};
18213
18623
  const debugLogsEnabled = pluginConfig.hooks?.session_logging === true && process.env.CLIKIT_DEBUG === "1";
18214
18624
  const toolLogsEnabled = pluginConfig.hooks?.tool_logging === true && process.env.CLIKIT_DEBUG === "1";