@dosu/cli 0.60.2 → 0.62.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 (3) hide show
  1. package/README.md +2 -0
  2. package/bin/dosu.js +365 -120
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -107,6 +107,8 @@ Or right-click the binary, select "Open", and click "Open" in the dialog.
107
107
 
108
108
  `dosu upgrade` delegates to npm, pnpm, Yarn Classic, or Homebrew only after confirming which manager owns the current installation. Temporary package-runner invocations stay ephemeral, ambiguous or local installs are left unchanged, and standalone binaries receive the latest safe manual download path. After a successful update it hands off to the new version, which re-applies the bundled skills and, only if the update crossed a release that changed the agent config format, runs `dosu setup` (or the non-interactive `dosu mcp refresh` without a TTY). Upgrades done outside `dosu upgrade` (npm, brew, `npx @dosu/cli@latest`) get a safety net: when the new version changed the shape of the MCP entry, the first command on it silently rewrites configured tools' MCP entries and prompts you to run `dosu setup` for the rest; the bundled agent skills are always re-applied on the first command after any version change.
109
109
 
110
+ Dosu also updates itself automatically. When the update check (every six hours) finds a newer release, npm, pnpm, Yarn Classic, and Homebrew installs start the same package-manager update in a detached background process. The current command runs unchanged, and your next command uses the new version, whose first run applies the skill and MCP refreshes above. Hooks, rules, and the status line still need `dosu setup` when a release changes them. Background updates never run for `npx` invocations, standalone binaries, CI, or `DOSU_DEV=true`. A failed install (for example, a global npm prefix that needs `sudo`) falls back to the "Run `dosu upgrade`" notice and is retried after six hours. Turn background updates off with `dosu upgrade --auto off` (and back on with `--auto on`), or with `DOSU_DISABLE_AUTOUPDATE=1` for a single environment.
111
+
110
112
  ### Platform commands
111
113
 
112
114
  Once authenticated against a deployment, you can drive the Dosu platform without leaving the terminal:
package/bin/dosu.js CHANGED
@@ -1083,7 +1083,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
1083
1083
  function getVersionString() {
1084
1084
  return `v${VERSION}`;
1085
1085
  }
1086
- var VERSION = "0.60.2", INSTALL_CHANNEL = "npm";
1086
+ var VERSION = "0.62.0", INSTALL_CHANNEL = "npm";
1087
1087
 
1088
1088
  // src/debug/logger.ts
1089
1089
  import {
@@ -13800,7 +13800,7 @@ var init_conflicts = __esm(() => {
13800
13800
  });
13801
13801
 
13802
13802
  // src/telemetry/debug-id.ts
13803
- var BUNDLE_DEBUG_ID_PLACEHOLDER = "49fa5d82-a4a1-8b36-6475-6e2164756e21";
13803
+ var BUNDLE_DEBUG_ID_PLACEHOLDER = "da3b44a3-063b-fb2c-6475-6e2164756e21";
13804
13804
 
13805
13805
  // src/telemetry/telemetry.ts
13806
13806
  import { randomUUID as randomUUID2 } from "node:crypto";
@@ -60326,11 +60326,11 @@ dosu skill install | remove | update
60326
60326
  dosu telemetry status [--json]
60327
60327
  dosu telemetry enable | disable | reset
60328
60328
  dosu insights
60329
- dosu upgrade
60329
+ dosu upgrade [--auto on|off]
60330
60330
  dosu logs [--tail [n]] [--clear]
60331
60331
  \`\`\`
60332
60332
 
60333
- \`deployments\` selects the MCP deployment stored in local config; it is distinct from \`agents\`. \`insights\` opens an interactive visual report. \`logs --clear\` deletes the CLI log file.
60333
+ \`deployments\` selects the MCP deployment stored in local config; it is distinct from \`agents\`. \`insights\` opens an interactive visual report. \`logs --clear\` deletes the CLI log file. The CLI updates itself in the background by default; a \`[dosu:update] Installing ...\` notice on stderr needs no action. \`upgrade --auto off\` turns that off.
60334
60334
 
60335
60335
  ## Codebase audit
60336
60336
 
@@ -61719,6 +61719,7 @@ var ClaudeProvider = () => createJSONProvider({
61719
61719
  paths: ["~/.claude"],
61720
61720
  globalPath: "~/.claude.json",
61721
61721
  topKey: "mcpServers",
61722
+ buildServer: ({ url, headers }) => ({ type: "http", url, headers, alwaysLoad: true }),
61722
61723
  localConfigPath: (cwd) => join24(cwd, ".mcp.json")
61723
61724
  });
61724
61725
  var init_claude = __esm(() => {
@@ -62341,10 +62342,204 @@ var init_refresh = __esm(() => {
62341
62342
  init_providers();
62342
62343
  });
62343
62344
 
62344
- // src/version/update-check.ts
62345
- import { existsSync as existsSync23, mkdirSync as mkdirSync13, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "node:fs";
62345
+ // src/version/auto-update.ts
62346
+ import { spawn as spawn3 } from "node:child_process";
62347
+ import {
62348
+ closeSync as closeSync6,
62349
+ existsSync as existsSync23,
62350
+ mkdirSync as mkdirSync13,
62351
+ openSync as openSync6,
62352
+ readFileSync as readFileSync22,
62353
+ rmSync as rmSync7,
62354
+ statSync as statSync8,
62355
+ writeFileSync as writeFileSync14,
62356
+ writeSync
62357
+ } from "node:fs";
62358
+ import { homedir as homedir11 } from "node:os";
62346
62359
  import { join as join38 } from "node:path";
62360
+ function statePath() {
62361
+ return join38(getConfigDir(), STATE_FILENAME2);
62362
+ }
62363
+ function lockPath2() {
62364
+ return join38(getConfigDir(), LOCK_FILENAME2);
62365
+ }
62347
62366
  function isValidVersion(value) {
62367
+ return typeof value === "string" && VERSION_PATTERN.test(value);
62368
+ }
62369
+ function readState() {
62370
+ try {
62371
+ const raw = JSON.parse(readFileSync22(statePath(), "utf-8"));
62372
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw))
62373
+ return {};
62374
+ const data = raw;
62375
+ const state = {};
62376
+ if (data.disabled === true)
62377
+ state.disabled = true;
62378
+ const last = data.lastAttempt;
62379
+ if (last && isValidVersion(last.version) && typeof last.ok === "boolean" && typeof last.finishedAt === "number") {
62380
+ state.lastAttempt = { version: last.version, ok: last.ok, finishedAt: last.finishedAt };
62381
+ }
62382
+ return state;
62383
+ } catch {
62384
+ return {};
62385
+ }
62386
+ }
62387
+ function writeState(state) {
62388
+ try {
62389
+ const dir = getConfigDir();
62390
+ if (!existsSync23(dir))
62391
+ mkdirSync13(dir, { recursive: true, mode: 448 });
62392
+ writeFileSync14(statePath(), `${JSON.stringify(state, null, 2)}
62393
+ `, { mode: 384 });
62394
+ return true;
62395
+ } catch {
62396
+ return false;
62397
+ }
62398
+ }
62399
+ function isEnabledFlag(value) {
62400
+ if (value === undefined)
62401
+ return false;
62402
+ const normalized = value.trim().toLowerCase();
62403
+ return normalized !== "" && !["0", "false", "no", "off"].includes(normalized);
62404
+ }
62405
+ function autoUpdateDisabledReason(env = process.env) {
62406
+ if (isEnabledFlag(env[AUTO_UPDATE_ENV]))
62407
+ return "env";
62408
+ if (readState().disabled)
62409
+ return "settings";
62410
+ return;
62411
+ }
62412
+ function setAutoUpdateEnabled(enabled) {
62413
+ const state = readState();
62414
+ if (enabled)
62415
+ delete state.disabled;
62416
+ else
62417
+ state.disabled = true;
62418
+ return writeState(state);
62419
+ }
62420
+ function canAutoUpdate(channel, env) {
62421
+ if (env.NODE_ENV === "test" || env.CI || env.DOSU_DEV === "true")
62422
+ return false;
62423
+ if (!SUPPORTED_CHANNELS.has(channel) || isNpxInvocation(channel, env))
62424
+ return false;
62425
+ return autoUpdateDisabledReason(env) === undefined;
62426
+ }
62427
+ function backgroundInvocation(channel, entrypoint = process.argv[1], execPath = process.execPath) {
62428
+ const args = ["upgrade", "--background"];
62429
+ if (channel === "npm") {
62430
+ return entrypoint ? { command: execPath, args: [entrypoint, ...args] } : null;
62431
+ }
62432
+ if (channel === "homebrew")
62433
+ return { command: execPath, args };
62434
+ return null;
62435
+ }
62436
+ function lockIsFresh(now) {
62437
+ try {
62438
+ return now - statSync8(lockPath2()).mtimeMs < LOCK_STALE_MS;
62439
+ } catch {
62440
+ return false;
62441
+ }
62442
+ }
62443
+ function claimLock(version, now) {
62444
+ try {
62445
+ mkdirSync13(getConfigDir(), { recursive: true, mode: 448 });
62446
+ if (!lockIsFresh(now))
62447
+ rmSync7(lockPath2(), { force: true });
62448
+ const fd = openSync6(lockPath2(), "wx", 384);
62449
+ try {
62450
+ writeSync(fd, version);
62451
+ } finally {
62452
+ closeSync6(fd);
62453
+ }
62454
+ return "claimed";
62455
+ } catch (err) {
62456
+ return err.code === "EEXIST" ? "held" : "failed";
62457
+ }
62458
+ }
62459
+ function releaseLock() {
62460
+ try {
62461
+ rmSync7(lockPath2(), { force: true });
62462
+ } catch {}
62463
+ }
62464
+ function readLockVersion() {
62465
+ try {
62466
+ const version = readFileSync22(lockPath2(), "utf-8").trim();
62467
+ return isValidVersion(version) ? version : undefined;
62468
+ } catch {
62469
+ return;
62470
+ }
62471
+ }
62472
+ function startAutoUpdate(version, options = {}) {
62473
+ const channel = options.channel ?? INSTALL_CHANNEL;
62474
+ const env = options.env ?? process.env;
62475
+ const now = options.now ?? Date.now();
62476
+ try {
62477
+ if (!isValidVersion(version) || !canAutoUpdate(channel, env))
62478
+ return "unavailable";
62479
+ if (lockIsFresh(now))
62480
+ return "in_progress";
62481
+ const last = readState().lastAttempt;
62482
+ if (last?.version === version && now - last.finishedAt < RETRY_INTERVAL_MS) {
62483
+ return "unavailable";
62484
+ }
62485
+ const invocation = backgroundInvocation(channel, options.entrypoint, options.execPath);
62486
+ if (!invocation)
62487
+ return "unavailable";
62488
+ const claim = claimLock(version, now);
62489
+ if (claim !== "claimed")
62490
+ return claim === "held" ? "in_progress" : "unavailable";
62491
+ try {
62492
+ const child = spawn3(invocation.command, invocation.args, {
62493
+ cwd: homedir11(),
62494
+ detached: true,
62495
+ stdio: "ignore",
62496
+ windowsHide: true,
62497
+ env: { ...env, DOSU_TELEMETRY_DISABLED: "1" }
62498
+ });
62499
+ child.on("error", releaseLock);
62500
+ child.unref();
62501
+ } catch (err) {
62502
+ releaseLock();
62503
+ throw err;
62504
+ }
62505
+ logger.info("auto-update", `Started background update to ${version}`);
62506
+ return "started";
62507
+ } catch (err) {
62508
+ logger.error("auto-update", `Could not start background update: ${err}`);
62509
+ return "unavailable";
62510
+ }
62511
+ }
62512
+ function runBackgroundUpgrade(upgrade, now = Date.now) {
62513
+ const version = readLockVersion();
62514
+ let status = 1;
62515
+ try {
62516
+ status = upgrade();
62517
+ } catch (err) {
62518
+ logger.error("auto-update", `Background update threw: ${err}`);
62519
+ }
62520
+ if (version) {
62521
+ const state = readState();
62522
+ state.lastAttempt = { version, ok: status === 0, finishedAt: now() };
62523
+ writeState(state);
62524
+ }
62525
+ logger.info("auto-update", `Background update ${status === 0 ? "finished" : "failed"}`);
62526
+ releaseLock();
62527
+ return status;
62528
+ }
62529
+ var STATE_FILENAME2 = "auto-update.json", LOCK_FILENAME2 = "auto-update.lock", LOCK_STALE_MS, RETRY_INTERVAL_MS, SUPPORTED_CHANNELS, VERSION_PATTERN, AUTO_UPDATE_ENV = "DOSU_DISABLE_AUTOUPDATE";
62530
+ var init_auto_update = __esm(() => {
62531
+ init_config();
62532
+ init_logger();
62533
+ LOCK_STALE_MS = 15 * 60 * 1000;
62534
+ RETRY_INTERVAL_MS = 6 * 60 * 60 * 1000;
62535
+ SUPPORTED_CHANNELS = new Set(["npm", "homebrew"]);
62536
+ VERSION_PATTERN = /^[0-9A-Za-z.+-]{1,64}$/;
62537
+ });
62538
+
62539
+ // src/version/update-check.ts
62540
+ import { existsSync as existsSync24, mkdirSync as mkdirSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync15 } from "node:fs";
62541
+ import { join as join39 } from "node:path";
62542
+ function isValidVersion2(value) {
62348
62543
  return typeof value === "string" && SEMVER_PATTERN.test(value);
62349
62544
  }
62350
62545
  function stripPrerelease(version) {
@@ -62365,15 +62560,15 @@ function isNewerVersion(latest, current) {
62365
62560
  return false;
62366
62561
  }
62367
62562
  function getCachePath2() {
62368
- return join38(getConfigDir(), CACHE_FILENAME3);
62563
+ return join39(getConfigDir(), CACHE_FILENAME3);
62369
62564
  }
62370
62565
  function readCache() {
62371
62566
  try {
62372
62567
  const path = getCachePath2();
62373
- if (!existsSync23(path))
62568
+ if (!existsSync24(path))
62374
62569
  return null;
62375
- const data = JSON.parse(readFileSync22(path, "utf-8"));
62376
- if (typeof data.lastCheck === "number" && isValidVersion(data.latestVersion)) {
62570
+ const data = JSON.parse(readFileSync23(path, "utf-8"));
62571
+ if (typeof data.lastCheck === "number" && isValidVersion2(data.latestVersion)) {
62377
62572
  return data;
62378
62573
  }
62379
62574
  return null;
@@ -62384,10 +62579,10 @@ function readCache() {
62384
62579
  function writeCache(cache) {
62385
62580
  try {
62386
62581
  const dir = getConfigDir();
62387
- if (!existsSync23(dir)) {
62388
- mkdirSync13(dir, { recursive: true, mode: 448 });
62582
+ if (!existsSync24(dir)) {
62583
+ mkdirSync14(dir, { recursive: true, mode: 448 });
62389
62584
  }
62390
- writeFileSync14(getCachePath2(), JSON.stringify(cache), { mode: 384 });
62585
+ writeFileSync15(getCachePath2(), JSON.stringify(cache), { mode: 384 });
62391
62586
  } catch {}
62392
62587
  }
62393
62588
  async function fetchLatestVersion() {
@@ -62399,7 +62594,7 @@ async function fetchLatestVersion() {
62399
62594
  return null;
62400
62595
  const data = await resp.json();
62401
62596
  const latest = data.latest;
62402
- return isValidVersion(latest) ? latest : null;
62597
+ return isValidVersion2(latest) ? latest : null;
62403
62598
  } catch {
62404
62599
  return null;
62405
62600
  } finally {
@@ -62419,30 +62614,43 @@ function styleHint(hint) {
62419
62614
  const [, before, command, after] = match;
62420
62615
  return [before && import_picocolors30.default.dim(before), import_picocolors30.default.cyan(command), after && import_picocolors30.default.dim(after)].filter(Boolean).join("");
62421
62616
  }
62422
- function buildUpdateNotice(current, latest, channel, interactive, npx = false, width = process.stderr.columns ?? 80) {
62423
- const hint = buildUpdateHint(channel, npx);
62424
- if (interactive) {
62425
- const content = [
62426
- `Update available: ${import_picocolors30.default.dim(current)} ${import_picocolors30.default.dim("→")} ${import_picocolors30.default.bold(brand(latest))}`,
62427
- styleHint(hint)
62428
- ];
62429
- const innerWidth = Math.max(...content.map(visibleWidth2)) + BOX_PADDING * 2;
62430
- const framed = (line) => {
62431
- const pad = innerWidth - visibleWidth2(line);
62432
- const left = Math.floor(pad / 2);
62433
- return `${import_picocolors30.default.yellow("│")}${" ".repeat(left)}${line}${" ".repeat(pad - left)}${import_picocolors30.default.yellow("│")}`;
62434
- };
62435
- const box = [
62436
- import_picocolors30.default.yellow(`╭${"─".repeat(innerWidth)}╮`),
62437
- framed(""),
62438
- ...content.map(framed),
62439
- framed(""),
62440
- import_picocolors30.default.yellow(`╰${"─".repeat(innerWidth)}╯`)
62441
- ];
62442
- return `
62617
+ function framedNotice(content, width) {
62618
+ const innerWidth = Math.max(...content.map(visibleWidth2)) + BOX_PADDING * 2;
62619
+ const framed = (line) => {
62620
+ const pad = innerWidth - visibleWidth2(line);
62621
+ const left = Math.floor(pad / 2);
62622
+ return `${import_picocolors30.default.yellow("│")}${" ".repeat(left)}${line}${" ".repeat(pad - left)}${import_picocolors30.default.yellow("│")}`;
62623
+ };
62624
+ const box = [
62625
+ import_picocolors30.default.yellow(`╭${"─".repeat(innerWidth)}╮`),
62626
+ framed(""),
62627
+ ...content.map(framed),
62628
+ framed(""),
62629
+ import_picocolors30.default.yellow(`╰${"─".repeat(innerWidth)}╯`)
62630
+ ];
62631
+ return `
62443
62632
  ${centerBlock(box, width).join(`
62444
62633
  `)}
62445
62634
  `;
62635
+ }
62636
+ function versionArrow(current, latest) {
62637
+ return `${import_picocolors30.default.dim(current)} ${import_picocolors30.default.dim("→")} ${import_picocolors30.default.bold(brand(latest))}`;
62638
+ }
62639
+ function buildAutoUpdateNotice(current, latest, interactive, width = process.stderr.columns ?? 80) {
62640
+ if (interactive) {
62641
+ return framedNotice([
62642
+ `Updating Dosu: ${versionArrow(current, latest)}`,
62643
+ import_picocolors30.default.dim("Installing in the background; your next command uses it")
62644
+ ], width);
62645
+ }
62646
+ return `
62647
+ [dosu:update] Installing Dosu ${latest} in the background (running ${current}). ` + `The next Dosu command uses it; no action needed.
62648
+ `;
62649
+ }
62650
+ function buildUpdateNotice(current, latest, channel, interactive, npx = false, width = process.stderr.columns ?? 80) {
62651
+ const hint = buildUpdateHint(channel, npx);
62652
+ if (interactive) {
62653
+ return framedNotice([`Update available: ${versionArrow(current, latest)}`, styleHint(hint)], width);
62446
62654
  }
62447
62655
  const agentAction = hint[0].toLowerCase() + hint.slice(1);
62448
62656
  const verifyCommand = npx ? "npx -y @dosu/cli@latest --version" : "dosu --version";
@@ -62455,8 +62663,12 @@ function getAvailableUpdate() {
62455
62663
  const cache = readCache();
62456
62664
  return cache && isNewerVersion(cache.latestVersion, VERSION) ? cache.latestVersion : null;
62457
62665
  }
62458
- function displayNotice(current, latest) {
62459
- console.error(buildUpdateNotice(current, latest, INSTALL_CHANNEL, process.stderr.isTTY === true, isNpxInvocation()));
62666
+ function handleNewerVersion(latest, notify) {
62667
+ const autoUpdate = startAutoUpdate(latest);
62668
+ if (!notify)
62669
+ return;
62670
+ const interactive = process.stderr.isTTY === true;
62671
+ console.error(autoUpdate === "unavailable" ? buildUpdateNotice(VERSION, latest, INSTALL_CHANNEL, interactive, isNpxInvocation()) : buildAutoUpdateNotice(VERSION, latest, interactive));
62460
62672
  }
62461
62673
  async function checkForUpdates(options = {}) {
62462
62674
  const notify = options.notify ?? true;
@@ -62464,8 +62676,8 @@ async function checkForUpdates(options = {}) {
62464
62676
  const cache = readCache();
62465
62677
  const isStale = !cache || Date.now() - cache.lastCheck > CHECK_INTERVAL_MS2;
62466
62678
  if (!isStale) {
62467
- if (notify && isNewerVersion(cache.latestVersion, VERSION)) {
62468
- displayNotice(VERSION, cache.latestVersion);
62679
+ if (isNewerVersion(cache.latestVersion, VERSION)) {
62680
+ handleNewerVersion(cache.latestVersion, notify);
62469
62681
  }
62470
62682
  return;
62471
62683
  }
@@ -62478,8 +62690,8 @@ async function checkForUpdates(options = {}) {
62478
62690
  if (latest) {
62479
62691
  logger.debug("update-check", `Cached latest version: ${latest}`);
62480
62692
  }
62481
- if (notify && isNewerVersion(latestKnownVersion, VERSION)) {
62482
- displayNotice(VERSION, latestKnownVersion);
62693
+ if (isNewerVersion(latestKnownVersion, VERSION)) {
62694
+ handleNewerVersion(latestKnownVersion, notify);
62483
62695
  }
62484
62696
  } catch (err) {
62485
62697
  logger.error("update-check", `Update check failed: ${err}`);
@@ -62491,14 +62703,15 @@ var init_update_check = __esm(() => {
62491
62703
  init_logger();
62492
62704
  init_styles();
62493
62705
  init_layout();
62706
+ init_auto_update();
62494
62707
  import_picocolors30 = __toESM(require_picocolors(), 1);
62495
62708
  CHECK_INTERVAL_MS2 = 6 * 60 * 60 * 1000;
62496
62709
  SEMVER_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
62497
62710
  });
62498
62711
 
62499
62712
  // src/version/mcp-refresh-check.ts
62500
- import { existsSync as existsSync24, mkdirSync as mkdirSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync15 } from "node:fs";
62501
- import { join as join39 } from "node:path";
62713
+ import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "node:fs";
62714
+ import { join as join40 } from "node:path";
62502
62715
  function needsMcpRefresh(previous, current) {
62503
62716
  if (previous === null)
62504
62717
  return true;
@@ -62508,14 +62721,14 @@ function needsMcpRefresh(previous, current) {
62508
62721
  return MCP_FORMAT_CHANGES.some((change) => isNewerVersion(change, older) && !isNewerVersion(change, newer));
62509
62722
  }
62510
62723
  function getCachePath3() {
62511
- return join39(getConfigDir(), CACHE_FILENAME4);
62724
+ return join40(getConfigDir(), CACHE_FILENAME4);
62512
62725
  }
62513
62726
  function readMcpRefreshCache() {
62514
62727
  try {
62515
62728
  const path = getCachePath3();
62516
- if (!existsSync24(path))
62729
+ if (!existsSync25(path))
62517
62730
  return null;
62518
- const data = JSON.parse(readFileSync23(path, "utf-8"));
62731
+ const data = JSON.parse(readFileSync24(path, "utf-8"));
62519
62732
  if (typeof data?.version === "string")
62520
62733
  return { version: data.version };
62521
62734
  return null;
@@ -62526,10 +62739,10 @@ function readMcpRefreshCache() {
62526
62739
  function writeMcpRefreshCache(cache) {
62527
62740
  try {
62528
62741
  const dir = getConfigDir();
62529
- if (!existsSync24(dir)) {
62530
- mkdirSync14(dir, { recursive: true, mode: 448 });
62742
+ if (!existsSync25(dir)) {
62743
+ mkdirSync15(dir, { recursive: true, mode: 448 });
62531
62744
  }
62532
- writeFileSync15(getCachePath3(), JSON.stringify(cache), { mode: 384 });
62745
+ writeFileSync16(getCachePath3(), JSON.stringify(cache), { mode: 384 });
62533
62746
  } catch {}
62534
62747
  }
62535
62748
  function canRefreshMcp(cfg) {
@@ -62538,7 +62751,7 @@ function canRefreshMcp(cfg) {
62538
62751
  return false;
62539
62752
  return cfg.mode === MODE_OSS || Boolean(target.deployment_id);
62540
62753
  }
62541
- function displayNotice2(names) {
62754
+ function displayNotice(names) {
62542
62755
  console.error(`
62543
62756
  ${import_picocolors31.default.green(`✓ Dosu ${VERSION}: refreshed MCP config for ${names.join(", ")}`)}
62544
62757
  ` + `${import_picocolors31.default.dim(` Run ${import_picocolors31.default.cyan('"dosu setup"')} to also update hooks and rules, then restart your AI agents.`)}
@@ -62563,7 +62776,7 @@ function checkForMcpRefresh(options = {}) {
62563
62776
  writeMcpRefreshCache({ version: VERSION });
62564
62777
  logger.info("mcp-refresh", `Version ${VERSION}: refreshed ${result.updated.length}, failed ${result.failed.length}`);
62565
62778
  if (notify && result.updated.length > 0) {
62566
- displayNotice2(result.updated.map((provider) => provider.name()));
62779
+ displayNotice(result.updated.map((provider) => provider.name()));
62567
62780
  }
62568
62781
  } catch (err) {
62569
62782
  logger.error("mcp-refresh", `MCP refresh check failed: ${err}`);
@@ -62576,11 +62789,14 @@ var init_mcp_refresh_check = __esm(() => {
62576
62789
  init_refresh();
62577
62790
  init_update_check();
62578
62791
  import_picocolors31 = __toESM(require_picocolors(), 1);
62579
- MCP_FORMAT_CHANGES = ["0.53.0"];
62792
+ MCP_FORMAT_CHANGES = [
62793
+ "0.53.0",
62794
+ "0.62.0"
62795
+ ];
62580
62796
  });
62581
62797
 
62582
62798
  // src/version/skill-update-check.ts
62583
- function displayNotice3() {
62799
+ function displayNotice2() {
62584
62800
  console.error(`
62585
62801
  ${import_picocolors32.default.green(`✓ Dosu ${VERSION}: refreshed the bundled agent skills`)}
62586
62802
  ` + `${import_picocolors32.default.dim(" Restart your AI agents to pick up the new skill content.")}
@@ -62599,7 +62815,7 @@ function checkForSkillUpdates(options = {}) {
62599
62815
  }
62600
62816
  logger.info("skill-update-check", `Refreshed skills from ${state.version} to ${VERSION}`);
62601
62817
  if (notify && result.version)
62602
- displayNotice3();
62818
+ displayNotice2();
62603
62819
  } catch (err) {
62604
62820
  logger.error("skill-update-check", `Skill update check failed: ${err}`);
62605
62821
  }
@@ -62639,11 +62855,11 @@ var init_errors3 = __esm(() => {
62639
62855
  var MCP_PROVIDER_SLUG2 = "dosu_mcp";
62640
62856
 
62641
62857
  // src/debug/follow.ts
62642
- import { closeSync as closeSync6, openSync as openSync6, readSync as readSync5, statSync as statSync8 } from "node:fs";
62858
+ import { closeSync as closeSync7, openSync as openSync7, readSync as readSync5, statSync as statSync9 } from "node:fs";
62643
62859
  function createLogFollower(path, emit) {
62644
62860
  const sizeOf = () => {
62645
62861
  try {
62646
- return statSync8(path).size;
62862
+ return statSync9(path).size;
62647
62863
  } catch {
62648
62864
  return 0;
62649
62865
  }
@@ -62657,7 +62873,7 @@ function createLogFollower(path, emit) {
62657
62873
  if (size === offset)
62658
62874
  return;
62659
62875
  try {
62660
- const fd = openSync6(path, "r");
62876
+ const fd = openSync7(path, "r");
62661
62877
  try {
62662
62878
  const buf = Buffer.alloc(size - offset);
62663
62879
  const read = readSync5(fd, buf, 0, buf.length, offset);
@@ -62665,7 +62881,7 @@ function createLogFollower(path, emit) {
62665
62881
  if (read > 0)
62666
62882
  emit(buf.toString("utf-8", 0, read));
62667
62883
  } finally {
62668
- closeSync6(fd);
62884
+ closeSync7(fd);
62669
62885
  }
62670
62886
  } catch {}
62671
62887
  }
@@ -62674,15 +62890,15 @@ function createLogFollower(path, emit) {
62674
62890
  var init_follow = () => {};
62675
62891
 
62676
62892
  // src/sessions/session-title.ts
62677
- import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, renameSync as renameSync6, statSync as statSync9, writeFileSync as writeFileSync16 } from "node:fs";
62678
- import { homedir as homedir11 } from "node:os";
62679
- import { join as join40 } from "node:path";
62893
+ import { existsSync as existsSync26, mkdirSync as mkdirSync16, readFileSync as readFileSync25, renameSync as renameSync6, statSync as statSync10, writeFileSync as writeFileSync17 } from "node:fs";
62894
+ import { homedir as homedir12 } from "node:os";
62895
+ import { join as join41 } from "node:path";
62680
62896
  function cachePath2(configDir) {
62681
- return join40(configDir, CACHE_FILENAME5);
62897
+ return join41(configDir, CACHE_FILENAME5);
62682
62898
  }
62683
62899
  function loadCacheFile2(configDir) {
62684
62900
  try {
62685
- const raw = JSON.parse(readFileSync24(cachePath2(configDir), "utf-8"));
62901
+ const raw = JSON.parse(readFileSync25(cachePath2(configDir), "utf-8"));
62686
62902
  if (raw.schema_version !== CACHE_SCHEMA_VERSION2 || typeof raw.entries !== "object")
62687
62903
  return {};
62688
62904
  return raw.entries;
@@ -62692,12 +62908,12 @@ function loadCacheFile2(configDir) {
62692
62908
  }
62693
62909
  function saveCacheFile2(configDir, entries) {
62694
62910
  try {
62695
- if (!existsSync25(configDir))
62696
- mkdirSync15(configDir, { recursive: true, mode: 448 });
62911
+ if (!existsSync26(configDir))
62912
+ mkdirSync16(configDir, { recursive: true, mode: 448 });
62697
62913
  const path = cachePath2(configDir);
62698
62914
  const tmp = `${path}.${process.pid}.tmp`;
62699
62915
  const file = { schema_version: CACHE_SCHEMA_VERSION2, entries };
62700
- writeFileSync16(tmp, JSON.stringify(file), { mode: 384 });
62916
+ writeFileSync17(tmp, JSON.stringify(file), { mode: 384 });
62701
62917
  renameSync6(tmp, path);
62702
62918
  } catch {}
62703
62919
  }
@@ -62730,15 +62946,15 @@ function claudeSummaryFromHead(text) {
62730
62946
  }
62731
62947
  return null;
62732
62948
  }
62733
- function reconstructSession(harness, id, slug, home = homedir11(), exists = existsSync25) {
62949
+ function reconstructSession(harness, id, slug, home = homedir12(), exists = existsSync26) {
62734
62950
  if (!slug)
62735
62951
  return null;
62736
62952
  const candidates = [];
62737
62953
  if (harness === "claude") {
62738
- candidates.push(join40(home, ".claude", "projects", slug, `${id}.jsonl`));
62954
+ candidates.push(join41(home, ".claude", "projects", slug, `${id}.jsonl`));
62739
62955
  } else if (harness === "cursor") {
62740
- const project = join40(home, ".cursor", "projects", slug);
62741
- candidates.push(join40(project, "agent-transcripts", id, `${id}.jsonl`), join40(project, "agent-transcripts", `${id}.jsonl`));
62956
+ const project = join41(home, ".cursor", "projects", slug);
62957
+ candidates.push(join41(project, "agent-transcripts", id, `${id}.jsonl`), join41(project, "agent-transcripts", `${id}.jsonl`));
62742
62958
  } else {
62743
62959
  return null;
62744
62960
  }
@@ -62750,14 +62966,14 @@ function reconstructSession(harness, id, slug, home = homedir11(), exists = exis
62750
62966
  }
62751
62967
  function readHead2(path) {
62752
62968
  try {
62753
- return readFileSync24(path, "utf-8").slice(0, 128 * 1024);
62969
+ return readFileSync25(path, "utf-8").slice(0, 128 * 1024);
62754
62970
  } catch {
62755
62971
  return null;
62756
62972
  }
62757
62973
  }
62758
62974
  function fileMtime2(path) {
62759
62975
  try {
62760
- return statSync9(path).mtime.toISOString();
62976
+ return statSync10(path).mtime.toISOString();
62761
62977
  } catch {
62762
62978
  return "";
62763
62979
  }
@@ -62830,7 +63046,7 @@ var init_alt_screen = __esm(() => {
62830
63046
  });
62831
63047
 
62832
63048
  // src/tui/activity-view.ts
62833
- import { existsSync as existsSync26, readFileSync as readFileSync25 } from "node:fs";
63049
+ import { existsSync as existsSync27, readFileSync as readFileSync26 } from "node:fs";
62834
63050
  import { basename as basename5 } from "node:path";
62835
63051
  function reduceActivityViewKey(key) {
62836
63052
  if (key === "q" || key === ESC7 || key === CTRL_C4)
@@ -63151,7 +63367,7 @@ function createRowNamer() {
63151
63367
  names.titles[key] = t;
63152
63368
  };
63153
63369
  for (const s of [...backlog.queued, ...backlog.open]) {
63154
- if (!existsSync26(s.path))
63370
+ if (!existsSync27(s.path))
63155
63371
  continue;
63156
63372
  const key = `${s.harness}/${s.id}`;
63157
63373
  const dir = dirs.resolve(s);
@@ -63188,7 +63404,7 @@ function createRowNamer() {
63188
63404
  }
63189
63405
  function defaultReadLog2() {
63190
63406
  try {
63191
- return readFileSync25(logger.getLogPath(), "utf-8");
63407
+ return readFileSync26(logger.getLogPath(), "utf-8");
63192
63408
  } catch {
63193
63409
  return "";
63194
63410
  }
@@ -63405,14 +63621,14 @@ var init_activity_view = __esm(() => {
63405
63621
  });
63406
63622
 
63407
63623
  // src/rules/installer.ts
63408
- import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync26, unlinkSync as unlinkSync5, writeFileSync as writeFileSync17 } from "node:fs";
63409
- import { homedir as homedir12 } from "node:os";
63410
- import { dirname as dirname12, join as join41 } from "node:path";
63624
+ import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync27, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18 } from "node:fs";
63625
+ import { homedir as homedir13 } from "node:os";
63626
+ import { dirname as dirname12, join as join42 } from "node:path";
63411
63627
  function claudeConfigDir4() {
63412
- return process.env.CLAUDE_CONFIG_DIR || join41(homedir12(), ".claude");
63628
+ return process.env.CLAUDE_CONFIG_DIR || join42(homedir13(), ".claude");
63413
63629
  }
63414
63630
  function codexHome4() {
63415
- return process.env.CODEX_HOME || join41(homedir12(), ".codex");
63631
+ return process.env.CODEX_HOME || join42(homedir13(), ".codex");
63416
63632
  }
63417
63633
  function isRuleAgent(agent) {
63418
63634
  return Object.hasOwn(RULE_TARGETS, agent);
@@ -63438,17 +63654,17 @@ async function fetchDosuRule(fetchImpl = globalThis.fetch) {
63438
63654
  return normalizeRule(FALLBACK_DOSU_RULE);
63439
63655
  }
63440
63656
  function ensureParent(path) {
63441
- mkdirSync16(dirname12(path), { recursive: true });
63657
+ mkdirSync17(dirname12(path), { recursive: true });
63442
63658
  }
63443
63659
  function writeIfChanged(path, content) {
63444
- if (!existsSync27(path)) {
63660
+ if (!existsSync28(path)) {
63445
63661
  ensureParent(path);
63446
- writeFileSync17(path, content, "utf-8");
63662
+ writeFileSync18(path, content, "utf-8");
63447
63663
  return "created";
63448
63664
  }
63449
- if (readFileSync26(path, "utf-8") === content)
63665
+ if (readFileSync27(path, "utf-8") === content)
63450
63666
  return "unchanged";
63451
- writeFileSync17(path, content, "utf-8");
63667
+ writeFileSync18(path, content, "utf-8");
63452
63668
  return "updated";
63453
63669
  }
63454
63670
  function findSection(content) {
@@ -63474,14 +63690,14 @@ function buildSection(content, lineEnding = `
63474
63690
  return `${DOSU_RULE_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_RULE_SECTION_END}`;
63475
63691
  }
63476
63692
  function upsertSection(path, content) {
63477
- if (!existsSync27(path)) {
63693
+ if (!existsSync28(path)) {
63478
63694
  const section = buildSection(content);
63479
63695
  ensureParent(path);
63480
- writeFileSync17(path, `${section}
63696
+ writeFileSync18(path, `${section}
63481
63697
  `, "utf-8");
63482
63698
  return "created";
63483
63699
  }
63484
- const existing = readFileSync26(path, "utf-8");
63700
+ const existing = readFileSync27(path, "utf-8");
63485
63701
  const lineEnding = lineEndingFor(existing);
63486
63702
  const section = buildSection(content, lineEnding);
63487
63703
  const location = findSection(existing);
@@ -63494,7 +63710,7 @@ function upsertSection(path, content) {
63494
63710
  }
63495
63711
  if (next === existing)
63496
63712
  return "unchanged";
63497
- writeFileSync17(path, next, "utf-8");
63713
+ writeFileSync18(path, next, "utf-8");
63498
63714
  return "updated";
63499
63715
  }
63500
63716
  function installRuleForAgent(agent, content) {
@@ -63511,13 +63727,13 @@ function removeRuleForAgent(agent) {
63511
63727
  return null;
63512
63728
  const target = RULE_TARGETS[agent];
63513
63729
  const path = target.path();
63514
- if (!existsSync27(path))
63730
+ if (!existsSync28(path))
63515
63731
  return { agent, path, action: "not_found" };
63516
63732
  if (target.kind === "file") {
63517
63733
  unlinkSync5(path);
63518
63734
  return { agent, path, action: "removed" };
63519
63735
  }
63520
- const existing = readFileSync26(path, "utf-8");
63736
+ const existing = readFileSync27(path, "utf-8");
63521
63737
  const lineEnding = lineEndingFor(existing);
63522
63738
  const location = findSection(existing);
63523
63739
  if (!location)
@@ -63526,7 +63742,7 @@ function removeRuleForAgent(agent) {
63526
63742
  if (!next) {
63527
63743
  unlinkSync5(path);
63528
63744
  } else {
63529
- writeFileSync17(path, `${next}${lineEnding}`, "utf-8");
63745
+ writeFileSync18(path, `${next}${lineEnding}`, "utf-8");
63530
63746
  }
63531
63747
  return { agent, path, action: "removed" };
63532
63748
  }
@@ -63554,36 +63770,36 @@ var init_installer = __esm(() => {
63554
63770
  RULE_TARGETS = {
63555
63771
  claude: {
63556
63772
  kind: "file",
63557
- path: () => join41(claudeConfigDir4(), "rules", "dosu.md")
63773
+ path: () => join42(claudeConfigDir4(), "rules", "dosu.md")
63558
63774
  },
63559
63775
  cursor: {
63560
63776
  kind: "file",
63561
- path: () => join41(homedir12(), ".cursor", "rules", "dosu.mdc"),
63777
+ path: () => join42(homedir13(), ".cursor", "rules", "dosu.mdc"),
63562
63778
  cursorFrontmatter: true
63563
63779
  },
63564
63780
  codex: {
63565
63781
  kind: "section",
63566
- path: () => join41(codexHome4(), "AGENTS.md")
63782
+ path: () => join42(codexHome4(), "AGENTS.md")
63567
63783
  },
63568
63784
  opencode: {
63569
63785
  kind: "section",
63570
- path: () => join41(homedir12(), ".config", "opencode", "AGENTS.md")
63786
+ path: () => join42(homedir13(), ".config", "opencode", "AGENTS.md")
63571
63787
  },
63572
63788
  gemini: {
63573
63789
  kind: "section",
63574
- path: () => join41(homedir12(), ".gemini", "GEMINI.md")
63790
+ path: () => join42(homedir13(), ".gemini", "GEMINI.md")
63575
63791
  },
63576
63792
  antigravity: {
63577
63793
  kind: "section",
63578
- path: () => join41(homedir12(), ".gemini", "GEMINI.md")
63794
+ path: () => join42(homedir13(), ".gemini", "GEMINI.md")
63579
63795
  }
63580
63796
  };
63581
63797
  });
63582
63798
 
63583
63799
  // src/setup/agents-md-step.ts
63584
63800
  import { execSync as execSync2 } from "node:child_process";
63585
- import { existsSync as existsSync28, readFileSync as readFileSync27, writeFileSync as writeFileSync18 } from "node:fs";
63586
- import { join as join42 } from "node:path";
63801
+ import { existsSync as existsSync29, readFileSync as readFileSync28, writeFileSync as writeFileSync19 } from "node:fs";
63802
+ import { join as join43 } from "node:path";
63587
63803
  function inGitWorkTree(cwd = process.cwd()) {
63588
63804
  try {
63589
63805
  const stdout = execSync2("git rev-parse --is-inside-work-tree", {
@@ -63597,10 +63813,10 @@ function inGitWorkTree(cwd = process.cwd()) {
63597
63813
  }
63598
63814
  function dosuAgentsSectionState(cwd = process.cwd()) {
63599
63815
  try {
63600
- const path = join42(cwd, "AGENTS.md");
63601
- if (!existsSync28(path))
63816
+ const path = join43(cwd, "AGENTS.md");
63817
+ if (!existsSync29(path))
63602
63818
  return "missing";
63603
- const content = readFileSync27(path, "utf-8");
63819
+ const content = readFileSync28(path, "utf-8");
63604
63820
  const startMatch = content.match(SECTION_START_RE);
63605
63821
  if (!startMatch || !content.includes(DOSU_SECTION_END))
63606
63822
  return "missing";
@@ -63635,14 +63851,14 @@ function findSection2(content) {
63635
63851
  return { start, end };
63636
63852
  }
63637
63853
  function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
63638
- const path = join42(cwd, "AGENTS.md");
63639
- if (!existsSync28(path)) {
63854
+ const path = join43(cwd, "AGENTS.md");
63855
+ if (!existsSync29(path)) {
63640
63856
  const section = buildDosuAgentsSection(content);
63641
- writeFileSync18(path, `${section}
63857
+ writeFileSync19(path, `${section}
63642
63858
  `);
63643
63859
  return { path, action: "created" };
63644
63860
  }
63645
- const existing = readFileSync27(path, "utf-8");
63861
+ const existing = readFileSync28(path, "utf-8");
63646
63862
  const lineEnding = lineEndingFor2(existing);
63647
63863
  const section = renderDosuAgentsSection(content, lineEnding);
63648
63864
  const location = findSection2(existing);
@@ -63654,7 +63870,7 @@ function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RU
63654
63870
  }
63655
63871
  if (next === existing)
63656
63872
  return { path, action: "unchanged" };
63657
- writeFileSync18(path, next);
63873
+ writeFileSync19(path, next);
63658
63874
  return { path, action: "updated" };
63659
63875
  }
63660
63876
  async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
@@ -65366,7 +65582,7 @@ var init_flow2 = __esm(() => {
65366
65582
  // src/commands/upgrade.ts
65367
65583
  import { spawnSync } from "node:child_process";
65368
65584
  import { realpathSync as realpathSync2 } from "node:fs";
65369
- import { homedir as homedir13 } from "node:os";
65585
+ import { homedir as homedir14 } from "node:os";
65370
65586
  import { posix, win32 as win322 } from "node:path";
65371
65587
  function isAbsoluteCommandProcessor(value) {
65372
65588
  return Boolean(value && win322.isAbsolute(value) && win322.basename(value).toLowerCase() === "cmd.exe");
@@ -65420,7 +65636,7 @@ function packageRoots(manager, platform, comSpec, env, cwd) {
65420
65636
  manager === "npm" ? path.join(lines[0], "@dosu", "cli") : path.join(lines[0], "node_modules", "@dosu", "cli")
65421
65637
  ];
65422
65638
  }
65423
- function owningPackageManager(entrypoint, platform, comSpec, env = process.env, cwd = homedir13()) {
65639
+ function owningPackageManager(entrypoint, platform, comSpec, env = process.env, cwd = homedir14()) {
65424
65640
  const path = platform === "win32" ? win322 : posix;
65425
65641
  if (!entrypoint || !path.isAbsolute(entrypoint))
65426
65642
  return null;
@@ -65473,7 +65689,7 @@ Or install Dosu globally with your package manager:`);
65473
65689
  function runUpgrade(channel = INSTALL_CHANNEL, options = {}) {
65474
65690
  const platform = options.platform ?? process.platform;
65475
65691
  const env = options.env ?? process.env;
65476
- const cwd = options.cwd ?? homedir13();
65692
+ const cwd = options.cwd ?? homedir14();
65477
65693
  let manager = null;
65478
65694
  if (channel === "npm") {
65479
65695
  if (isNpxInvocation(channel, env)) {
@@ -65540,7 +65756,7 @@ function finishWithNewBinary(channel, options) {
65540
65756
  return;
65541
65757
  }
65542
65758
  const result = spawnSync(invocation.command, invocation.args, {
65543
- cwd: options.cwd ?? homedir13(),
65759
+ cwd: options.cwd ?? homedir14(),
65544
65760
  shell: false,
65545
65761
  stdio: "inherit"
65546
65762
  });
@@ -65590,9 +65806,37 @@ Refreshing agent MCP configs with the new version...`);
65590
65806
  console.error(SETUP_FALLBACK);
65591
65807
  return 0;
65592
65808
  }
65809
+ function setAutoUpdate(value) {
65810
+ const normalized = value.trim().toLowerCase();
65811
+ if (normalized !== "on" && normalized !== "off") {
65812
+ console.error(`Invalid --auto value '${value}' (expected 'on' or 'off').`);
65813
+ return 2;
65814
+ }
65815
+ if (!setAutoUpdateEnabled(normalized === "on")) {
65816
+ console.error("Could not save the auto-update setting.");
65817
+ return 1;
65818
+ }
65819
+ if (normalized === "off") {
65820
+ console.log('Automatic updates are off. Run "dosu upgrade" to update by hand.');
65821
+ } else if (autoUpdateDisabledReason() === "env") {
65822
+ console.log(`Automatic updates are on, but ${AUTO_UPDATE_ENV} still disables them here.`);
65823
+ } else {
65824
+ console.log("Automatic updates are on.");
65825
+ }
65826
+ return 0;
65827
+ }
65593
65828
  function upgradeCommand() {
65594
- return new Command("upgrade").description("Update Dosu to the latest version, re-running setup when the update changes agent config").addOption(new Option("--finish <from>").hideHelp()).action(async (opts) => {
65595
- const status = opts.finish !== undefined ? await finishUpgrade(opts.finish) : await completeUpgrade();
65829
+ return new Command("upgrade").description("Update Dosu to the latest version, re-running setup when the update changes agent config").option("--auto <on|off>", "Turn automatic background updates on or off").addOption(new Option("--background").hideHelp()).addOption(new Option("--finish <from>").hideHelp()).action(async (opts) => {
65830
+ let status;
65831
+ if (opts.auto !== undefined) {
65832
+ status = setAutoUpdate(opts.auto);
65833
+ } else if (opts.background) {
65834
+ status = runBackgroundUpgrade(() => runUpgrade());
65835
+ } else if (opts.finish !== undefined) {
65836
+ status = await finishUpgrade(opts.finish);
65837
+ } else {
65838
+ status = await completeUpgrade();
65839
+ }
65596
65840
  if (status !== 0)
65597
65841
  process.exitCode = status;
65598
65842
  });
@@ -65602,6 +65846,7 @@ var init_upgrade = __esm(() => {
65602
65846
  init_commander();
65603
65847
  init_config();
65604
65848
  init_refresh();
65849
+ init_auto_update();
65605
65850
  init_mcp_refresh_check();
65606
65851
  init_skill_update_check();
65607
65852
  import_picocolors35 = __toESM(require_picocolors(), 1);
@@ -66309,7 +66554,7 @@ var init_pages_view = __esm(() => {
66309
66554
  });
66310
66555
 
66311
66556
  // src/tui/tui.ts
66312
- import { homedir as homedir14 } from "node:os";
66557
+ import { homedir as homedir15 } from "node:os";
66313
66558
  import { basename as basename6 } from "node:path";
66314
66559
  async function probeSession(cfg) {
66315
66560
  if (!isAuthenticated(cfg) || !isTokenExpired(cfg))
@@ -66574,7 +66819,7 @@ async function runSettings(cfg) {
66574
66819
  }
66575
66820
  }
66576
66821
  function displayDir(dir) {
66577
- const home = homedir14();
66822
+ const home = homedir15();
66578
66823
  return dir === home ? "~" : dir.startsWith(`${home}/`) ? `~${dir.slice(home.length)}` : dir;
66579
66824
  }
66580
66825
  function discoverProjectDirs() {
@@ -67284,7 +67529,7 @@ var init_flow3 = __esm(() => {
67284
67529
  });
67285
67530
 
67286
67531
  // src/cli/cli.ts
67287
- import { readFileSync as readFileSync28, unlinkSync as unlinkSync6 } from "node:fs";
67532
+ import { readFileSync as readFileSync29, unlinkSync as unlinkSync6 } from "node:fs";
67288
67533
  function shouldRunBackgroundChecks(actionName) {
67289
67534
  return actionName !== "upgrade";
67290
67535
  }
@@ -67730,7 +67975,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
67730
67975
  }
67731
67976
  if (opts.follow) {
67732
67977
  try {
67733
- const lines = readFileSync28(logPath, "utf-8").split(`
67978
+ const lines = readFileSync29(logPath, "utf-8").split(`
67734
67979
  `);
67735
67980
  if (lines.at(-1) === "")
67736
67981
  lines.pop();
@@ -67746,7 +67991,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
67746
67991
  if (opts.tail !== undefined) {
67747
67992
  const n = typeof opts.tail === "string" ? parseInt(opts.tail, 10) || 50 : 50;
67748
67993
  try {
67749
- const content = readFileSync28(logPath, "utf-8");
67994
+ const content = readFileSync29(logPath, "utf-8");
67750
67995
  const lines = content.split(`
67751
67996
  `);
67752
67997
  console.log(lines.slice(-n).join(`
@@ -67872,4 +68117,4 @@ main().catch((err) => {
67872
68117
  process.exit(1);
67873
68118
  });
67874
68119
 
67875
- //# debugId=49fa5d82-a4a1-8b36-6475-6e2164756e21
68120
+ //# debugId=da3b44a3-063b-fb2c-6475-6e2164756e21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.60.2",
3
+ "version": "0.62.0",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",