@0dai-dev/cli 3.3.5 → 3.9.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/bin/0dai.js +75 -26
  2. package/package.json +1 -1
package/bin/0dai.js CHANGED
@@ -62,6 +62,65 @@ const PROBE_DIRS = [
62
62
  "android", "ios", "linux", "macos", "windows",
63
63
  ];
64
64
 
65
+ // Single source of truth for all supported agent CLIs.
66
+ // Adding a new CLI here automatically wires detection, doctor, validate,
67
+ // and update — no other changes needed in this file. Keep in sync with
68
+ // bootstrap/common.sh's detect_available_clis() and scripts/swarm.py's
69
+ // AGENT_STRENGTHS dict (those are the bash + python equivalents).
70
+ //
71
+ // Fields:
72
+ // name logical name used in discovery.json + swarm
73
+ // bin actual binary name in $PATH (only differs from name for qoder)
74
+ // pkg package name for install/update (null = no auto-update)
75
+ // pkgType "npm" | "pip" | "go" — drives update install command
76
+ // install human-readable install hint shown in doctor output
77
+ // altAuth optional alternative auth hint (subscription, etc.)
78
+ // agentFiles files that must exist when this CLI is selected (cmdValidate)
79
+ const SUPPORTED_CLIS = [
80
+ {
81
+ name: "claude", bin: "claude",
82
+ pkg: "@anthropic-ai/claude-code", pkgType: "npm",
83
+ install: "npm i -g @anthropic-ai/claude-code",
84
+ altAuth: "Pro/Team subscription",
85
+ agentFiles: [".claude/settings.json", ".claude/CLAUDE.md", ".mcp.json"],
86
+ },
87
+ {
88
+ name: "codex", bin: "codex",
89
+ pkg: "@openai/codex", pkgType: "npm",
90
+ install: "npm i -g @openai/codex",
91
+ altAuth: "ChatGPT Pro subscription",
92
+ agentFiles: ["AGENTS.md", ".codex/config.toml"],
93
+ },
94
+ {
95
+ name: "opencode", bin: "opencode",
96
+ pkg: null, pkgType: "go",
97
+ install: "go install github.com/nichochar/opencode@latest",
98
+ altAuth: null,
99
+ agentFiles: ["opencode.json"],
100
+ },
101
+ {
102
+ name: "gemini", bin: "gemini",
103
+ pkg: "@google/gemini-cli", pkgType: "npm",
104
+ install: "npm i -g @google/gemini-cli",
105
+ altAuth: null,
106
+ agentFiles: null,
107
+ },
108
+ {
109
+ name: "aider", bin: "aider",
110
+ pkg: "aider-chat", pkgType: "pip",
111
+ install: "pip install aider-chat",
112
+ altAuth: null,
113
+ agentFiles: null,
114
+ },
115
+ {
116
+ name: "qoder", bin: "qodercli",
117
+ pkg: "@qoder-ai/qodercli", pkgType: "npm",
118
+ install: "npm i -g @qoder-ai/qodercli",
119
+ altAuth: null,
120
+ agentFiles: [".qoder/settings.json"],
121
+ },
122
+ ];
123
+
65
124
  function deviceFingerprint() {
66
125
  const crypto = require("crypto");
67
126
  const parts = [
@@ -323,10 +382,10 @@ function collectMetadata(target) {
323
382
 
324
383
  const clis = [];
325
384
  const { execSync } = require("child_process");
326
- for (const cli of ["claude", "codex", "opencode", "gemini", "aider"]) {
385
+ for (const cli of SUPPORTED_CLIS) {
327
386
  try {
328
- execSync(`command -v ${cli}`, { stdio: "ignore", shell: "/bin/sh", env: process.env });
329
- clis.push(cli);
387
+ execSync(`command -v ${cli.bin}`, { stdio: "ignore", shell: "/bin/sh", env: process.env });
388
+ clis.push(cli.name);
330
389
  } catch {}
331
390
  }
332
391
 
@@ -854,17 +913,10 @@ function cmdDoctor(target) {
854
913
  }
855
914
 
856
915
  // --- agent CLIs check ---
857
- const AGENT_CLIS = [
858
- { name: "claude", pkg: "@anthropic-ai/claude-code", bin: "claude", install: "npm i -g @anthropic-ai/claude-code", altAuth: "Pro/Team subscription" },
859
- { name: "codex", pkg: "@openai/codex", bin: "codex", install: "npm i -g @openai/codex", altAuth: "ChatGPT Pro subscription" },
860
- { name: "gemini", pkg: "@google/gemini-cli", bin: "gemini", install: "npm i -g @google/gemini-cli", altAuth: null },
861
- { name: "aider", pkg: null, bin: "aider", install: "pip install aider-chat", altAuth: null },
862
- { name: "opencode", pkg: null, bin: "opencode", install: "go install github.com/nichochar/opencode@latest", altAuth: null },
863
- ];
864
916
  const { execFileSync: _ef2 } = require("child_process");
865
917
  let updatesAvailable = 0;
866
918
  console.log("\n agent CLIs:");
867
- for (const cli of AGENT_CLIS) {
919
+ for (const cli of SUPPORTED_CLIS) {
868
920
  let installed = false, ver = null;
869
921
  try {
870
922
  const out = _ef2(cli.bin, ["--version"], { timeout: 8000 }).toString().trim();
@@ -936,11 +988,11 @@ function cmdValidate(target) {
936
988
  agents = JSON.parse(fs.readFileSync(path.join(ai, "manifest", "discovery.json"), "utf8")).selected_agents || [];
937
989
  } catch {}
938
990
 
939
- const agentFiles = {
940
- codex: ["AGENTS.md", ".codex/config.toml"],
941
- claude: [".claude/settings.json", ".claude/CLAUDE.md", ".mcp.json"],
942
- opencode: ["opencode.json"],
943
- };
991
+ const agentFiles = Object.fromEntries(
992
+ SUPPORTED_CLIS
993
+ .filter((c) => c.agentFiles && c.agentFiles.length > 0)
994
+ .map((c) => [c.name, c.agentFiles])
995
+ );
944
996
  for (const agent of agents) {
945
997
  for (const f of agentFiles[agent] || []) required.push(f);
946
998
  }
@@ -983,13 +1035,10 @@ function cmdUpdate(args) {
983
1035
  const { execFileSync: _ef3, execSync } = require("child_process");
984
1036
  const dryRun = args.includes("--dry-run");
985
1037
 
1038
+ // 0dai self-update entry, then all supported agent CLIs.
986
1039
  const CLIS = [
987
- { name: "0dai", pkg: "@0dai-dev/cli", bin: "0dai", type: "npm" },
988
- { name: "claude", pkg: "@anthropic-ai/claude-code",bin: "claude", type: "npm" },
989
- { name: "codex", pkg: "@openai/codex", bin: "codex", type: "npm" },
990
- { name: "gemini", pkg: "@google/gemini-cli", bin: "gemini", type: "npm" },
991
- { name: "aider", pkg: "aider-chat", bin: "aider", type: "pip" },
992
- { name: "opencode",pkg: null, bin: "opencode",type: "go" },
1040
+ { name: "0dai", pkg: "@0dai-dev/cli", bin: "0dai", pkgType: "npm" },
1041
+ ...SUPPORTED_CLIS,
993
1042
  ];
994
1043
 
995
1044
  let updated = 0;
@@ -1005,9 +1054,9 @@ function cmdUpdate(args) {
1005
1054
  if (!installed) continue;
1006
1055
 
1007
1056
  let latest = null;
1008
- if (cli.type === "npm" && cli.pkg) {
1057
+ if (cli.pkgType === "npm" && cli.pkg) {
1009
1058
  try { latest = _ef3("npm", ["view", cli.pkg, "version"], { timeout: 5000 }).toString().trim(); } catch {}
1010
- } else if (cli.type === "pip" && cli.pkg) {
1059
+ } else if (cli.pkgType === "pip" && cli.pkg) {
1011
1060
  try {
1012
1061
  const out = _ef3("pip", ["index", "versions", cli.pkg], { timeout: 8000, encoding: "utf8" });
1013
1062
  const m = out.match(/LATEST:\s*(\d+\.\d+\.\d+)/i) || out.match(/(\d+\.\d+\.\d+)/);
@@ -1024,12 +1073,12 @@ function cmdUpdate(args) {
1024
1073
  if (dryRun) { updated++; continue; }
1025
1074
 
1026
1075
  try {
1027
- if (cli.type === "npm") {
1076
+ if (cli.pkgType === "npm") {
1028
1077
  log(`updating ${cli.name}...`);
1029
1078
  execSync(`npm install -g ${cli.pkg}@latest`, { timeout: 60000, stdio: "pipe" });
1030
1079
  log(`${cli.name} updated to ${latest}`);
1031
1080
  updated++;
1032
- } else if (cli.type === "pip") {
1081
+ } else if (cli.pkgType === "pip") {
1033
1082
  log(`updating ${cli.name}...`);
1034
1083
  execSync(`pip install --upgrade ${cli.pkg}`, { timeout: 60000, stdio: "pipe" });
1035
1084
  log(`${cli.name} updated to ${latest}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0dai-dev/cli",
3
- "version": "3.3.5",
3
+ "version": "3.9.0",
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"