@0dai-dev/cli 3.1.6 → 3.1.8

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/bin/0dai.js +125 -4
  2. package/package.json +1 -1
package/bin/0dai.js CHANGED
@@ -344,9 +344,16 @@ function writeFiles(target, files) {
344
344
  if (rel.endsWith("settings.json")) {
345
345
  finalContent = mergeSettingsJson(existing, content);
346
346
  merged++;
347
- } else if (rel === "AGENTS.md" && existing.includes("managed: false")) {
348
- unchanged++; // User owns this file, skip
349
- continue;
347
+ } else if (rel === "AGENTS.md") {
348
+ if (existing.includes("managed: false")) {
349
+ unchanged++; // User owns this file, skip
350
+ continue;
351
+ }
352
+ // Backup existing AGENTS.md before overwrite
353
+ const backupDir = path.join(target, "ai", ".backups");
354
+ fs.mkdirSync(backupDir, { recursive: true });
355
+ fs.writeFileSync(path.join(backupDir, "AGENTS.md.bak"), existing, "utf8");
356
+ updated++;
350
357
  } else {
351
358
  updated++;
352
359
  }
@@ -807,6 +814,50 @@ function cmdDoctor(target) {
807
814
  console.log(` ${mark.padEnd(22)} ${c.name}${hint}`);
808
815
  }
809
816
 
817
+ // --- agent CLIs check ---
818
+ const AGENT_CLIS = [
819
+ { name: "claude", pkg: "@anthropic-ai/claude-code", bin: "claude", install: "npm i -g @anthropic-ai/claude-code", altAuth: "Pro/Team subscription" },
820
+ { name: "codex", pkg: "@openai/codex", bin: "codex", install: "npm i -g @openai/codex", altAuth: "ChatGPT Pro subscription" },
821
+ { name: "gemini", pkg: "@google/gemini-cli", bin: "gemini", install: "npm i -g @google/gemini-cli", altAuth: null },
822
+ { name: "aider", pkg: null, bin: "aider", install: "pip install aider-chat", altAuth: null },
823
+ { name: "opencode", pkg: null, bin: "opencode", install: "go install github.com/nichochar/opencode@latest", altAuth: null },
824
+ ];
825
+ const { execFileSync: _ef2 } = require("child_process");
826
+ let updatesAvailable = 0;
827
+ console.log("\n agent CLIs:");
828
+ for (const cli of AGENT_CLIS) {
829
+ let installed = false, ver = null;
830
+ try {
831
+ const out = _ef2(cli.bin, ["--version"], { timeout: 3000 }).toString().trim();
832
+ installed = true;
833
+ const m = out.match(/(\d+\.\d+\.\d+)/);
834
+ if (m) ver = m[1];
835
+ } catch {}
836
+
837
+ if (installed) {
838
+ let latest = null;
839
+ if (cli.pkg) {
840
+ try {
841
+ const npmOut = _ef2("npm", ["view", cli.pkg, "version"], { timeout: 5000 }).toString().trim();
842
+ if (npmOut.match(/^\d+\.\d+\.\d+$/)) latest = npmOut;
843
+ } catch {}
844
+ }
845
+ if (latest && ver && latest !== ver) {
846
+ updatesAvailable++;
847
+ console.log(` ${W}update${R2} ${cli.name} ${D}${ver} → ${latest}${R2}`);
848
+ console.log(` ${D}→ ${cli.install}${R2}`);
849
+ } else {
850
+ console.log(` ${G}ok${R2} ${cli.name}${ver ? ` ${D}v${ver}${R2}` : ""}`);
851
+ }
852
+ } else {
853
+ console.log(` ${D}—${R2} ${cli.name} ${D}not installed${R2}`);
854
+ console.log(` ${D}→ ${cli.install}${cli.altAuth ? ` (or ${cli.altAuth})` : ""}${R2}`);
855
+ }
856
+ }
857
+ if (updatesAvailable) {
858
+ console.log(`\n ${D}Run: 0dai update${R2} to update all`);
859
+ }
860
+
810
861
  // --- swarm check ---
811
862
  const swarmDir = path.join(ai, "swarm");
812
863
  const countDir = (d) => { try { return fs.readdirSync(d).filter(f => f.endsWith(".json")).length; } catch { return 0; } };
@@ -888,6 +939,74 @@ function cmdValidate(target) {
888
939
  }
889
940
  }
890
941
 
942
+ // --- Update agent CLIs ---
943
+ function cmdUpdate(args) {
944
+ const { execFileSync: _ef3, execSync } = require("child_process");
945
+ const dryRun = args.includes("--dry-run");
946
+
947
+ const CLIS = [
948
+ { name: "0dai", pkg: "@0dai-dev/cli", bin: "0dai", type: "npm" },
949
+ { name: "claude", pkg: "@anthropic-ai/claude-code",bin: "claude", type: "npm" },
950
+ { name: "codex", pkg: "@openai/codex", bin: "codex", type: "npm" },
951
+ { name: "gemini", pkg: "@google/gemini-cli", bin: "gemini", type: "npm" },
952
+ { name: "aider", pkg: "aider-chat", bin: "aider", type: "pip" },
953
+ { name: "opencode",pkg: null, bin: "opencode",type: "go" },
954
+ ];
955
+
956
+ let updated = 0;
957
+ for (const cli of CLIS) {
958
+ let installed = false, ver = null;
959
+ try {
960
+ const out = _ef3(cli.bin, ["--version"], { timeout: 3000 }).toString().trim();
961
+ installed = true;
962
+ const m = out.match(/(\d+\.\d+\.\d+)/);
963
+ if (m) ver = m[1];
964
+ } catch {}
965
+
966
+ if (!installed) continue;
967
+
968
+ let latest = null;
969
+ if (cli.type === "npm" && cli.pkg) {
970
+ try { latest = _ef3("npm", ["view", cli.pkg, "version"], { timeout: 5000 }).toString().trim(); } catch {}
971
+ } else if (cli.type === "pip" && cli.pkg) {
972
+ try {
973
+ const out = _ef3("pip", ["index", "versions", cli.pkg], { timeout: 8000, encoding: "utf8" });
974
+ const m = out.match(/LATEST:\s*(\d+\.\d+\.\d+)/i) || out.match(/(\d+\.\d+\.\d+)/);
975
+ if (m) latest = m[1];
976
+ } catch {}
977
+ }
978
+
979
+ if (!latest || latest === ver) {
980
+ console.log(` ${cli.name} ${ver || ""} — up to date`);
981
+ continue;
982
+ }
983
+
984
+ console.log(` ${cli.name} ${ver} → ${latest}`);
985
+ if (dryRun) { updated++; continue; }
986
+
987
+ try {
988
+ if (cli.type === "npm") {
989
+ log(`updating ${cli.name}...`);
990
+ execSync(`npm install -g ${cli.pkg}@latest`, { timeout: 60000, stdio: "pipe" });
991
+ log(`${cli.name} updated to ${latest}`);
992
+ updated++;
993
+ } else if (cli.type === "pip") {
994
+ log(`updating ${cli.name}...`);
995
+ execSync(`pip install --upgrade ${cli.pkg}`, { timeout: 60000, stdio: "pipe" });
996
+ log(`${cli.name} updated to ${latest}`);
997
+ updated++;
998
+ }
999
+ } catch (e) {
1000
+ log(`failed to update ${cli.name}: ${e.message.split("\n")[0]}`);
1001
+ }
1002
+ }
1003
+ if (updated) {
1004
+ log(`${dryRun ? "would update" : "updated"} ${updated} CLI(s)`);
1005
+ } else {
1006
+ log("all CLIs are up to date");
1007
+ }
1008
+ }
1009
+
891
1010
  // --- Session reflection --- (dogfood feedback #36)
892
1011
  function cmdReflect(target, args) {
893
1012
  const ai = path.join(target, "ai");
@@ -1912,6 +2031,7 @@ async function main() {
1912
2031
  case "doctor": cmdDoctor(target); break;
1913
2032
  case "validate": cmdValidate(target); break;
1914
2033
  case "reflect": cmdReflect(target, args); break;
2034
+ case "update": cmdUpdate(args); break;
1915
2035
  case "metrics": cmdMetrics(target); break;
1916
2036
  case "portfolio": cmdPortfolio(); break;
1917
2037
  case "status": cmdStatus(target); break;
@@ -1960,7 +2080,8 @@ async function main() {
1960
2080
  console.log(" sync Update ai/ layer (via API) [--dry-run] [--quiet]");
1961
2081
  console.log(" detect Show detected stack");
1962
2082
  console.log(" doctor Check health + credentials checklist");
1963
- console.log(" validate Validate ai/ layer completeness");
2083
+ console.log(" update Update all installed agent CLIs to latest [--dry-run]");
2084
+ console.log(" validate Validate ai/ layer completeness");
1964
2085
  console.log(" reflect Session reflection: delivered, delegation rate, blockers");
1965
2086
  console.log(" metrics Effectiveness score: adoption funnel, sessions, delegation");
1966
2087
  console.log(" portfolio All tracked projects: score, sessions, agents, last activity");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0dai-dev/cli",
3
- "version": "3.1.6",
3
+ "version": "3.1.8",
4
4
  "description": "One config layer for 5 AI agent CLIs — Claude Code, Codex, OpenCode, Gemini, Aider",
5
5
  "bin": {
6
6
  "0dai": "./bin/0dai.js"