@0dai-dev/cli 3.1.4 → 3.1.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.
Files changed (2) hide show
  1. package/bin/0dai.js +61 -3
  2. package/package.json +1 -1
package/bin/0dai.js CHANGED
@@ -391,7 +391,12 @@ async function cmdInit(target, args = []) {
391
391
  });
392
392
 
393
393
  if (result.error) {
394
- if (result.hint) {
394
+ if (result.error.includes("authentication")) {
395
+ log(`authentication required`);
396
+ console.log(` 0dai auth is separate from your agent CLIs (Claude Code, Codex).`);
397
+ console.log(` It tracks projects, usage limits, and team features.\n`);
398
+ console.log(` ${D}Run: 0dai auth login${R}`);
399
+ } else if (result.hint) {
395
400
  log(`${result.message || result.error}`);
396
401
  console.log(` ${result.hint}\n`);
397
402
  } else {
@@ -411,6 +416,11 @@ async function cmdInit(target, args = []) {
411
416
  }
412
417
  writeFiles(target, result.files || {});
413
418
 
419
+ // Ensure ai/VERSION matches CLI version
420
+ const versionFile = path.join(target, "ai", "VERSION");
421
+ fs.mkdirSync(path.dirname(versionFile), { recursive: true });
422
+ fs.writeFileSync(versionFile, VERSION + "\n", "utf8");
423
+
414
424
  // Add to .gitignore
415
425
  const gi = path.join(target, ".gitignore");
416
426
  try {
@@ -499,7 +509,17 @@ async function cmdSync(target, args = []) {
499
509
  dry_run: dryRun, quiet,
500
510
  });
501
511
 
502
- if (result.error) { log(`error: ${result.error}`); process.exit(1); }
512
+ if (result.error) {
513
+ if (result.error.includes("authentication")) {
514
+ log(`authentication required`);
515
+ console.log(` 0dai auth is separate from your agent CLIs (Claude Code, Codex).`);
516
+ console.log(` It tracks projects, usage limits, and team features.\n`);
517
+ console.log(` ${D}Run: 0dai auth login${R}`);
518
+ } else {
519
+ log(`error: ${result.error}`);
520
+ }
521
+ process.exit(1);
522
+ }
503
523
 
504
524
  const updated = result.files_updated || {};
505
525
  if (dryRun) {
@@ -524,6 +544,15 @@ async function cmdSync(target, args = []) {
524
544
  log("already up to date");
525
545
  }
526
546
 
547
+ // Ensure ai/VERSION matches CLI version after successful sync
548
+ const versionFile = path.join(target, "ai", "VERSION");
549
+ try {
550
+ const current = fs.existsSync(versionFile) ? fs.readFileSync(versionFile, "utf8").trim() : "";
551
+ if (current !== VERSION) {
552
+ fs.writeFileSync(versionFile, VERSION + "\n", "utf8");
553
+ }
554
+ } catch {}
555
+
527
556
  // Update portfolio registry
528
557
  registerProject(target, path.basename(target), stack);
529
558
  }
@@ -1247,10 +1276,38 @@ async function checkVersion() {
1247
1276
  async function cmdAuthLogin() {
1248
1277
  const isTTY = process.stdout.isTTY && process.stdin.isTTY;
1249
1278
 
1279
+ // Check if already authenticated
1280
+ try {
1281
+ const existing = JSON.parse(fs.readFileSync(AUTH_FILE, "utf8"));
1282
+ if (existing.access_token || existing.email) {
1283
+ if (isTTY) {
1284
+ const p = require("@clack/prompts");
1285
+ p.intro(`${T}0dai${R} authentication`);
1286
+ p.log.success(`Already logged in as ${T}${existing.email || "unknown"}${R} (${existing.plan || "free"} plan)`);
1287
+ const reauth = await p.confirm({ message: "Sign in with a different account?" });
1288
+ if (p.isCancel(reauth) || !reauth) {
1289
+ p.outro("Current session kept");
1290
+ return;
1291
+ }
1292
+ } else {
1293
+ log(`Already logged in as ${existing.email || "unknown"} (${existing.plan || "free"} plan)`);
1294
+ log("To switch accounts, delete ~/.0dai/auth.json and run again");
1295
+ return;
1296
+ }
1297
+ }
1298
+ } catch {}
1299
+
1250
1300
  if (isTTY) {
1251
1301
  // Interactive TUI flow
1252
1302
  const p = require("@clack/prompts");
1253
- p.intro(`${T}0dai${R} authentication`);
1303
+ if (!p._intro_shown) p.intro(`${T}0dai${R} authentication`);
1304
+
1305
+ p.note(
1306
+ "0dai auth is separate from agent CLIs (Claude Code, Codex).\n" +
1307
+ "It tracks your projects, usage limits, and team features.\n" +
1308
+ "Your agent CLIs keep their own auth (subscription/API key).",
1309
+ "Why sign in?"
1310
+ );
1254
1311
 
1255
1312
  const method = await p.select({
1256
1313
  message: "How would you like to sign in?",
@@ -1344,6 +1401,7 @@ async function cmdAuthLogin() {
1344
1401
 
1345
1402
  } else {
1346
1403
  // Non-interactive: device code only
1404
+ log("0dai auth is separate from agent CLIs. It tracks projects, limits, and team features.");
1347
1405
  const result = await apiCall("/v1/auth/device", { client_id: "cli" });
1348
1406
  if (result.error) { log(`error: ${result.error}`); process.exit(1); }
1349
1407
  log(`Open: ${result.verification_uri}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0dai-dev/cli",
3
- "version": "3.1.4",
3
+ "version": "3.1.6",
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"