@bagdock/cli 0.2.0 → 0.3.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.
package/dist/bagdock.js CHANGED
@@ -2085,31 +2085,87 @@ var require_commander = __commonJS((exports) => {
2085
2085
  import { homedir } from "os";
2086
2086
  import { join } from "path";
2087
2087
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
2088
+ function setProfileOverride(name) {
2089
+ profileOverride = name;
2090
+ }
2088
2091
  function ensureConfigDir() {
2089
2092
  if (!existsSync(CONFIG_DIR)) {
2090
2093
  mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
2091
2094
  }
2092
2095
  }
2093
- function loadCredentials() {
2096
+ function loadStore() {
2094
2097
  try {
2095
- if (!existsSync(CREDENTIALS_FILE))
2096
- return null;
2097
- const raw = readFileSync(CREDENTIALS_FILE, "utf-8");
2098
- return JSON.parse(raw);
2098
+ if (!existsSync(CREDENTIALS_FILE)) {
2099
+ return { activeProfile: "default", profiles: {} };
2100
+ }
2101
+ const raw = JSON.parse(readFileSync(CREDENTIALS_FILE, "utf-8"));
2102
+ if (raw.accessToken && !raw.profiles) {
2103
+ const migrated = {
2104
+ activeProfile: "default",
2105
+ profiles: { default: raw }
2106
+ };
2107
+ saveStore(migrated);
2108
+ return migrated;
2109
+ }
2110
+ return raw;
2099
2111
  } catch {
2100
- return null;
2112
+ return { activeProfile: "default", profiles: {} };
2101
2113
  }
2102
2114
  }
2103
- function saveCredentials(creds) {
2115
+ function saveStore(store) {
2104
2116
  ensureConfigDir();
2105
- writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), { mode: 384 });
2117
+ writeFileSync(CREDENTIALS_FILE, JSON.stringify(store, null, 2), { mode: 384 });
2118
+ }
2119
+ function resolveProfile() {
2120
+ if (profileOverride)
2121
+ return profileOverride;
2122
+ if (process.env.BAGDOCK_PROFILE)
2123
+ return process.env.BAGDOCK_PROFILE;
2124
+ return loadStore().activeProfile;
2125
+ }
2126
+ function loadCredentials() {
2127
+ const store = loadStore();
2128
+ const name = resolveProfile();
2129
+ return store.profiles[name] ?? null;
2130
+ }
2131
+ function saveCredentials(creds, profileName) {
2132
+ const store = loadStore();
2133
+ const name = profileName ?? resolveProfile();
2134
+ store.profiles[name] = creds;
2135
+ if (!store.activeProfile || Object.keys(store.profiles).length === 1) {
2136
+ store.activeProfile = name;
2137
+ }
2138
+ saveStore(store);
2106
2139
  }
2107
2140
  function clearCredentials() {
2108
- try {
2109
- if (existsSync(CREDENTIALS_FILE)) {
2110
- writeFileSync(CREDENTIALS_FILE, "{}", { mode: 384 });
2111
- }
2112
- } catch {}
2141
+ const store = loadStore();
2142
+ const name = resolveProfile();
2143
+ delete store.profiles[name];
2144
+ if (store.activeProfile === name) {
2145
+ const remaining = Object.keys(store.profiles);
2146
+ store.activeProfile = remaining[0] ?? "default";
2147
+ }
2148
+ saveStore(store);
2149
+ }
2150
+ function listProfiles() {
2151
+ const store = loadStore();
2152
+ return Object.entries(store.profiles).map(([name, creds]) => ({
2153
+ name,
2154
+ email: creds.email,
2155
+ operatorId: creds.operatorId,
2156
+ active: name === store.activeProfile
2157
+ }));
2158
+ }
2159
+ function switchProfile(name) {
2160
+ const store = loadStore();
2161
+ if (!store.profiles[name])
2162
+ return false;
2163
+ store.activeProfile = name;
2164
+ saveStore(store);
2165
+ return true;
2166
+ }
2167
+ function getActiveProfileName() {
2168
+ return resolveProfile();
2113
2169
  }
2114
2170
  function loadBagdockJson(dir) {
2115
2171
  const file = join(dir, "bagdock.json");
@@ -2121,7 +2177,7 @@ function loadBagdockJson(dir) {
2121
2177
  return null;
2122
2178
  }
2123
2179
  }
2124
- var CONFIG_DIR, CREDENTIALS_FILE, API_BASE, DASHBOARD_BASE;
2180
+ var CONFIG_DIR, CREDENTIALS_FILE, API_BASE, DASHBOARD_BASE, profileOverride;
2125
2181
  var init_config = __esm(() => {
2126
2182
  CONFIG_DIR = join(homedir(), ".bagdock");
2127
2183
  CREDENTIALS_FILE = join(CONFIG_DIR, "credentials.json");
@@ -2618,6 +2674,59 @@ var init_source = __esm(() => {
2618
2674
  source_default = chalk;
2619
2675
  });
2620
2676
 
2677
+ // src/output.ts
2678
+ function setOutputMode(opts) {
2679
+ quiet = !!opts.quiet;
2680
+ forceJson = !!opts.json || !!opts.quiet;
2681
+ }
2682
+ function isJsonMode() {
2683
+ return forceJson || !process.stdout.isTTY;
2684
+ }
2685
+ function isQuiet() {
2686
+ return quiet;
2687
+ }
2688
+ function outputSuccess(data) {
2689
+ if (isJsonMode()) {
2690
+ process.stdout.write(JSON.stringify(data, null, 2) + `
2691
+ `);
2692
+ }
2693
+ }
2694
+ function outputError(code, message, details) {
2695
+ if (isJsonMode()) {
2696
+ const err = { error: { code, message } };
2697
+ if (details)
2698
+ err.error.details = details;
2699
+ process.stderr.write(JSON.stringify(err) + `
2700
+ `);
2701
+ process.exit(1);
2702
+ } else {
2703
+ console.error(source_default.red(`Error [${code}]:`), message);
2704
+ if (details)
2705
+ console.error(details);
2706
+ process.exit(1);
2707
+ }
2708
+ }
2709
+ function outputList(objectType, data, hasMore) {
2710
+ if (isJsonMode()) {
2711
+ process.stdout.write(JSON.stringify({ object: "list", data, has_more: hasMore }, null, 2) + `
2712
+ `);
2713
+ }
2714
+ }
2715
+ function status(message) {
2716
+ if (!isQuiet() && !isJsonMode()) {
2717
+ console.log(source_default.dim(message));
2718
+ }
2719
+ }
2720
+ function success(message) {
2721
+ if (!isQuiet() && !isJsonMode()) {
2722
+ console.log(source_default.green(message));
2723
+ }
2724
+ }
2725
+ var forceJson = false, quiet = false;
2726
+ var init_output = __esm(() => {
2727
+ init_source();
2728
+ });
2729
+
2621
2730
  // node_modules/is-docker/index.js
2622
2731
  import fs from "node:fs";
2623
2732
  function hasDockerEnv() {
@@ -3172,6 +3281,18 @@ function getAuthToken() {
3172
3281
  const creds = loadCredentials();
3173
3282
  return creds?.accessToken ?? null;
3174
3283
  }
3284
+ function getAuthSource() {
3285
+ if (apiKeyOverride)
3286
+ return { token: apiKeyOverride, source: "flag" };
3287
+ if (process.env.BAGDOCK_API_KEY)
3288
+ return { token: process.env.BAGDOCK_API_KEY, source: "env (BAGDOCK_API_KEY)" };
3289
+ if (process.env.BAGDOCK_TOKEN)
3290
+ return { token: process.env.BAGDOCK_TOKEN, source: "env (BAGDOCK_TOKEN)" };
3291
+ const creds = loadCredentials();
3292
+ if (creds?.accessToken)
3293
+ return { token: creds.accessToken, source: `config (${getActiveProfileName()})` };
3294
+ return { token: null, source: "none" };
3295
+ }
3175
3296
  async function login() {
3176
3297
  const existing = loadCredentials();
3177
3298
  if (existing?.accessToken && existing.expiresAt && existing.expiresAt > Date.now()) {
@@ -3228,12 +3349,12 @@ Requesting device authorization...
3228
3349
  console.log(" Email:", source_default.bold(tokens.email));
3229
3350
  if (tokens.operator_id)
3230
3351
  console.log(" Operator:", source_default.bold(tokens.operator_id));
3352
+ console.log(" Profile:", source_default.bold(getActiveProfileName()));
3231
3353
  return;
3232
3354
  }
3233
3355
  const error = await tokenRes.json().catch(() => ({ error: "unknown" }));
3234
- if (error.error === "authorization_pending") {
3356
+ if (error.error === "authorization_pending")
3235
3357
  continue;
3236
- }
3237
3358
  if (error.error === "slow_down") {
3238
3359
  await sleep(pollInterval);
3239
3360
  continue;
@@ -3258,7 +3379,7 @@ Requesting device authorization...
3258
3379
  }
3259
3380
  async function logout() {
3260
3381
  clearCredentials();
3261
- console.log(source_default.green("Logged out."));
3382
+ console.log(source_default.green(`Logged out of profile "${getActiveProfileName()}".`));
3262
3383
  }
3263
3384
  async function whoami() {
3264
3385
  const token = getAuthToken();
@@ -3275,16 +3396,92 @@ async function whoami() {
3275
3396
  process.exit(1);
3276
3397
  }
3277
3398
  const user = await res.json();
3278
- console.log(source_default.green("Logged in as"), source_default.bold(user.email));
3279
- if (user.operator_id)
3280
- console.log("Operator:", source_default.bold(user.operator_id));
3281
- if (user.name)
3282
- console.log("Name:", user.name);
3399
+ if (isJsonMode()) {
3400
+ outputSuccess({ ...user, profile: getActiveProfileName() });
3401
+ } else {
3402
+ console.log(source_default.green("Logged in as"), source_default.bold(user.email));
3403
+ if (user.operator_id)
3404
+ console.log("Operator:", source_default.bold(user.operator_id));
3405
+ if (user.name)
3406
+ console.log("Name:", user.name);
3407
+ console.log("Profile:", source_default.bold(getActiveProfileName()));
3408
+ }
3283
3409
  } catch (err) {
3284
3410
  console.log(source_default.red("Failed to reach API:"), err.message);
3285
3411
  process.exit(1);
3286
3412
  }
3287
3413
  }
3414
+ async function authList() {
3415
+ const profiles = listProfiles();
3416
+ if (isJsonMode()) {
3417
+ outputSuccess({ profiles });
3418
+ return;
3419
+ }
3420
+ if (!profiles.length) {
3421
+ console.log(source_default.yellow(`
3422
+ No profiles found.`), "Run", source_default.cyan("bagdock login"), `to create one.
3423
+ `);
3424
+ return;
3425
+ }
3426
+ console.log();
3427
+ for (const p of profiles) {
3428
+ const marker = p.active ? source_default.green("* ") : " ";
3429
+ const label = p.active ? source_default.bold(p.name) : p.name;
3430
+ const email = p.email ? source_default.dim(` (${p.email})`) : "";
3431
+ const op = p.operatorId ? source_default.dim(` [${p.operatorId}]`) : "";
3432
+ console.log(` ${marker}${label}${email}${op}`);
3433
+ }
3434
+ console.log();
3435
+ }
3436
+ async function authSwitch(name) {
3437
+ const profiles = listProfiles();
3438
+ if (!profiles.length) {
3439
+ console.log(source_default.yellow("No profiles found."), "Run", source_default.cyan("bagdock login"), "first.");
3440
+ process.exit(1);
3441
+ }
3442
+ if (name) {
3443
+ if (switchProfile(name)) {
3444
+ if (isJsonMode()) {
3445
+ outputSuccess({ active_profile: name });
3446
+ } else {
3447
+ console.log(source_default.green(`Switched to profile "${name}".`));
3448
+ }
3449
+ } else {
3450
+ outputError("NOT_FOUND", `Profile "${name}" not found. Available: ${profiles.map((p) => p.name).join(", ")}`);
3451
+ }
3452
+ return;
3453
+ }
3454
+ if (!process.stdout.isTTY) {
3455
+ outputError("MISSING_PROFILE", "Pass a profile name in non-interactive mode: bagdock auth switch <name>");
3456
+ }
3457
+ console.log(source_default.cyan(`
3458
+ Available profiles:
3459
+ `));
3460
+ profiles.forEach((p, i) => {
3461
+ const marker = p.active ? source_default.green("* ") : " ";
3462
+ const email = p.email ? source_default.dim(` (${p.email})`) : "";
3463
+ console.log(` ${marker}${i + 1}. ${p.name}${email}`);
3464
+ });
3465
+ const readline = await import("readline");
3466
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
3467
+ const answer = await new Promise((resolve) => {
3468
+ rl.question(source_default.cyan(`
3469
+ Enter profile number or name: `), resolve);
3470
+ });
3471
+ rl.close();
3472
+ const idx = parseInt(answer, 10);
3473
+ const target = idx > 0 && idx <= profiles.length ? profiles[idx - 1].name : answer.trim();
3474
+ if (switchProfile(target)) {
3475
+ console.log(source_default.green(`
3476
+ Switched to profile "${target}".
3477
+ `));
3478
+ } else {
3479
+ console.log(source_default.red(`
3480
+ Profile "${target}" not found.
3481
+ `));
3482
+ process.exit(1);
3483
+ }
3484
+ }
3288
3485
  function sleep(ms) {
3289
3486
  return new Promise((resolve) => setTimeout(resolve, ms));
3290
3487
  }
@@ -3292,64 +3489,136 @@ var apiKeyOverride, CLIENT_ID = "bagdock-cli", MAX_POLL_DURATION_MS = 300000;
3292
3489
  var init_auth = __esm(() => {
3293
3490
  init_config();
3294
3491
  init_source();
3492
+ init_output();
3295
3493
  });
3296
3494
 
3297
- // src/output.ts
3298
- function setOutputMode(opts) {
3299
- if (opts.quiet) {
3300
- quiet = true;
3301
- forceJson = true;
3495
+ // src/doctor.ts
3496
+ var exports_doctor = {};
3497
+ __export(exports_doctor, {
3498
+ doctor: () => doctor
3499
+ });
3500
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
3501
+ import { join as join3, dirname } from "path";
3502
+ import { homedir as homedir2, platform as platform2 } from "os";
3503
+ import { fileURLToPath as fileURLToPath2 } from "url";
3504
+ function maskKey(key) {
3505
+ if (key.length <= 12)
3506
+ return key.slice(0, 4) + "...";
3507
+ return key.slice(0, 8) + "..." + key.slice(-4);
3508
+ }
3509
+ function getLocalVersion() {
3510
+ try {
3511
+ const pkgPath = join3(dirname(fileURLToPath2(import.meta.url)), "..", "package.json");
3512
+ const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
3513
+ return pkg.version ?? "unknown";
3514
+ } catch {
3515
+ return "unknown";
3302
3516
  }
3303
- if (opts.json) {
3304
- forceJson = true;
3517
+ }
3518
+ async function checkVersion() {
3519
+ const local = getLocalVersion();
3520
+ try {
3521
+ const res = await fetch("https://registry.npmjs.org/@bagdock/cli/latest", {
3522
+ signal: AbortSignal.timeout(5000)
3523
+ });
3524
+ if (res.ok) {
3525
+ const data = await res.json();
3526
+ if (data.version === local) {
3527
+ return { name: "CLI Version", status: "pass", message: `v${local} (latest)` };
3528
+ }
3529
+ return { name: "CLI Version", status: "warn", message: `v${local} (update available: v${data.version})` };
3530
+ }
3531
+ } catch {}
3532
+ return { name: "CLI Version", status: "pass", message: `v${local} (registry unreachable)` };
3533
+ }
3534
+ function checkAuth() {
3535
+ const { token, source } = getAuthSource();
3536
+ if (!token) {
3537
+ return { name: "API Key", status: "fail", message: "No API key found. Run `bagdock login` or set BAGDOCK_API_KEY." };
3305
3538
  }
3539
+ return { name: "API Key", status: "pass", message: `${maskKey(token)} (source: ${source})` };
3306
3540
  }
3307
- function isJsonMode() {
3308
- return forceJson || !process.stdout.isTTY;
3541
+ function checkProjectConfig() {
3542
+ const config = loadBagdockJson(process.cwd());
3543
+ if (!config) {
3544
+ return { name: "Project Config", status: "warn", message: "No bagdock.json found in current directory" };
3545
+ }
3546
+ const issues = [];
3547
+ if (!config.slug)
3548
+ issues.push("missing slug");
3549
+ if (!config.type)
3550
+ issues.push("missing type");
3551
+ if (!config.main)
3552
+ issues.push("missing main");
3553
+ if (issues.length) {
3554
+ return { name: "Project Config", status: "warn", message: `bagdock.json has issues: ${issues.join(", ")}` };
3555
+ }
3556
+ return { name: "Project Config", status: "pass", message: `${config.slug} (${config.type}/${config.kind ?? config.category})` };
3309
3557
  }
3310
- function isQuiet() {
3311
- return quiet;
3558
+ function checkAgents() {
3559
+ const detected = [];
3560
+ const home = homedir2();
3561
+ if (existsSync3(join3(home, ".cursor")))
3562
+ detected.push("Cursor");
3563
+ if (existsSync3(join3(home, ".windsurf")))
3564
+ detected.push("Windsurf");
3565
+ if (existsSync3(join3(home, "clawd", "skills")) || existsSync3(join3(home, ".codex")))
3566
+ detected.push("OpenClaw/Codex");
3567
+ const p = platform2();
3568
+ if (p === "darwin" && existsSync3(join3(home, "Library", "Application Support", "Claude", "claude_desktop_config.json"))) {
3569
+ detected.push("Claude Desktop");
3570
+ } else if (p === "win32" && existsSync3(join3(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json"))) {
3571
+ detected.push("Claude Desktop");
3572
+ } else if (p === "linux" && existsSync3(join3(home, ".config", "Claude", "claude_desktop_config.json"))) {
3573
+ detected.push("Claude Desktop");
3574
+ }
3575
+ if (existsSync3(join3(process.cwd(), ".vscode", "mcp.json")))
3576
+ detected.push("VS Code");
3577
+ if (!detected.length) {
3578
+ return { name: "AI Agents", status: "pass", message: "None detected" };
3579
+ }
3580
+ return { name: "AI Agents", status: "pass", message: `Detected: ${detected.join(", ")}` };
3312
3581
  }
3313
- function outputSuccess(data) {
3582
+ async function doctor() {
3583
+ const checks = [];
3314
3584
  if (isJsonMode()) {
3315
- process.stdout.write(JSON.stringify(data, null, 2) + `
3316
- `);
3585
+ checks.push(await checkVersion());
3586
+ checks.push(checkAuth());
3587
+ checks.push(checkProjectConfig());
3588
+ checks.push(checkAgents());
3589
+ const ok = checks.every((c) => c.status !== "fail");
3590
+ outputSuccess({ ok, checks });
3591
+ return;
3317
3592
  }
3318
- }
3319
- function outputError(code, message, details) {
3320
- if (isJsonMode()) {
3321
- const err = { error: { code, message } };
3322
- if (details)
3323
- err.error.details = details;
3324
- process.stderr.write(JSON.stringify(err) + `
3593
+ console.log(source_default.bold(`
3594
+ Bagdock Doctor
3595
+ `));
3596
+ process.stdout.write(" Checking CLI version...");
3597
+ const versionCheck = await checkVersion();
3598
+ checks.push(versionCheck);
3599
+ process.stdout.write(`\r ${ICON[versionCheck.status]} ${versionCheck.name}: ${versionCheck.message}
3325
3600
  `);
3601
+ const authCheck = checkAuth();
3602
+ checks.push(authCheck);
3603
+ console.log(` ${ICON[authCheck.status]} ${authCheck.name}: ${authCheck.message}`);
3604
+ const configCheck = checkProjectConfig();
3605
+ checks.push(configCheck);
3606
+ console.log(` ${ICON[configCheck.status]} ${configCheck.name}: ${configCheck.message}`);
3607
+ const agentCheck = checkAgents();
3608
+ checks.push(agentCheck);
3609
+ console.log(` ${ICON[agentCheck.status]} ${agentCheck.name}: ${agentCheck.message}`);
3610
+ console.log();
3611
+ const hasFail = checks.some((c) => c.status === "fail");
3612
+ if (hasFail)
3326
3613
  process.exit(1);
3327
- } else {
3328
- console.error(source_default.red(`Error [${code}]:`), message);
3329
- if (details)
3330
- console.error(details);
3331
- process.exit(1);
3332
- }
3333
3614
  }
3334
- function outputList(objectType, data, hasMore) {
3335
- if (isJsonMode()) {
3336
- process.stdout.write(JSON.stringify({ object: "list", data, has_more: hasMore }, null, 2) + `
3337
- `);
3338
- }
3339
- }
3340
- function status(message) {
3341
- if (!isQuiet() && !isJsonMode()) {
3342
- console.log(source_default.dim(message));
3343
- }
3344
- }
3345
- function success(message) {
3346
- if (!isQuiet() && !isJsonMode()) {
3347
- console.log(source_default.green(message));
3348
- }
3349
- }
3350
- var forceJson = false, quiet = false;
3351
- var init_output = __esm(() => {
3615
+ var ICON;
3616
+ var init_doctor = __esm(() => {
3352
3617
  init_source();
3618
+ init_auth();
3619
+ init_config();
3620
+ init_output();
3621
+ ICON = { pass: source_default.green("✔"), warn: source_default.yellow("!"), fail: source_default.red("✘") };
3353
3622
  });
3354
3623
 
3355
3624
  // src/dev.ts
@@ -3357,8 +3626,8 @@ var exports_dev = {};
3357
3626
  __export(exports_dev, {
3358
3627
  dev: () => dev
3359
3628
  });
3360
- import { existsSync as existsSync3, writeFileSync as writeFileSync3 } from "fs";
3361
- import { join as join3 } from "path";
3629
+ import { existsSync as existsSync4, writeFileSync as writeFileSync3 } from "fs";
3630
+ import { join as join4 } from "path";
3362
3631
  import { spawn } from "child_process";
3363
3632
  async function dev(opts) {
3364
3633
  const cwd = process.cwd();
@@ -3369,11 +3638,11 @@ async function dev(opts) {
3369
3638
  }
3370
3639
  const port = opts.port ?? "8787";
3371
3640
  const wranglerToml = generateWranglerToml(config, port);
3372
- const wranglerPath = join3(cwd, "wrangler.toml");
3641
+ const wranglerPath = join4(cwd, "wrangler.toml");
3373
3642
  writeFileSync3(wranglerPath, wranglerToml);
3374
3643
  console.log(source_default.green("Generated"), source_default.cyan("wrangler.toml"), source_default.green("from bagdock.json"));
3375
- const devVarsPath = join3(cwd, ".dev.vars");
3376
- if (!existsSync3(devVarsPath) && config.env) {
3644
+ const devVarsPath = join4(cwd, ".dev.vars");
3645
+ if (!existsSync4(devVarsPath) && config.env) {
3377
3646
  const hint = Object.entries(config.env).map(([key, meta]) => `# ${meta.description ?? key}${meta.required ? " (required)" : ""}
3378
3647
  ${key}=`).join(`
3379
3648
  `);
@@ -3434,8 +3703,8 @@ var exports_deploy = {};
3434
3703
  __export(exports_deploy, {
3435
3704
  deploy: () => deploy
3436
3705
  });
3437
- import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
3438
- import { join as join4 } from "path";
3706
+ import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
3707
+ import { join as join5 } from "path";
3439
3708
  import { execSync } from "child_process";
3440
3709
  import { createInterface } from "readline";
3441
3710
  async function deploy(opts) {
@@ -3476,8 +3745,8 @@ async function deploy(opts) {
3476
3745
  console.log(source_default.cyan(`
3477
3746
  Deploying ${config.slug}@${config.version} → ${envLabel}
3478
3747
  `));
3479
- const outDir = join4(cwd, ".bagdock");
3480
- const outFile = join4(outDir, "worker.mjs");
3748
+ const outDir = join5(cwd, ".bagdock");
3749
+ const outFile = join5(outDir, "worker.mjs");
3481
3750
  console.log(source_default.dim(" Building worker bundle..."));
3482
3751
  execSync(`mkdir -p ${outDir}`, { cwd });
3483
3752
  try {
@@ -3493,11 +3762,11 @@ Deploying ${config.slug}@${config.version} → ${envLabel}
3493
3762
  process.exit(1);
3494
3763
  }
3495
3764
  }
3496
- if (!existsSync4(outFile)) {
3765
+ if (!existsSync5(outFile)) {
3497
3766
  console.error(source_default.red(" Build output not found at"), outFile);
3498
3767
  process.exit(1);
3499
3768
  }
3500
- const scriptContent = readFileSync2(outFile);
3769
+ const scriptContent = readFileSync3(outFile);
3501
3770
  const sizeKb = (scriptContent.length / 1024).toFixed(1);
3502
3771
  console.log(source_default.dim(` Bundle size: ${sizeKb} KB`));
3503
3772
  console.log(source_default.dim(" Uploading to Bagdock platform..."));
@@ -4304,16 +4573,26 @@ function toPascalCase(s) {
4304
4573
 
4305
4574
  // bin/bagdock.ts
4306
4575
  init_output();
4576
+ init_config();
4307
4577
  var program2 = new Command;
4308
- program2.name("bagdock").description("Bagdock developer CLI").version("0.1.4").option("--json", "Force JSON output (auto-enabled in non-TTY)").option("-q, --quiet", "Suppress status messages (implies --json)").option("--api-key <key>", "API key to use for this invocation").hook("preAction", (_thisCommand, actionCommand) => {
4578
+ program2.name("bagdock").description("Bagdock developer CLI — built for humans, AI agents, and CI/CD pipelines").version("0.3.0").option("--json", "Force JSON output (auto-enabled in non-TTY)").option("-q, --quiet", "Suppress status messages (implies --json)").option("--api-key <key>", "API key to use for this invocation").option("-p, --profile <name>", "Profile to use (overrides BAGDOCK_PROFILE)").hook("preAction", (_thisCommand, actionCommand) => {
4309
4579
  const opts = program2.opts();
4310
4580
  setOutputMode({ json: opts.json, quiet: opts.quiet });
4311
4581
  if (opts.apiKey)
4312
4582
  setApiKeyOverride(opts.apiKey);
4583
+ if (opts.profile)
4584
+ setProfileOverride(opts.profile);
4313
4585
  });
4314
4586
  program2.command("login").description("Authenticate with Bagdock (opens browser)").action(login);
4315
4587
  program2.command("logout").description("Clear stored credentials").action(logout);
4316
4588
  program2.command("whoami").description("Show current authenticated user").action(whoami);
4589
+ var authCmd = program2.command("auth").description("Manage authentication profiles");
4590
+ authCmd.command("list").description("List all stored profiles").action(authList);
4591
+ authCmd.command("switch [name]").description("Switch active profile").action(async (name) => authSwitch(name));
4592
+ program2.command("doctor").description("Run environment diagnostics").action(async () => {
4593
+ const { doctor: doctor2 } = await Promise.resolve().then(() => (init_doctor(), exports_doctor));
4594
+ await doctor2();
4595
+ });
4317
4596
  program2.command("init [dir]").description("Scaffold a new project with bagdock.json").option("-t, --type <type>", "Project type (edge, app)").option("-k, --kind <kind>", "Project kind (adapter, comms, webhook, ui-extension, microfrontend)").option("-c, --category <category>", "Category").option("-s, --slug <slug>", "Unique project slug").option("-n, --name <name>", "Display name").action((dir, opts) => init(dir ?? ".", opts));
4318
4597
  program2.command("dev").description("Start local dev server").option("-p, --port <port>", "Local dev port", "8787").action(async (opts) => {
4319
4598
  const { dev: dev2 } = await Promise.resolve().then(() => (init_dev(), exports_dev));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bagdock/cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Bagdock developer CLI — build, test, and deploy apps and edges on the Bagdock platform",
5
5
  "keywords": [
6
6
  "bagdock",
@@ -28,8 +28,14 @@
28
28
  "files": [
29
29
  "dist",
30
30
  "README.md",
31
- "LICENSE"
31
+ "LICENSE",
32
+ "skills",
33
+ "skill-evals"
32
34
  ],
35
+ "skills": {
36
+ "name": "bagdock-cli",
37
+ "path": "skills/bagdock-cli"
38
+ },
33
39
  "publishConfig": {
34
40
  "access": "public"
35
41
  },
@@ -37,15 +43,18 @@
37
43
  "dev": "bun run bin/bagdock.ts",
38
44
  "build": "bun build bin/bagdock.ts --outdir dist --target node --format esm && node -e \"const fs=require('fs');const f='dist/bagdock.js';let c=fs.readFileSync(f,'utf8');c=c.replace(/^#!.*\\n/,'').replace(/^\\/\\/ @bun\\n/,'');fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c)\"",
39
45
  "prepublishOnly": "bun run build",
46
+ "test": "vitest run",
47
+ "test:watch": "vitest",
40
48
  "typecheck": "tsc --noEmit"
41
49
  },
42
50
  "dependencies": {
51
+ "chalk": "^5.4.1",
43
52
  "commander": "^13.1.0",
44
- "open": "^10.1.0",
45
- "chalk": "^5.4.1"
53
+ "open": "^10.1.0"
46
54
  },
47
55
  "devDependencies": {
48
56
  "@types/bun": "latest",
49
- "typescript": "^5.3.3"
57
+ "typescript": "^5.3.3",
58
+ "vitest": "^3.2.4"
50
59
  }
51
60
  }