oneagent 0.3.1 → 0.4.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.
Files changed (2) hide show
  1. package/dist/index.js +469 -175
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1387,6 +1387,9 @@ function timeAgo(date) {
1387
1387
  return `${months}mo ago`;
1388
1388
  return `${Math.floor(months / 12)}y ago`;
1389
1389
  }
1390
+
1391
+ // ../core/src/constants.ts
1392
+ var ONEAGENT_DIR = ".oneagent";
1390
1393
  // ../core/src/agents.ts
1391
1394
  var AGENT_DEFINITIONS;
1392
1395
  var init_agents = __esm(() => {
@@ -1436,7 +1439,7 @@ var init_agents = __esm(() => {
1436
1439
  target: "copilot",
1437
1440
  displayName: "GitHub Copilot",
1438
1441
  hint: ".github/instructions/*.instructions.md",
1439
- detectIndicators: [".github/copilot-instructions.md", ".github"],
1442
+ detectIndicators: [".github/copilot-instructions.md", ".github/instructions"],
1440
1443
  mainFile: ".github/copilot-instructions.md",
1441
1444
  skillsDir: ".github/skills"
1442
1445
  }
@@ -8415,9 +8418,10 @@ async function writeConfig(root, config) {
8415
8418
  await fs.mkdir(path.dirname(filePath), { recursive: true });
8416
8419
  await fs.writeFile(filePath, $stringify(config));
8417
8420
  }
8418
- var CONFIG_REL = ".oneagent/config.yml", ALL_AGENT_TARGETS;
8421
+ var CONFIG_REL, ALL_AGENT_TARGETS;
8419
8422
  var init_config = __esm(() => {
8420
8423
  init_dist4();
8424
+ CONFIG_REL = `${ONEAGENT_DIR}/config.yml`;
8421
8425
  ALL_AGENT_TARGETS = ["claude", "cursor", "windsurf", "opencode", "copilot"];
8422
8426
  });
8423
8427
 
@@ -8431,7 +8435,7 @@ async function readDetectedFile(root, rel) {
8431
8435
  if (stat.isSymbolicLink()) {
8432
8436
  const linkTarget = await fs2.readlink(absolutePath);
8433
8437
  const resolved = path2.resolve(path2.dirname(absolutePath), linkTarget);
8434
- if (resolved.startsWith(path2.join(root, ".one")))
8438
+ if (resolved.startsWith(path2.join(root, ONEAGENT_DIR)))
8435
8439
  return null;
8436
8440
  }
8437
8441
  const content = await fs2.readFile(absolutePath, "utf-8");
@@ -8483,7 +8487,7 @@ var init_detect = __esm(() => {
8483
8487
  import path3 from "path";
8484
8488
  import fs3 from "fs/promises";
8485
8489
  async function readRules(root) {
8486
- const rulesDir = path3.join(root, ".oneagent/rules");
8490
+ const rulesDir = path3.join(root, ONEAGENT_DIR, "rules");
8487
8491
  try {
8488
8492
  const files = await fs3.readdir(rulesDir);
8489
8493
  return files.filter((f) => f.endsWith(".md")).map((f) => ({ name: path3.basename(f, ".md"), path: path3.join(rulesDir, f) })).sort((a, b) => a.name.localeCompare(b.name));
@@ -8518,7 +8522,7 @@ async function readSkillFile(filePath) {
8518
8522
  return { name: path4.basename(filePath, ".md"), path: filePath, description, mode, content };
8519
8523
  }
8520
8524
  async function readSkills(root) {
8521
- const skillsDir = path4.join(root, ".oneagent/skills");
8525
+ const skillsDir = path4.join(root, ONEAGENT_DIR, "skills");
8522
8526
  try {
8523
8527
  const files = await fs4.readdir(skillsDir);
8524
8528
  const mdFiles = files.filter((f) => f.endsWith(".md"));
@@ -8542,15 +8546,26 @@ async function ensureDir(dirPath) {
8542
8546
  async function createSymlink(symlinkPath, target) {
8543
8547
  await ensureDir(path5.dirname(symlinkPath));
8544
8548
  try {
8545
- await fs5.rm(symlinkPath, { recursive: true });
8549
+ const stat = await fs5.lstat(symlinkPath);
8550
+ if (stat.isSymbolicLink() && await fs5.readlink(symlinkPath) === target)
8551
+ return;
8546
8552
  } catch {}
8547
- await fs5.symlink(target, symlinkPath);
8553
+ for (let attempt = 0;attempt < 3; attempt++) {
8554
+ await fs5.rm(symlinkPath, { recursive: true, force: true });
8555
+ try {
8556
+ await fs5.symlink(target, symlinkPath);
8557
+ return;
8558
+ } catch (err) {
8559
+ if (err.code !== "EEXIST" || attempt === 2)
8560
+ throw err;
8561
+ }
8562
+ }
8548
8563
  }
8549
8564
  function relativeTarget(symlinkPath, targetAbsPath) {
8550
8565
  return path5.relative(path5.dirname(symlinkPath), targetAbsPath);
8551
8566
  }
8552
8567
  function buildMainSymlinks(root, targets) {
8553
- const instructionsAbs = path5.join(root, ".oneagent/instructions.md");
8568
+ const instructionsAbs = path5.join(root, ONEAGENT_DIR, "instructions.md");
8554
8569
  const seen = new Map;
8555
8570
  for (const target of targets) {
8556
8571
  const def = AGENT_DEFINITIONS.find((d2) => d2.target === target);
@@ -8566,21 +8581,21 @@ function buildMainSymlinks(root, targets) {
8566
8581
  return Array.from(seen.values());
8567
8582
  }
8568
8583
  function buildRulesSymlinks(root, targets) {
8569
- const targetAbs = path5.join(root, ".oneagent/rules");
8584
+ const targetAbs = path5.join(root, ONEAGENT_DIR, "rules");
8570
8585
  return AGENT_DEFINITIONS.filter((d2) => targets.includes(d2.target) && d2.rulesDir).map((d2) => {
8571
8586
  const symlinkPath = path5.join(root, d2.rulesDir);
8572
8587
  return { symlinkPath, target: relativeTarget(symlinkPath, targetAbs), label: d2.rulesDir };
8573
8588
  });
8574
8589
  }
8575
8590
  function buildSkillSymlinks(root, targets) {
8576
- const targetAbs = path5.join(root, ".oneagent/skills");
8591
+ const targetAbs = path5.join(root, ONEAGENT_DIR, "skills");
8577
8592
  return AGENT_DEFINITIONS.filter((d2) => targets.includes(d2.target) && d2.skillsDir).map((d2) => {
8578
8593
  const symlinkPath = path5.join(root, d2.skillsDir);
8579
8594
  return { symlinkPath, target: relativeTarget(symlinkPath, targetAbs), label: d2.skillsDir };
8580
8595
  });
8581
8596
  }
8582
8597
  function buildCommandSymlinks(root, targets) {
8583
- const targetAbs = path5.join(root, ".oneagent/commands");
8598
+ const targetAbs = path5.join(root, ONEAGENT_DIR, "commands");
8584
8599
  return AGENT_DEFINITIONS.filter((d2) => targets.includes(d2.target) && d2.commandsDir).map((d2) => {
8585
8600
  const symlinkPath = path5.join(root, d2.commandsDir);
8586
8601
  return { symlinkPath, target: relativeTarget(symlinkPath, targetAbs), label: d2.commandsDir };
@@ -8588,7 +8603,7 @@ function buildCommandSymlinks(root, targets) {
8588
8603
  }
8589
8604
  function buildAgentsDirSymlinks(root) {
8590
8605
  const symlinkPath = path5.join(root, ".agents/skills");
8591
- const targetAbs = path5.join(root, ".oneagent/skills");
8606
+ const targetAbs = path5.join(root, ONEAGENT_DIR, "skills");
8592
8607
  return [{ symlinkPath, target: relativeTarget(symlinkPath, targetAbs), label: ".agents/skills" }];
8593
8608
  }
8594
8609
  async function migrateFilesFromDir(srcDir, destDir, root) {
@@ -8600,9 +8615,22 @@ async function migrateFilesFromDir(srcDir, destDir, root) {
8600
8615
  return;
8601
8616
  }
8602
8617
  for (const entry of entries) {
8603
- if (!entry.isFile())
8604
- continue;
8605
8618
  const srcFile = path5.join(srcDir, entry.name);
8619
+ const fileStat = await fs5.lstat(srcFile);
8620
+ if (fileStat.isSymbolicLink())
8621
+ continue;
8622
+ if (fileStat.isDirectory()) {
8623
+ const destSub = path5.join(destDir, entry.name);
8624
+ try {
8625
+ await fs5.access(destSub);
8626
+ } catch {
8627
+ await fs5.mkdir(destDir, { recursive: true });
8628
+ await fs5.rename(srcFile, destSub);
8629
+ }
8630
+ continue;
8631
+ }
8632
+ if (!fileStat.isFile())
8633
+ continue;
8606
8634
  const destFile = path5.join(destDir, entry.name);
8607
8635
  let destExists = false;
8608
8636
  try {
@@ -8615,7 +8643,7 @@ async function migrateFilesFromDir(srcDir, destDir, root) {
8615
8643
  fs5.readFile(destFile, "utf-8")
8616
8644
  ]);
8617
8645
  if (srcContent !== destContent) {
8618
- const backupDir = path5.join(root, ".oneagent/backup");
8646
+ const backupDir = path5.join(root, ONEAGENT_DIR, "backup");
8619
8647
  await fs5.mkdir(backupDir, { recursive: true });
8620
8648
  const safeName = path5.relative(root, srcFile).replace(/\//g, "_");
8621
8649
  await fs5.writeFile(path5.join(backupDir, safeName), srcContent);
@@ -8639,21 +8667,75 @@ async function migrateAndRemoveDir(src, dest, root) {
8639
8667
  await fs5.rm(src, { recursive: true, force: true });
8640
8668
  }
8641
8669
  async function migrateRuleAndSkillFiles(root) {
8642
- const destRules = path5.join(root, ".oneagent/rules");
8643
- const destSkills = path5.join(root, ".oneagent/skills");
8644
- const destCommands = path5.join(root, ".oneagent/commands");
8670
+ const destRules = path5.join(root, ONEAGENT_DIR, "rules");
8671
+ const destSkills = path5.join(root, ONEAGENT_DIR, "skills");
8672
+ const destCommands = path5.join(root, ONEAGENT_DIR, "commands");
8645
8673
  for (const def of AGENT_DEFINITIONS) {
8646
8674
  if (def.rulesDir)
8647
8675
  await migrateAndRemoveDir(path5.join(root, def.rulesDir), destRules, root);
8648
8676
  }
8677
+ for (const def of AGENT_DEFINITIONS) {
8678
+ if (def.skillsDir)
8679
+ await migrateAndRemoveDir(path5.join(root, def.skillsDir), destSkills, root);
8680
+ }
8649
8681
  await migrateAndRemoveDir(path5.join(root, ".agents/skills"), destSkills, root);
8650
8682
  for (const def of AGENT_DEFINITIONS) {
8651
8683
  if (def.commandsDir)
8652
8684
  await migrateAndRemoveDir(path5.join(root, def.commandsDir), destCommands, root);
8653
8685
  }
8654
8686
  }
8687
+ async function backupDirRecursive(srcDir, backupDir, prefix) {
8688
+ let entries;
8689
+ try {
8690
+ entries = await fs5.readdir(srcDir, { withFileTypes: true });
8691
+ } catch {
8692
+ return;
8693
+ }
8694
+ for (const entry of entries) {
8695
+ const srcPath = path5.join(srcDir, entry.name);
8696
+ const lstat = await fs5.lstat(srcPath);
8697
+ if (lstat.isSymbolicLink())
8698
+ continue;
8699
+ if (lstat.isDirectory()) {
8700
+ await backupDirRecursive(srcPath, backupDir, `${prefix}_${entry.name}`);
8701
+ } else if (lstat.isFile()) {
8702
+ await fs5.mkdir(backupDir, { recursive: true });
8703
+ await fs5.copyFile(srcPath, path5.join(backupDir, `${prefix}_${entry.name}`));
8704
+ }
8705
+ }
8706
+ }
8707
+ async function cleanupAgentDir(root, target) {
8708
+ const def = AGENT_DEFINITIONS.find((d2) => d2.target === target);
8709
+ const backupDir = path5.join(root, ONEAGENT_DIR, "backup");
8710
+ const agentDir = [def.rulesDir, def.skillsDir, def.commandsDir].filter(Boolean).map((d2) => d2.split("/")[0]).find((d2) => d2 !== ".github");
8711
+ if (agentDir) {
8712
+ const agentDirAbs = path5.join(root, agentDir);
8713
+ let stat;
8714
+ try {
8715
+ stat = await fs5.lstat(agentDirAbs);
8716
+ } catch {}
8717
+ if (stat && stat.isDirectory() && !stat.isSymbolicLink()) {
8718
+ await backupDirRecursive(agentDirAbs, backupDir, agentDir);
8719
+ await fs5.rm(agentDirAbs, { recursive: true, force: true });
8720
+ }
8721
+ }
8722
+ if (target === "opencode") {
8723
+ const opPath = path5.join(root, "opencode.json");
8724
+ try {
8725
+ const content = await fs5.readFile(opPath, "utf-8");
8726
+ await fs5.mkdir(backupDir, { recursive: true });
8727
+ await fs5.writeFile(path5.join(backupDir, "opencode.json"), content);
8728
+ } catch {}
8729
+ try {
8730
+ await fs5.unlink(opPath);
8731
+ } catch {}
8732
+ }
8733
+ }
8655
8734
  async function createAllSymlinks(entries) {
8656
- for (const e2 of entries) {
8735
+ const deduped = new Map;
8736
+ for (const e2 of entries)
8737
+ deduped.set(e2.symlinkPath, e2);
8738
+ for (const e2 of deduped.values()) {
8657
8739
  await createSymlink(e2.symlinkPath, e2.target);
8658
8740
  }
8659
8741
  }
@@ -8722,7 +8804,7 @@ async function readOpencode(root) {
8722
8804
  function buildOpencodeConfig(existing) {
8723
8805
  return {
8724
8806
  ...existing,
8725
- instructions: ".oneagent/instructions.md"
8807
+ instructions: `${ONEAGENT_DIR}/instructions.md`
8726
8808
  };
8727
8809
  }
8728
8810
  async function addOpenCodePlugin(root, id) {
@@ -8846,7 +8928,7 @@ async function checkOpencodeStatus(root, _rules) {
8846
8928
  const existing = await readOpencode(root);
8847
8929
  if (!existing)
8848
8930
  return { exists: false, valid: false };
8849
- return { exists: true, valid: existing["instructions"] === ".oneagent/instructions.md" };
8931
+ return { exists: true, valid: existing["instructions"] === `${ONEAGENT_DIR}/instructions.md` };
8850
8932
  }
8851
8933
  async function checkCopilotPrompt(root, skill) {
8852
8934
  const filePath = copilotPromptFilePath(root, skill.name);
@@ -8895,9 +8977,11 @@ function parseTemplateYaml(yamlText, fallbackName = "custom") {
8895
8977
  const name = nameMatch?.[1]?.trim() ?? fallbackName;
8896
8978
  const descMatch = yamlText.match(/^description:\s*(.+)$/m);
8897
8979
  const description = descMatch?.[1]?.trim() ?? "";
8980
+ const extendsMatch = yamlText.match(/^extends:\s*(.+)$/m);
8981
+ const extendsValue = extendsMatch?.[1]?.trim();
8898
8982
  const skills = parseSkillsFromYaml(yamlText);
8899
8983
  const plugins = parsePluginsFromYaml(yamlText);
8900
- return { name, description, skills, plugins };
8984
+ return { name, description, skills, plugins, ...extendsValue ? { extends: extendsValue } : {} };
8901
8985
  }
8902
8986
  function parseSkillsFromYaml(yamlText) {
8903
8987
  const skills = [];
@@ -8934,8 +9018,31 @@ function parsePluginsFromYaml(yamlText) {
8934
9018
  }
8935
9019
  return plugins;
8936
9020
  }
9021
+ async function resolveExtends(child, resolveBuiltin) {
9022
+ if (!child.extends)
9023
+ return child;
9024
+ let parent;
9025
+ if (child.extends.startsWith("https://")) {
9026
+ parent = await fetchTemplateFromGitHub(child.extends);
9027
+ } else if (resolveBuiltin) {
9028
+ const resolved = await resolveBuiltin(child.extends);
9029
+ if (!resolved)
9030
+ throw new Error(`Unknown builtin template: "${child.extends}"`);
9031
+ parent = resolved;
9032
+ } else {
9033
+ throw new Error(`Cannot resolve extends: "${child.extends}"`);
9034
+ }
9035
+ return {
9036
+ name: child.name,
9037
+ description: child.description,
9038
+ instructions: child.instructions,
9039
+ skills: [...parent.skills, ...child.skills],
9040
+ plugins: [...parent.plugins, ...child.plugins],
9041
+ rules: [...parent.rules, ...child.rules]
9042
+ };
9043
+ }
8937
9044
  async function applyTemplateFiles(root, template) {
8938
- const oneagentDir = path9.join(root, ".oneagent");
9045
+ const oneagentDir = path9.join(root, ONEAGENT_DIR);
8939
9046
  await fs10.mkdir(path9.join(oneagentDir, "rules"), { recursive: true });
8940
9047
  await fs10.mkdir(path9.join(oneagentDir, "skills"), { recursive: true });
8941
9048
  await fs10.writeFile(path9.join(oneagentDir, "instructions.md"), template.instructions);
@@ -8944,19 +9051,26 @@ async function applyTemplateFiles(root, template) {
8944
9051
  }
8945
9052
  }
8946
9053
  async function installTemplateSkills(root, template) {
8947
- const results = await Promise.all(template.skills.map(async (entry) => {
9054
+ const installed = [];
9055
+ const failed = [];
9056
+ for (const entry of template.skills) {
8948
9057
  try {
8949
9058
  await execFileAsync("npx", ["skills", "add", entry.repo, "--skill", entry.skill, "--agent", "universal", "--yes"], { cwd: root });
8950
- return { entry, ok: true };
9059
+ installed.push(entry);
8951
9060
  } catch (err) {
8952
9061
  const reason = err instanceof Error ? err.message : String(err);
8953
- return { entry, ok: false, reason };
9062
+ failed.push({ entry, reason });
8954
9063
  }
8955
- }));
8956
- return {
8957
- installed: results.filter((r) => r.ok).map((r) => r.entry),
8958
- failed: results.filter((r) => !r.ok).map((r) => ({ entry: r.entry, reason: r.reason }))
8959
- };
9064
+ }
9065
+ return { installed, failed };
9066
+ }
9067
+ async function installBuiltinSkill(root) {
9068
+ try {
9069
+ await execFileAsync("npx", ["skills", "add", BUILTIN_SKILL_REPO, "--skill", BUILTIN_SKILL_NAME, "--agent", "universal", "--yes"], { cwd: root });
9070
+ return true;
9071
+ } catch {
9072
+ return false;
9073
+ }
8960
9074
  }
8961
9075
  async function installTemplatePlugins(root, template, activeTargets2) {
8962
9076
  const installed = [];
@@ -8993,14 +9107,31 @@ async function installTemplatePlugins(root, template, activeTargets2) {
8993
9107
  return { installed, manual, failed };
8994
9108
  }
8995
9109
  async function fetchTemplateFromGitHub(url) {
8996
- const rawBase = githubUrlToRawBase(url);
9110
+ const { owner, repo, branch, subdir } = parseGitHubUrl(url);
9111
+ const branchExplicit = url.includes("/tree/");
9112
+ const resolvedBranch = branchExplicit ? branch : await fetchDefaultBranch(owner, repo);
9113
+ const rawBase = `https://raw.githubusercontent.com/${owner}/${repo}/${resolvedBranch}${subdir ? `/${subdir}` : ""}`;
8997
9114
  const [yamlText, instructions] = await Promise.all([
8998
9115
  fetchText(`${rawBase}/template.yml`),
8999
9116
  fetchText(`${rawBase}/instructions.md`)
9000
9117
  ]);
9001
- const { name, description, skills, plugins } = parseTemplateYaml(yamlText);
9118
+ const parsed = parseTemplateYaml(yamlText);
9002
9119
  const rules = await fetchGitHubRules(url);
9003
- return { name, description, skills, plugins, instructions, rules };
9120
+ const base = { ...parsed, instructions, rules };
9121
+ return resolveExtends(base);
9122
+ }
9123
+ async function fetchDefaultBranch(owner, repo) {
9124
+ try {
9125
+ const response = await fetch(`https://api.github.com/repos/${owner}/${repo}`, {
9126
+ headers: { Accept: "application/vnd.github.v3+json" }
9127
+ });
9128
+ if (!response.ok)
9129
+ return "main";
9130
+ const data = await response.json();
9131
+ return data.default_branch ?? "main";
9132
+ } catch {
9133
+ return "main";
9134
+ }
9004
9135
  }
9005
9136
  async function fetchText(url) {
9006
9137
  const response = await fetch(url);
@@ -9017,11 +9148,6 @@ function parseGitHubUrl(url) {
9017
9148
  const [, owner, repo, branch = "main", subdir = ""] = match;
9018
9149
  return { owner, repo, branch, subdir };
9019
9150
  }
9020
- function githubUrlToRawBase(url) {
9021
- const { owner, repo, branch, subdir } = parseGitHubUrl(url);
9022
- const base = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}`;
9023
- return subdir ? `${base}/${subdir}` : base;
9024
- }
9025
9151
  async function fetchGitHubRules(repoUrl) {
9026
9152
  const { owner, repo, branch, subdir } = parseGitHubUrl(repoUrl);
9027
9153
  const rulesPath = subdir ? `${subdir}/rules` : "rules";
@@ -9043,7 +9169,7 @@ async function fetchGitHubRules(repoUrl) {
9043
9169
  return [];
9044
9170
  }
9045
9171
  }
9046
- var execFileAsync;
9172
+ var execFileAsync, BUILTIN_SKILL_REPO = "https://github.com/moskalakamil/oneagent", BUILTIN_SKILL_NAME = "oneagent";
9047
9173
  var init_apply_template = __esm(() => {
9048
9174
  init_opencode();
9049
9175
  execFileAsync = promisify(execFile);
@@ -9075,7 +9201,7 @@ async function loadTemplate(name) {
9075
9201
  fs11.readFile(path10.join(templateDir, "template.yml"), "utf-8"),
9076
9202
  fs11.readFile(path10.join(templateDir, "instructions.md"), "utf-8")
9077
9203
  ]);
9078
- const { description, skills: skills2, plugins } = parseTemplateYaml(yamlText, name);
9204
+ const parsed = parseTemplateYaml(yamlText, name);
9079
9205
  const rulesDir = path10.join(templateDir, "rules");
9080
9206
  let rules2 = [];
9081
9207
  try {
@@ -9085,7 +9211,8 @@ async function loadTemplate(name) {
9085
9211
  content: await fs11.readFile(path10.join(rulesDir, f), "utf-8")
9086
9212
  })));
9087
9213
  } catch {}
9088
- return { name, description, skills: skills2, plugins, instructions, rules: rules2 };
9214
+ const base = { ...parsed, instructions, rules: rules2 };
9215
+ return resolveExtends(base, (n) => resolveBuiltinTemplate(n));
9089
9216
  }
9090
9217
  async function resolveBuiltinTemplate(name) {
9091
9218
  if (!TEMPLATE_NAMES.includes(name))
@@ -9105,98 +9232,6 @@ var init_src2 = __esm(() => {
9105
9232
  ];
9106
9233
  });
9107
9234
 
9108
- // src/assets/about-oneagent.ts
9109
- var ABOUT_ONEAGENT_CONTENT = `---
9110
- name: about-oneagent
9111
- description: Explains how AI configuration is managed in this project using oneagent. Use when working with the .oneagent/ directory, adding or modifying rules or skills, or when files like CLAUDE.md, AGENTS.md, .cursor/rules/, or .github/instructions/ are mentioned.
9112
- applyTo: "**"
9113
- globs: "**"
9114
- alwaysApply: true
9115
- ---
9116
- # Project AI Configuration — oneagent
9117
-
9118
- This project uses [oneagent](https://github.com/moskalakamil/oneagent) to manage AI agent configuration.
9119
- Rules, skills, and instructions are maintained in a single source of truth and automatically distributed to all configured AI agents (Claude, Cursor, Windsurf, OpenCode, Copilot).
9120
-
9121
- ## Directory Structure
9122
-
9123
- \`\`\`
9124
- .oneagent/
9125
- instructions.md # Main project instructions (source for CLAUDE.md, AGENTS.md, etc.)
9126
- rules/ # Rules distributed to all configured agents
9127
- skills/ # Skills distributed as slash commands / agent tools
9128
- \`\`\`
9129
-
9130
- > Do NOT edit files in \`.claude/\`, \`.cursor/\`, \`.windsurf/\`, \`.opencode/\`, \`.github/instructions/\` directly.
9131
- > These are auto-generated or symlinked from \`.oneagent/\` and will be overwritten on next \`oneagent generate\`.
9132
-
9133
- ## Adding a Rule
9134
-
9135
- Create a \`.md\` file in \`.oneagent/rules/\`. Each agent reads frontmatter differently — use all relevant fields:
9136
-
9137
- **Rule that applies to all files (recommended for general guidelines):**
9138
-
9139
- \`\`\`md
9140
- ---
9141
- name: rule-name
9142
- description: What this rule does and when to use it (used by Cursor and Copilot).
9143
- applyTo: "**"
9144
- alwaysApply: true
9145
- ---
9146
- # Rule Title
9147
-
9148
- Rule content here.
9149
- \`\`\`
9150
-
9151
- **Rule scoped to specific files:**
9152
-
9153
- \`\`\`md
9154
- ---
9155
- name: rule-name
9156
- description: What this rule does (used by Cursor and Copilot to decide when to apply it).
9157
- applyTo: "**/*.ts"
9158
- globs: "**/*.ts"
9159
- ---
9160
- # Rule Title
9161
-
9162
- Rule content here.
9163
- \`\`\`
9164
-
9165
- **Frontmatter fields by agent:**
9166
-
9167
- | Field | Agent | Purpose |
9168
- |-------|-------|---------|
9169
- | \`applyTo\` | Claude Code, Copilot | Glob pattern scoping the rule to matching files |
9170
- | \`globs\` | Cursor | Glob pattern for file-scoped rules ("Apply to Specific Files" mode) |
9171
- | \`alwaysApply: true\` | Cursor | Apply to every session regardless of files ("Always Apply" mode) |
9172
- | \`description\` | Cursor, Copilot | Used by the agent to decide when/whether to apply the rule |
9173
- | \`name\` | All | Rule identifier |
9174
-
9175
- > Windsurf and OpenCode ignore frontmatter — the rule body is used as-is.
9176
-
9177
- Then run \`oneagent generate\` to distribute the rule to all configured agents.
9178
-
9179
- ## Adding a Skill
9180
-
9181
- Create a \`.md\` file in \`.oneagent/skills/\`:
9182
-
9183
- \`\`\`md
9184
- ---
9185
- mode: agent # ask | edit | agent
9186
- description: Short description shown in agent menus
9187
- ---
9188
- Skill instructions here.
9189
- \`\`\`
9190
-
9191
- Then run \`oneagent generate\` to distribute the skill.
9192
-
9193
- ## Commands
9194
-
9195
- - \`oneagent generate\` — sync all rules and skills to agent-specific directories
9196
- - \`oneagent status\` — verify that all symlinks and generated files are up to date
9197
- - \`oneagent init\` — initialize oneagent in a project (run once)
9198
- `;
9199
-
9200
9235
  // src/commands/init.ts
9201
9236
  var exports_init = {};
9202
9237
  __export(exports_init, {
@@ -9213,20 +9248,12 @@ async function chooseContent(detected) {
9213
9248
  return "";
9214
9249
  if (detected.length === 1) {
9215
9250
  const file = detected[0];
9216
- const result2 = await Re({
9217
- message: `Found ${file.relativePath} (${timeAgo(file.modifiedAt)}). Import its content into .oneagent/instructions.md?`
9218
- });
9219
- if (Ct(result2))
9220
- cancelAndExit();
9221
- return result2 ? file.content : "";
9251
+ R2.info(`Found ${file.relativePath} (${timeAgo(file.modifiedAt)}) importing into ${ONEAGENT_DIR}/instructions.md`);
9252
+ return file.content;
9222
9253
  }
9223
9254
  if (filesHaveSameContent(detected)) {
9224
- const result2 = await Re({
9225
- message: `Found ${detected.length} files with identical content. Import?`
9226
- });
9227
- if (Ct(result2))
9228
- cancelAndExit();
9229
- return result2 ? detected[0].content : "";
9255
+ R2.info(`Found ${detected.length} files with identical content — importing into ${ONEAGENT_DIR}/instructions.md`);
9256
+ return detected[0].content;
9230
9257
  }
9231
9258
  Ve(detected.map((f) => ` • ${f.relativePath} ${timeAgo(f.modifiedAt)}`).join(`
9232
9259
  `), "Multiple files with different content found");
@@ -9282,13 +9309,19 @@ async function pickTargets(initialValues) {
9282
9309
  async function backupFiles(root, files) {
9283
9310
  if (files.length === 0)
9284
9311
  return;
9285
- const backupDir = path11.join(root, ".oneagent/backup");
9312
+ const backupDir = path11.join(root, ONEAGENT_DIR, "backup");
9286
9313
  await fs12.mkdir(backupDir, { recursive: true });
9287
9314
  for (const file of files) {
9288
9315
  const safeName = file.relativePath.replace(/\//g, "_");
9289
9316
  await fs12.writeFile(path11.join(backupDir, safeName), file.content);
9290
9317
  }
9291
9318
  }
9319
+ async function cleanupUnselectedAgentDirs(root, presentTargets, selectedTargets) {
9320
+ const unselected = presentTargets.filter((t) => !selectedTargets.includes(t));
9321
+ for (const target of unselected) {
9322
+ await cleanupAgentDir(root, target);
9323
+ }
9324
+ }
9292
9325
  async function pickTemplateInteractively() {
9293
9326
  const result = await Je({
9294
9327
  message: "Which template would you like to use?",
@@ -9339,6 +9372,12 @@ var init_init = __esm(() => {
9339
9372
  template: {
9340
9373
  type: "string",
9341
9374
  description: `Template to use: builtin name (${BUILTIN_TEMPLATE_NAMES.join("/")}) or GitHub URL`
9375
+ },
9376
+ yes: {
9377
+ type: "boolean",
9378
+ alias: "y",
9379
+ description: "Skip prompts: auto-import detected files and select detected agents",
9380
+ default: false
9342
9381
  }
9343
9382
  },
9344
9383
  async run({ args }) {
@@ -9367,19 +9406,26 @@ var init_init = __esm(() => {
9367
9406
  Ve(message, "Error");
9368
9407
  process.exit(1);
9369
9408
  }
9409
+ } else if (args.yes) {
9410
+ if (detected.length > 0) {
9411
+ const newest = detected.toSorted((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime())[0];
9412
+ importedContent = newest.content;
9413
+ R2.info(`Auto-importing content from ${newest.relativePath}`);
9414
+ }
9370
9415
  } else {
9371
9416
  importedContent = await chooseContent(detected);
9372
9417
  }
9373
9418
  const presentTargets = await detectPresentTargets(root);
9374
- const selectedTargets = await pickTargets(presentTargets);
9419
+ const selectedTargets = args.yes ? presentTargets.length > 0 ? presentTargets : ALL_AGENT_TARGETS.slice(0, 1) : await pickTargets(presentTargets);
9375
9420
  const s = bt2();
9376
- s.start("Setting up .oneagent/ directory...");
9377
- await fs12.mkdir(path11.join(root, ".oneagent/rules"), { recursive: true });
9378
- await fs12.mkdir(path11.join(root, ".oneagent/skills"), { recursive: true });
9379
- await fs12.mkdir(path11.join(root, ".oneagent/commands"), { recursive: true });
9421
+ s.start(`Setting up ${ONEAGENT_DIR}/ directory...`);
9422
+ await fs12.mkdir(path11.join(root, ONEAGENT_DIR, "rules"), { recursive: true });
9423
+ await fs12.mkdir(path11.join(root, ONEAGENT_DIR, "skills"), { recursive: true });
9424
+ await fs12.mkdir(path11.join(root, ONEAGENT_DIR, "commands"), { recursive: true });
9380
9425
  await backupFiles(root, detected);
9381
9426
  await removeDeprecatedFiles(root);
9382
9427
  await migrateRuleAndSkillFiles(root);
9428
+ await cleanupUnselectedAgentDirs(root, presentTargets, selectedTargets);
9383
9429
  const config2 = { version: 1, targets: makeTargets(...selectedTargets) };
9384
9430
  await writeConfig(root, config2);
9385
9431
  if (template) {
@@ -9389,30 +9435,37 @@ var init_init = __esm(() => {
9389
9435
 
9390
9436
  Add your AI instructions here.
9391
9437
  `;
9392
- await fs12.writeFile(path11.join(root, ".oneagent/instructions.md"), instructionsContent);
9438
+ await fs12.writeFile(path11.join(root, ONEAGENT_DIR, "instructions.md"), instructionsContent);
9393
9439
  }
9394
- await fs12.writeFile(path11.join(root, ".oneagent/rules/about-oneagent.md"), ABOUT_ONEAGENT_CONTENT, "utf-8");
9395
9440
  s.stop("Directory structure created.");
9396
- const commandFiles = await fs12.readdir(path11.join(root, ".oneagent/commands")).catch(() => []);
9441
+ const commandFiles = await fs12.readdir(path11.join(root, ONEAGENT_DIR, "commands")).catch(() => []);
9397
9442
  if (commandFiles.some((f) => f.endsWith(".md"))) {
9398
- R2.warn("Commands detected in .oneagent/commands/. Consider migrating to .oneagent/skills/ — skills are distributed to more agents and support richer features.");
9443
+ R2.warn(`Commands detected in ${ONEAGENT_DIR}/commands/. Consider migrating to ${ONEAGENT_DIR}/skills/ — skills are distributed to more agents and support richer features.`);
9399
9444
  }
9400
9445
  if (commandFiles.some((f) => f.endsWith(".md"))) {
9401
9446
  const commandsSupported = new Set(AGENT_DEFINITIONS.filter((d2) => d2.commandsDir).map((d2) => d2.target));
9402
9447
  const unsupported = selectedTargets.filter((t) => !commandsSupported.has(t));
9403
9448
  if (unsupported.length > 0) {
9404
9449
  const names = unsupported.map((t) => AGENT_DEFINITIONS.find((d2) => d2.target === t).displayName).join(", ");
9405
- R2.warn(`Commands in .oneagent/commands/ will not be available in: ${names} — these agents do not support custom slash commands.`);
9450
+ R2.warn(`Commands in ${ONEAGENT_DIR}/commands/ will not be available in: ${names} — these agents do not support custom slash commands.`);
9406
9451
  }
9407
9452
  }
9408
9453
  const s2 = bt2();
9409
9454
  s2.start("Generating symlinks and agent files...");
9410
9455
  await generate(root, config2);
9411
9456
  s2.stop("Done.");
9457
+ const sSkill = bt2();
9458
+ sSkill.start("Installing oneagent skill...");
9459
+ const builtinInstalled = await installBuiltinSkill(root);
9460
+ if (builtinInstalled) {
9461
+ sSkill.stop("Installed oneagent skill.");
9462
+ } else {
9463
+ sSkill.stop("Could not install oneagent skill (skipped).");
9464
+ }
9412
9465
  let skillResult = { installed: [], failed: [] };
9413
9466
  if (template && template.skills.length > 0) {
9414
9467
  const s3 = bt2();
9415
- s3.start("Installing skills...");
9468
+ s3.start("Installing template skills...");
9416
9469
  skillResult = await installTemplateSkills(root, template);
9417
9470
  s3.stop(`Installed ${skillResult.installed.length} skill(s).`);
9418
9471
  for (const f of skillResult.failed) {
@@ -9435,10 +9488,10 @@ Add your AI instructions here.
9435
9488
  ...skillResult.installed.length > 0 ? [`Installed ${skillResult.installed.length} skill(s): ${skillResult.installed.map((s3) => s3.skill).join(", ")}`] : [],
9436
9489
  ...template.rules.length > 0 ? [`Added ${template.rules.length} rule(s) from template`] : [],
9437
9490
  ...pluginResult.installed.length > 0 ? [`Installed ${pluginResult.installed.length} plugin(s): ${pluginResult.installed.map((p) => p.id).join(", ")}`] : []
9438
- ] : ["Created .oneagent/instructions.md"],
9439
- "Created .oneagent/rules/about-oneagent.md",
9491
+ ] : [`Created ${ONEAGENT_DIR}/instructions.md`],
9492
+ ...builtinInstalled ? [`Installed oneagent skill`] : [],
9440
9493
  ...selectedTargets.map((t) => `Configured: ${t}`),
9441
- ...detected.length > 0 ? [`Backed up ${detected.length} file(s) to .oneagent/backup/`] : []
9494
+ ...detected.length > 0 ? [`Backed up ${detected.length} file(s) to ${ONEAGENT_DIR}/backup/`] : []
9442
9495
  ];
9443
9496
  Ve(lines.map((l) => ` • ${l}`).join(`
9444
9497
  `), "Setup complete");
@@ -9471,18 +9524,25 @@ var init_generate2 = __esm(() => {
9471
9524
  name: "generate",
9472
9525
  description: "Generate symlinks and agent-specific files"
9473
9526
  },
9474
- async run() {
9527
+ args: {
9528
+ yes: {
9529
+ type: "boolean",
9530
+ alias: "y",
9531
+ description: "Skip confirmation prompts and auto-migrate colliding files"
9532
+ }
9533
+ },
9534
+ async run({ args }) {
9475
9535
  const root = process.cwd();
9476
9536
  let config2;
9477
9537
  try {
9478
9538
  config2 = await readConfig(root);
9479
9539
  } catch {
9480
- console.error("Error: No .oneagent/config.yml found. Run `oneagent init` first.");
9540
+ console.error(`Error: No ${ONEAGENT_DIR}/config.yml found. Run \`oneagent init\` first.`);
9481
9541
  process.exit(1);
9482
9542
  }
9483
9543
  const { mainFiles, ruleSkillFiles } = await detectGenerateCollisions(root, config2);
9484
9544
  if (mainFiles.length > 0) {
9485
- const backupDir = path12.join(root, ".oneagent/backup");
9545
+ const backupDir = path12.join(root, ONEAGENT_DIR, "backup");
9486
9546
  await fs13.mkdir(backupDir, { recursive: true });
9487
9547
  for (const file of mainFiles) {
9488
9548
  const safeName = file.relativePath.replace(/\//g, "_");
@@ -9490,16 +9550,20 @@ var init_generate2 = __esm(() => {
9490
9550
  }
9491
9551
  }
9492
9552
  if (ruleSkillFiles.length > 0) {
9493
- Ve(ruleSkillFiles.map((f) => ` • ${f.relativePath}`).join(`
9494
- `), "These rule/skill files are not dotai symlinks");
9495
- const proceed = await Re({
9496
- message: "Move them to .oneagent/ and replace with symlinks?"
9497
- });
9498
- if (Ct(proceed) || !proceed) {
9499
- Le("Aborted.");
9500
- process.exit(0);
9553
+ if (args.yes) {
9554
+ await migrateRuleAndSkillFiles(root);
9555
+ } else {
9556
+ Ve(ruleSkillFiles.map((f) => ` • ${f.relativePath}`).join(`
9557
+ `), "These rule/skill files are not oneagent symlinks");
9558
+ const proceed = await Re({
9559
+ message: `Move them to ${ONEAGENT_DIR}/ and replace with symlinks?`
9560
+ });
9561
+ if (Ct(proceed) || !proceed) {
9562
+ Le("Aborted.");
9563
+ process.exit(0);
9564
+ }
9565
+ await migrateRuleAndSkillFiles(root);
9501
9566
  }
9502
- await migrateRuleAndSkillFiles(root);
9503
9567
  }
9504
9568
  const s = bt2();
9505
9569
  s.start("Generating...");
@@ -9535,7 +9599,7 @@ var init_status2 = __esm(() => {
9535
9599
  try {
9536
9600
  config2 = await readConfig(root);
9537
9601
  } catch {
9538
- console.error("Error: No .oneagent/config.yml found. Run `oneagent init` first.");
9602
+ console.error(`Error: No ${ONEAGENT_DIR}/config.yml found. Run \`oneagent init\` first.`);
9539
9603
  process.exit(1);
9540
9604
  }
9541
9605
  const status2 = await checkStatus(root, config2);
@@ -9568,6 +9632,233 @@ OpenCode:
9568
9632
  });
9569
9633
  });
9570
9634
 
9635
+ // src/commands/targets.ts
9636
+ var exports_targets = {};
9637
+ __export(exports_targets, {
9638
+ default: () => targets_default
9639
+ });
9640
+ import path13 from "path";
9641
+ import fs14 from "fs/promises";
9642
+ function cancelAndExit2() {
9643
+ Le("Cancelled.");
9644
+ process.exit(0);
9645
+ }
9646
+ async function detectPresentTargets2(root) {
9647
+ const results = await Promise.all(AGENT_DEFINITIONS.map(async (def) => {
9648
+ for (const indicator of def.detectIndicators) {
9649
+ try {
9650
+ await fs14.access(path13.join(root, indicator));
9651
+ return def.target;
9652
+ } catch {}
9653
+ }
9654
+ return null;
9655
+ }));
9656
+ return results.filter((t) => t !== null);
9657
+ }
9658
+ var targets_default;
9659
+ var init_targets = __esm(() => {
9660
+ init_dist();
9661
+ init_dist3();
9662
+ init_src();
9663
+ targets_default = defineCommand2({
9664
+ meta: {
9665
+ name: "targets",
9666
+ description: "Add or remove AI agent targets"
9667
+ },
9668
+ async run() {
9669
+ const root = process.cwd();
9670
+ let config2;
9671
+ try {
9672
+ config2 = await readConfig(root);
9673
+ } catch {
9674
+ console.error(`Error: No ${ONEAGENT_DIR}/config.yml found. Run \`oneagent init\` first.`);
9675
+ process.exit(1);
9676
+ }
9677
+ const current = activeTargets(config2);
9678
+ const presentTargets = await detectPresentTargets2(root);
9679
+ const initialValues = [...new Set([...current, ...presentTargets])];
9680
+ Ve(current.map((t) => ` • ${AGENT_DEFINITIONS.find((d2) => d2.target === t).displayName}`).join(`
9681
+ `), "Currently configured targets");
9682
+ const result = await je({
9683
+ message: `Which AI agents do you want to support?
9684
+ \x1B[90m · Space to toggle · Enter to confirm\x1B[39m`,
9685
+ options: AGENT_DEFINITIONS.map((d2) => ({ value: d2.target, label: d2.displayName, hint: d2.hint })),
9686
+ initialValues,
9687
+ required: true
9688
+ });
9689
+ if (Ct(result))
9690
+ cancelAndExit2();
9691
+ const selected = result;
9692
+ const removed = current.filter((t) => !selected.includes(t));
9693
+ const added = selected.filter((t) => !current.includes(t));
9694
+ if (removed.length === 0 && added.length === 0) {
9695
+ Le("No changes.");
9696
+ return;
9697
+ }
9698
+ const s = bt2();
9699
+ s.start("Updating targets...");
9700
+ for (const target of removed) {
9701
+ await cleanupAgentDir(root, target);
9702
+ }
9703
+ config2.targets = makeTargets(...selected);
9704
+ await writeConfig(root, config2);
9705
+ await generate(root, config2);
9706
+ s.stop("Done.");
9707
+ const lines = [
9708
+ ...added.length > 0 ? [`Added: ${added.map((t) => AGENT_DEFINITIONS.find((d2) => d2.target === t).displayName).join(", ")}`] : [],
9709
+ ...removed.length > 0 ? [`Removed: ${removed.map((t) => AGENT_DEFINITIONS.find((d2) => d2.target === t).displayName).join(", ")}`] : []
9710
+ ];
9711
+ Ve(lines.map((l) => ` • ${l}`).join(`
9712
+ `), "Targets updated");
9713
+ if (removed.length > 0) {
9714
+ R2.info(`Removed agent files backed up to ${ONEAGENT_DIR}/backup/`);
9715
+ }
9716
+ Le("Run `oneagent status` to verify your setup.");
9717
+ }
9718
+ });
9719
+ });
9720
+
9721
+ // src/commands/add.ts
9722
+ var exports_add = {};
9723
+ __export(exports_add, {
9724
+ default: () => add_default
9725
+ });
9726
+ var add_default;
9727
+ var init_add = __esm(() => {
9728
+ init_dist();
9729
+ init_dist3();
9730
+ init_src();
9731
+ add_default = defineCommand2({
9732
+ meta: {
9733
+ name: "add",
9734
+ description: "Add an AI agent target"
9735
+ },
9736
+ args: {
9737
+ target: {
9738
+ type: "positional",
9739
+ description: "Agent to add (claude, cursor, windsurf, opencode, copilot)",
9740
+ required: false
9741
+ }
9742
+ },
9743
+ async run({ args }) {
9744
+ const root = process.cwd();
9745
+ let config2;
9746
+ try {
9747
+ config2 = await readConfig(root);
9748
+ } catch {
9749
+ console.error(`Error: No ${ONEAGENT_DIR}/config.yml found. Run \`oneagent init\` first.`);
9750
+ process.exit(1);
9751
+ }
9752
+ const current = activeTargets(config2);
9753
+ const available = ALL_AGENT_TARGETS.filter((t) => !current.includes(t));
9754
+ if (available.length === 0) {
9755
+ R2.info("All agents are already configured.");
9756
+ return;
9757
+ }
9758
+ let target;
9759
+ if (args.target) {
9760
+ if (!ALL_AGENT_TARGETS.includes(args.target)) {
9761
+ console.error(`Unknown target "${args.target}". Available: ${ALL_AGENT_TARGETS.join(", ")}`);
9762
+ process.exit(1);
9763
+ }
9764
+ target = args.target;
9765
+ if (current.includes(target)) {
9766
+ R2.info(`${AGENT_DEFINITIONS.find((d2) => d2.target === target).displayName} is already configured.`);
9767
+ return;
9768
+ }
9769
+ } else {
9770
+ const result = await Je({
9771
+ message: "Which agent do you want to add?",
9772
+ options: available.map((t) => {
9773
+ const def = AGENT_DEFINITIONS.find((d2) => d2.target === t);
9774
+ return { value: t, label: def.displayName, hint: def.hint };
9775
+ })
9776
+ });
9777
+ if (Ct(result)) {
9778
+ Le("Cancelled.");
9779
+ process.exit(0);
9780
+ }
9781
+ target = result;
9782
+ }
9783
+ config2.targets[target] = true;
9784
+ await writeConfig(root, config2);
9785
+ await generate(root, config2);
9786
+ R2.success(`Added ${AGENT_DEFINITIONS.find((d2) => d2.target === target).displayName}`);
9787
+ }
9788
+ });
9789
+ });
9790
+
9791
+ // src/commands/remove.ts
9792
+ var exports_remove = {};
9793
+ __export(exports_remove, {
9794
+ default: () => remove_default
9795
+ });
9796
+ var remove_default;
9797
+ var init_remove = __esm(() => {
9798
+ init_dist();
9799
+ init_dist3();
9800
+ init_src();
9801
+ remove_default = defineCommand2({
9802
+ meta: {
9803
+ name: "remove",
9804
+ description: "Remove an AI agent target"
9805
+ },
9806
+ args: {
9807
+ target: {
9808
+ type: "positional",
9809
+ description: "Agent to remove (claude, cursor, windsurf, opencode, copilot)",
9810
+ required: false
9811
+ }
9812
+ },
9813
+ async run({ args }) {
9814
+ const root = process.cwd();
9815
+ let config2;
9816
+ try {
9817
+ config2 = await readConfig(root);
9818
+ } catch {
9819
+ console.error(`Error: No ${ONEAGENT_DIR}/config.yml found. Run \`oneagent init\` first.`);
9820
+ process.exit(1);
9821
+ }
9822
+ const current = activeTargets(config2);
9823
+ if (current.length === 1) {
9824
+ console.error("Cannot remove the last target. At least one agent must be configured.");
9825
+ process.exit(1);
9826
+ }
9827
+ let target;
9828
+ if (args.target) {
9829
+ if (!ALL_AGENT_TARGETS.includes(args.target)) {
9830
+ console.error(`Unknown target "${args.target}". Available: ${ALL_AGENT_TARGETS.join(", ")}`);
9831
+ process.exit(1);
9832
+ }
9833
+ target = args.target;
9834
+ if (!current.includes(target)) {
9835
+ R2.info(`${AGENT_DEFINITIONS.find((d2) => d2.target === target).displayName} is not configured.`);
9836
+ return;
9837
+ }
9838
+ } else {
9839
+ const result = await Je({
9840
+ message: "Which agent do you want to remove?",
9841
+ options: current.map((t) => {
9842
+ const def = AGENT_DEFINITIONS.find((d2) => d2.target === t);
9843
+ return { value: t, label: def.displayName, hint: def.hint };
9844
+ })
9845
+ });
9846
+ if (Ct(result)) {
9847
+ Le("Cancelled.");
9848
+ process.exit(0);
9849
+ }
9850
+ target = result;
9851
+ }
9852
+ await cleanupAgentDir(root, target);
9853
+ config2.targets[target] = false;
9854
+ await writeConfig(root, config2);
9855
+ await generate(root, config2);
9856
+ R2.success(`Removed ${AGENT_DEFINITIONS.find((d2) => d2.target === target).displayName}`);
9857
+ R2.info(`Files backed up to ${ONEAGENT_DIR}/backup/`);
9858
+ }
9859
+ });
9860
+ });
9861
+
9571
9862
  // ../../node_modules/.bun/citty@0.2.1/node_modules/citty/dist/index.mjs
9572
9863
  init_scule();
9573
9864
  import { parseArgs as parseArgs$1 } from "node:util";
@@ -9922,7 +10213,10 @@ var main = defineCommand({
9922
10213
  subCommands: {
9923
10214
  init: () => Promise.resolve().then(() => (init_init(), exports_init)).then((r) => r.default),
9924
10215
  generate: () => Promise.resolve().then(() => (init_generate2(), exports_generate)).then((r) => r.default),
9925
- status: () => Promise.resolve().then(() => (init_status2(), exports_status)).then((r) => r.default)
10216
+ status: () => Promise.resolve().then(() => (init_status2(), exports_status)).then((r) => r.default),
10217
+ targets: () => Promise.resolve().then(() => (init_targets(), exports_targets)).then((r) => r.default),
10218
+ add: () => Promise.resolve().then(() => (init_add(), exports_add)).then((r) => r.default),
10219
+ remove: () => Promise.resolve().then(() => (init_remove(), exports_remove)).then((r) => r.default)
9926
10220
  }
9927
10221
  });
9928
10222
  runMain(main);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oneagent",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "One source of truth for AI agent rules — distributed via symlinks to Claude, Cursor, Windsurf, Copilot, OpenCode",
6
6
  "license": "MIT",