sidekick-agent-hub 0.17.0 → 0.17.1

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/dist/sidekick-cli.mjs +118 -65
  2. package/package.json +1 -1
@@ -4507,6 +4507,8 @@ var require_codexProfiles = __commonJS({
4507
4507
  };
4508
4508
  }();
4509
4509
  Object.defineProperty(exports, "__esModule", { value: true });
4510
+ exports.getSystemCodexHome = getSystemCodexHome;
4511
+ exports.getCodexMonitoringHomes = getCodexMonitoringHomes;
4510
4512
  exports.getCodexProfilesDir = getCodexProfilesDir;
4511
4513
  exports.getCodexProfileHome = getCodexProfileHome;
4512
4514
  exports.listCodexAccounts = listCodexAccounts2;
@@ -4523,8 +4525,39 @@ var require_codexProfiles = __commonJS({
4523
4525
  var child_process_1 = __require("child_process");
4524
4526
  var crypto_1 = __require("crypto");
4525
4527
  var accountRegistry_1 = require_accountRegistry();
4528
+ function getDefaultSystemCodexHome() {
4529
+ return path7.join(os5.homedir(), ".codex");
4530
+ }
4531
+ function getExplicitCodexHome() {
4532
+ const explicitHome = process.env.CODEX_HOME?.trim();
4533
+ return explicitHome ? explicitHome : null;
4534
+ }
4535
+ function dedupePaths(paths) {
4536
+ const seen = /* @__PURE__ */ new Set();
4537
+ const unique = [];
4538
+ for (const candidate of paths) {
4539
+ const normalized = path7.resolve(candidate);
4540
+ if (seen.has(normalized))
4541
+ continue;
4542
+ seen.add(normalized);
4543
+ unique.push(candidate);
4544
+ }
4545
+ return unique;
4546
+ }
4526
4547
  function getSystemCodexHome() {
4527
- return process.env.CODEX_HOME ?? path7.join(os5.homedir(), ".codex");
4548
+ return getExplicitCodexHome() ?? getDefaultSystemCodexHome();
4549
+ }
4550
+ function getCodexMonitoringHomes() {
4551
+ const explicitHome = getExplicitCodexHome();
4552
+ if (explicitHome)
4553
+ return [explicitHome];
4554
+ const homes = [];
4555
+ const active = getActiveCodexAccount3();
4556
+ if (active) {
4557
+ homes.push(getCodexProfileHome(active.id));
4558
+ }
4559
+ homes.push(getDefaultSystemCodexHome());
4560
+ return dedupePaths(homes);
4528
4561
  }
4529
4562
  function getCodexProfilesDir() {
4530
4563
  return path7.join((0, accountRegistry_1.getAccountsDir)(), "codex", "profiles");
@@ -4829,8 +4862,8 @@ var require_detect = __commonJS({
4829
4862
  }
4830
4863
  return path7.join(os5.homedir(), ".local", "share", "opencode");
4831
4864
  }
4832
- function getCodexHome() {
4833
- return (0, codexProfiles_1.resolveSidekickCodexHome)();
4865
+ function getCodexHomes() {
4866
+ return (0, codexProfiles_1.getCodexMonitoringHomes)();
4834
4867
  }
4835
4868
  function getMostRecentMtime(dir) {
4836
4869
  try {
@@ -4868,32 +4901,37 @@ var require_detect = __commonJS({
4868
4901
  return Math.max(sessionMtime, messageMtime, partMtime);
4869
4902
  }
4870
4903
  function getCodexActivityMtime() {
4871
- const codexHome = getCodexHome();
4872
- const dbPath = path7.join(codexHome, "state.sqlite");
4873
- try {
4874
- const dbMtime = fs9.statSync(dbPath).mtime.getTime();
4875
- if (dbMtime > 0)
4876
- return dbMtime;
4877
- } catch {
4904
+ let latest = 0;
4905
+ for (const codexHome of getCodexHomes()) {
4906
+ const dbPath = path7.join(codexHome, "state.sqlite");
4907
+ try {
4908
+ const dbMtime = fs9.statSync(dbPath).mtime.getTime();
4909
+ if (dbMtime > latest)
4910
+ latest = dbMtime;
4911
+ } catch {
4912
+ }
4913
+ const sessionsMtime = getMostRecentMtime(path7.join(codexHome, "sessions"));
4914
+ if (sessionsMtime > latest)
4915
+ latest = sessionsMtime;
4878
4916
  }
4879
- return getMostRecentMtime(path7.join(codexHome, "sessions"));
4917
+ return latest;
4880
4918
  }
4881
4919
  function getProviderPaths() {
4882
4920
  const claudeBase = path7.join(os5.homedir(), ".claude", "projects");
4883
4921
  const openCodeDataDir = getOpenCodeDataDir();
4922
+ const codexHomes = getCodexHomes();
4884
4923
  return {
4885
4924
  claudeBase,
4886
4925
  openCodeDbPath: path7.join(openCodeDataDir, "opencode.db"),
4887
4926
  openCodeStorageDir: path7.join(openCodeDataDir, "storage"),
4888
- codexSessionsDir: path7.join(getCodexHome(), "sessions"),
4889
- codexDbPath: path7.join(getCodexHome(), "state.sqlite")
4927
+ codexHomes
4890
4928
  };
4891
4929
  }
4892
4930
  function getAllDetectedProviders2() {
4893
- const { claudeBase, openCodeDbPath, openCodeStorageDir, codexSessionsDir, codexDbPath } = getProviderPaths();
4931
+ const { claudeBase, openCodeDbPath, openCodeStorageDir, codexHomes } = getProviderPaths();
4894
4932
  const hasClaude = fs9.existsSync(claudeBase);
4895
4933
  const hasOpenCode = fs9.existsSync(openCodeStorageDir) || fs9.existsSync(openCodeDbPath);
4896
- const hasCodex = fs9.existsSync(codexSessionsDir) || fs9.existsSync(codexDbPath);
4934
+ const hasCodex = codexHomes.some((codexHome) => fs9.existsSync(path7.join(codexHome, "sessions")) || fs9.existsSync(path7.join(codexHome, "state.sqlite")));
4897
4935
  const available = [];
4898
4936
  if (hasClaude)
4899
4937
  available.push({ id: "claude-code", mtime: getMostRecentMtime(claudeBase) });
@@ -4907,10 +4945,10 @@ var require_detect = __commonJS({
4907
4945
  function detectProvider2(override) {
4908
4946
  if (override && override !== "auto")
4909
4947
  return override;
4910
- const { claudeBase, openCodeDbPath, openCodeStorageDir, codexSessionsDir, codexDbPath } = getProviderPaths();
4948
+ const { claudeBase, openCodeDbPath, openCodeStorageDir, codexHomes } = getProviderPaths();
4911
4949
  const hasClaude = fs9.existsSync(claudeBase);
4912
4950
  const hasOpenCode = fs9.existsSync(openCodeStorageDir) || fs9.existsSync(openCodeDbPath);
4913
- const hasCodex = fs9.existsSync(codexSessionsDir) || fs9.existsSync(codexDbPath);
4951
+ const hasCodex = codexHomes.some((codexHome) => fs9.existsSync(path7.join(codexHome, "sessions")) || fs9.existsSync(path7.join(codexHome, "state.sqlite")));
4914
4952
  const available = [];
4915
4953
  if (hasClaude) {
4916
4954
  available.push({ id: "claude-code", mtime: getMostRecentMtime(claudeBase) });
@@ -9087,11 +9125,11 @@ var require_codex = __commonJS({
9087
9125
  var codexDatabase_1 = require_codexDatabase();
9088
9126
  var codexProfiles_1 = require_codexProfiles();
9089
9127
  var modelContext_1 = require_modelContext();
9090
- function getCodexHome() {
9091
- return (0, codexProfiles_1.resolveSidekickCodexHome)();
9128
+ function getCodexHomes() {
9129
+ return (0, codexProfiles_1.getCodexMonitoringHomes)();
9092
9130
  }
9093
- function getSessionsDir() {
9094
- return path7.join(getCodexHome(), "sessions");
9131
+ function getSessionsDirs() {
9132
+ return getCodexHomes().map((home) => path7.join(home, "sessions"));
9095
9133
  }
9096
9134
  function isRolloutFile(filename) {
9097
9135
  return filename.startsWith("rollout-") && filename.endsWith(".jsonl");
@@ -9138,6 +9176,31 @@ var require_codex = __commonJS({
9138
9176
  }
9139
9177
  return results;
9140
9178
  }
9179
+ function findRolloutFilesInConfiguredHomes() {
9180
+ const results = [];
9181
+ const seen = /* @__PURE__ */ new Set();
9182
+ for (const sessionsDir of getSessionsDirs()) {
9183
+ for (const file of findRolloutFiles(sessionsDir)) {
9184
+ if (seen.has(file.path))
9185
+ continue;
9186
+ seen.add(file.path);
9187
+ results.push(file);
9188
+ }
9189
+ }
9190
+ return results;
9191
+ }
9192
+ function getSessionsDir() {
9193
+ const dirs = getSessionsDirs();
9194
+ for (const dir of dirs) {
9195
+ if (findRolloutFiles(dir).length > 0) {
9196
+ return dir;
9197
+ }
9198
+ }
9199
+ return dirs[0] ?? path7.join(process.cwd(), ".codex", "sessions");
9200
+ }
9201
+ function getCodexHome() {
9202
+ return path7.dirname(getSessionsDir());
9203
+ }
9141
9204
  function isSystemInjection(text) {
9142
9205
  const t = text.trimStart();
9143
9206
  return t.startsWith("<") || t.startsWith("#");
@@ -9443,10 +9506,7 @@ var require_codex = __commonJS({
9443
9506
  return path7.dirname(thread.rollout_path);
9444
9507
  }
9445
9508
  }
9446
- const sessionsDir = getSessionsDir();
9447
- if (!fs9.existsSync(sessionsDir))
9448
- return null;
9449
- const files = findRolloutFiles(sessionsDir);
9509
+ const files = findRolloutFilesInConfiguredHomes();
9450
9510
  if (files.length === 0)
9451
9511
  return null;
9452
9512
  files.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
@@ -9456,7 +9516,7 @@ var require_codex = __commonJS({
9456
9516
  return path7.dirname(file.path);
9457
9517
  }
9458
9518
  }
9459
- return fs9.existsSync(sessionsDir) ? sessionsDir : null;
9519
+ return getSessionsDir();
9460
9520
  }
9461
9521
  // --- Session discovery ---
9462
9522
  findActiveSession(workspacePath) {
@@ -9467,10 +9527,7 @@ var require_codex = __commonJS({
9467
9527
  return thread.rollout_path;
9468
9528
  }
9469
9529
  }
9470
- const sessionsDir = getSessionsDir();
9471
- if (!fs9.existsSync(sessionsDir))
9472
- return null;
9473
- const files = findRolloutFiles(sessionsDir);
9530
+ const files = findRolloutFilesInConfiguredHomes();
9474
9531
  files.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
9475
9532
  for (const file of files) {
9476
9533
  const meta = readSessionMeta(file.path);
@@ -9488,10 +9545,7 @@ var require_codex = __commonJS({
9488
9545
  if (dbPaths.length > 0)
9489
9546
  return dbPaths;
9490
9547
  }
9491
- const sessionsDir = getSessionsDir();
9492
- if (!fs9.existsSync(sessionsDir))
9493
- return [];
9494
- const files = findRolloutFiles(sessionsDir);
9548
+ const files = findRolloutFilesInConfiguredHomes();
9495
9549
  files.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
9496
9550
  return files.filter((f) => {
9497
9551
  const meta = readSessionMeta(f.path);
@@ -9523,27 +9577,23 @@ var require_codex = __commonJS({
9523
9577
  });
9524
9578
  }
9525
9579
  }
9526
- const sessionsDir = getSessionsDir();
9527
- if (fs9.existsSync(sessionsDir)) {
9528
- const files = findRolloutFiles(sessionsDir);
9529
- for (const file of files) {
9530
- const meta = readSessionMeta(file.path);
9531
- if (!meta?.cwd)
9532
- continue;
9533
- const existing = seenCwds.get(meta.cwd);
9534
- if (existing) {
9535
- if (file.mtime > existing.lastModified) {
9536
- existing.lastModified = file.mtime;
9537
- }
9538
- } else {
9539
- seenCwds.set(meta.cwd, {
9540
- dir: path7.dirname(file.path),
9541
- name: meta.cwd,
9542
- encodedName: meta.cwd,
9543
- sessionCount: 1,
9544
- lastModified: file.mtime
9545
- });
9580
+ for (const file of findRolloutFilesInConfiguredHomes()) {
9581
+ const meta = readSessionMeta(file.path);
9582
+ if (!meta?.cwd)
9583
+ continue;
9584
+ const existing = seenCwds.get(meta.cwd);
9585
+ if (existing) {
9586
+ if (file.mtime > existing.lastModified) {
9587
+ existing.lastModified = file.mtime;
9546
9588
  }
9589
+ } else {
9590
+ seenCwds.set(meta.cwd, {
9591
+ dir: path7.dirname(file.path),
9592
+ name: meta.cwd,
9593
+ encodedName: meta.cwd,
9594
+ sessionCount: 1,
9595
+ lastModified: file.mtime
9596
+ });
9547
9597
  }
9548
9598
  }
9549
9599
  folders.push(...seenCwds.values());
@@ -9607,10 +9657,7 @@ var require_codex = __commonJS({
9607
9657
  if (forkedThreads.length > 0)
9608
9658
  return subagents;
9609
9659
  }
9610
- const sessionsDir = getSessionsDir();
9611
- if (!fs9.existsSync(sessionsDir))
9612
- return subagents;
9613
- const files = findRolloutFiles(sessionsDir);
9660
+ const files = findRolloutFilesInConfiguredHomes();
9614
9661
  files.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
9615
9662
  const filesToCheck = files.slice(0, 50);
9616
9663
  for (const file of filesToCheck) {
@@ -34436,8 +34483,8 @@ var require_dist = __commonJS({
34436
34483
  Object.defineProperty(exports, "__esModule", { value: true });
34437
34484
  exports.findActiveClaudeSession = exports.discoverSessionDirectory = exports.getClaudeSessionDirectory = exports.encodeClaudeWorkspacePath = exports.detectSessionActivity = exports.extractTaskInfo = exports.scanSubagentDir = exports.normalizeCodexToolInput = exports.normalizeCodexToolName = exports.extractPatchFilePaths = exports.CodexRolloutParser = exports.parseDbPartData = exports.parseDbMessageData = exports.convertOpenCodeMessage = exports.detectPlanModeFromText = exports.normalizeToolInput = exports.normalizeToolName = exports.TRUNCATION_PATTERNS = exports.JsonlParser = exports.CodexProvider = exports.OpenCodeProvider = exports.ClaudeCodeProvider = exports.getAllDetectedProviders = exports.detectProvider = exports.readClaudeCodePlanFiles = exports.getPlanAnalytics = exports.writePlans = exports.getLatestPlan = exports.readPlans = exports.readLatestHandoff = exports.readHistory = exports.readNotes = exports.readDecisions = exports.readTasks = exports.getProjectSlugRaw = exports.getProjectSlug = exports.encodeWorkspacePath = exports.getGlobalDataPath = exports.getProjectDataPath = exports.getConfigDir = exports.MAX_PLANS_PER_PROJECT = exports.PLAN_SCHEMA_VERSION = exports.createEmptyTokenTotals = exports.HISTORICAL_DATA_SCHEMA_VERSION = exports.STALENESS_THRESHOLDS = exports.IMPORTANCE_DECAY_FACTORS = exports.KNOWLEDGE_NOTE_SCHEMA_VERSION = exports.DECISION_LOG_SCHEMA_VERSION = exports.normalizeTaskStatus = exports.TASK_PERSISTENCE_SCHEMA_VERSION = void 0;
34438
34485
  exports.HeatmapTracker = exports.FrequencyTracker = exports.getSnapshotPath = exports.isSnapshotValid = exports.deleteSnapshot = exports.loadSnapshot = exports.saveSnapshot = exports.parseTodoDependencies = exports.EventAggregator = exports.getRandomPhrase = exports.ALL_PHRASES = exports.HIGHLIGHT_CSS = exports.clearHighlightCache = exports.highlightEvent = exports.formatSessionJson = exports.formatSessionMarkdown = exports.formatSessionText = exports.classifyNoise = exports.shouldMergeWithPrevious = exports.classifyFollowEvent = exports.classifyMessage = exports.getSoftNoiseReason = exports.isHardNoiseFollowEvent = exports.isHardNoise = exports.formatToolSummary = exports.toFollowEvents = exports.createWatcher = exports.parseChangelog = exports.extractProposedPlanShared = exports.parsePlanMarkdownShared = exports.PlanExtractor = exports.composeContext = exports.FilterEngine = exports.searchSessions = exports.CodexDatabase = exports.OpenCodeDatabase = exports.discoverDebugLogs = exports.collapseDuplicates = exports.filterByLevel = exports.parseDebugLog = exports.scanSubagentTraces = exports.findAllSessionsWithWorktrees = exports.discoverWorktreeSiblings = exports.resolveWorktreeMainRepo = exports.getAllClaudeProjectFolders = exports.decodeEncodedPath = exports.getMostRecentlyActiveSessionDir = exports.findSubdirectorySessionDirs = exports.findSessionsInDirectory = exports.findAllClaudeSessions = void 0;
34439
- exports.formatCost = exports.calculateCostWithPricing = exports.calculateCost = exports.getModelInfo = exports.getModelPricing = exports.parseModelId = exports.DEFAULT_CONTEXT_WINDOW = exports.getModelContextWindowSize = exports.quotaFromCodexRateLimits = exports.writeQuotaSnapshot = exports.readQuotaSnapshot = exports.QuotaPoller = exports.describeQuotaFailure = exports.fetchQuota = exports.removeCodexAccount = exports.switchToCodexAccount = exports.finalizeCodexAccount = exports.prepareCodexAccount = exports.getCodexExecutionEnv = exports.resolveSidekickCodexHome = exports.getActiveCodexAccount = exports.listCodexAccounts = exports.getCodexProfileHome = exports.getCodexProfilesDir = exports.removeSavedAccountProfile = exports.replaceSavedAccountProfiles = exports.setActiveSavedAccount = exports.upsertSavedAccountProfile = exports.getActiveSavedAccount = exports.listSavedAccountProfiles = exports.writeSavedAccountRegistry = exports.readSavedAccountRegistry = exports.getAccountsDir = exports.isMultiAccountEnabled = exports.getActiveAccount = exports.listAccounts = exports.removeAccount = exports.switchToAccount = exports.addCurrentAccount = exports.readActiveClaudeAccount = exports.writeAccountRegistry = exports.readAccountRegistry = exports.readClaudeMaxAccessTokenSync = exports.readClaudeMaxCredentials = exports.writeActiveCredentials = exports.readActiveCredentials = exports.openInBrowser = exports.parseTranscript = exports.generateHtmlReport = exports.PatternExtractor = void 0;
34440
- exports.fetchOpenAIStatus = exports.fetchProviderStatus = exports.permissionModeSchema = exports.sessionEventSchema = exports.sessionMessageSchema = exports.messageUsageSchema = exports.extractToolCalls = exports.extractTokenUsage = void 0;
34486
+ exports.calculateCost = exports.getModelInfo = exports.getModelPricing = exports.parseModelId = exports.DEFAULT_CONTEXT_WINDOW = exports.getModelContextWindowSize = exports.quotaFromCodexRateLimits = exports.writeQuotaSnapshot = exports.readQuotaSnapshot = exports.QuotaPoller = exports.describeQuotaFailure = exports.fetchQuota = exports.removeCodexAccount = exports.switchToCodexAccount = exports.finalizeCodexAccount = exports.prepareCodexAccount = exports.getCodexExecutionEnv = exports.resolveSidekickCodexHome = exports.getActiveCodexAccount = exports.listCodexAccounts = exports.getSystemCodexHome = exports.getCodexMonitoringHomes = exports.getCodexProfileHome = exports.getCodexProfilesDir = exports.removeSavedAccountProfile = exports.replaceSavedAccountProfiles = exports.setActiveSavedAccount = exports.upsertSavedAccountProfile = exports.getActiveSavedAccount = exports.listSavedAccountProfiles = exports.writeSavedAccountRegistry = exports.readSavedAccountRegistry = exports.getAccountsDir = exports.isMultiAccountEnabled = exports.getActiveAccount = exports.listAccounts = exports.removeAccount = exports.switchToAccount = exports.addCurrentAccount = exports.readActiveClaudeAccount = exports.writeAccountRegistry = exports.readAccountRegistry = exports.readClaudeMaxAccessTokenSync = exports.readClaudeMaxCredentials = exports.writeActiveCredentials = exports.readActiveCredentials = exports.openInBrowser = exports.parseTranscript = exports.generateHtmlReport = exports.PatternExtractor = void 0;
34487
+ exports.fetchOpenAIStatus = exports.fetchProviderStatus = exports.permissionModeSchema = exports.sessionEventSchema = exports.sessionMessageSchema = exports.messageUsageSchema = exports.extractToolCalls = exports.extractTokenUsage = exports.formatCost = exports.calculateCostWithPricing = void 0;
34441
34488
  var taskPersistence_1 = require_taskPersistence();
34442
34489
  Object.defineProperty(exports, "TASK_PERSISTENCE_SCHEMA_VERSION", { enumerable: true, get: function() {
34443
34490
  return taskPersistence_1.TASK_PERSISTENCE_SCHEMA_VERSION;
@@ -34871,6 +34918,12 @@ var require_dist = __commonJS({
34871
34918
  Object.defineProperty(exports, "getCodexProfileHome", { enumerable: true, get: function() {
34872
34919
  return codexProfiles_1.getCodexProfileHome;
34873
34920
  } });
34921
+ Object.defineProperty(exports, "getCodexMonitoringHomes", { enumerable: true, get: function() {
34922
+ return codexProfiles_1.getCodexMonitoringHomes;
34923
+ } });
34924
+ Object.defineProperty(exports, "getSystemCodexHome", { enumerable: true, get: function() {
34925
+ return codexProfiles_1.getSystemCodexHome;
34926
+ } });
34874
34927
  Object.defineProperty(exports, "listCodexAccounts", { enumerable: true, get: function() {
34875
34928
  return codexProfiles_1.listCodexAccounts;
34876
34929
  } });
@@ -37187,7 +37240,7 @@ var init_UpdateCheckService = __esm({
37187
37240
  /** Run the update check (one-shot). */
37188
37241
  async check() {
37189
37242
  try {
37190
- const current = "0.17.0";
37243
+ const current = "0.17.1";
37191
37244
  const cached = this.readCache();
37192
37245
  let latest;
37193
37246
  if (cached && Date.now() - cached.checkedAt < CACHE_TTL_MS) {
@@ -77804,7 +77857,7 @@ function StatusBar({
77804
77857
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: parseBlessedTags(BRAND_INLINE) }),
77805
77858
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { dimColor: true, children: [
77806
77859
  " v",
77807
- "0.17.0"
77860
+ "0.17.1"
77808
77861
  ] }),
77809
77862
  updateInfo && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { color: "yellow", children: [
77810
77863
  " (v",
@@ -78194,7 +78247,7 @@ function ChangelogOverlay({ entries, scrollOffset }) {
78194
78247
  " ",
78195
78248
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { bold: true, color: "cyan", children: [
78196
78249
  "Terminal Dashboard v",
78197
- "0.17.0"
78250
+ "0.17.1"
78198
78251
  ] }),
78199
78252
  latestDate ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: "gray", children: [
78200
78253
  " \u2014 ",
@@ -78516,7 +78569,7 @@ var init_mouse = __esm({
78516
78569
  var CHANGELOG_default;
78517
78570
  var init_CHANGELOG = __esm({
78518
78571
  "CHANGELOG.md"() {
78519
- CHANGELOG_default = '# Changelog\n\nAll notable changes to the Sidekick Agent Hub CLI will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [0.17.0] - 2026-04-13\n\n### Added\n\n- **Multi-provider account management**: `sidekick account` now supports `--provider codex` for Codex profile management alongside Claude Code accounts\n- **Codex account lifecycle**: `--add` prepares a profile and spawns `codex login`; `--switch-to` and `--remove` accept email, label, or profile ID\n- **Quota snapshot fallback**: `sidekick quota` for Codex shows cached rate-limit snapshots when no active session exists, with "cached from" timestamp\n\n### Fixed\n\n- **Email normalization**: Claude account lookup normalizes email case for reliable matching\n\n## [0.16.1] - 2026-03-27\n\n### Fixed\n\n- **Dashboard provider status scoping**: The TUI now shows degraded-service notices only for the monitored provider \u2014 Claude for Claude Code sessions, OpenAI for Codex sessions, and no status banner for OpenCode\n\n## [0.16.0] - 2026-03-23\n\n### Changed\n\n- **Consistent cost formatting**: All cost displays (`stats`, `context`, Sessions panel, narrative prompt) now use shared `formatCost()` with intelligent decimal precision (4 places for < $0.01, 2 otherwise)\n- **QuotaService**: Rewritten to wrap shared `QuotaPoller` with exponential backoff instead of manual polling loop\n- **modelContext**: Now re-exports `getModelInfo` from shared library alongside `getContextWindowSize`\n\n## [0.15.2] - 2026-03-18\n\n### Fixed\n\n- **CLI help descriptions**: Updated `quota` and `status` command descriptions to reflect provider-aware behavior\n- **`sidekick quota --provider`**: Added local `--provider` option so `sidekick quota --provider codex` works naturally\n\n## [0.15.0] - 2026-03-18\n\n### Added\n\n- **OpenAI status page monitoring**: CLI dashboard now shows OpenAI API status alongside Claude API status\n- **Codex rate limits in dashboard**: Sessions panel displays Codex rate-limit data with "Rate Limits" header instead of "Quota"\n- **Provider-aware `sidekick quota` command**: Detects active provider and shows Codex rate limits, Claude subscription quota, or an informational message for OpenCode\n\n### Fixed\n\n- **QuotaService polling for Codex**: Dashboard no longer starts Claude OAuth quota polling when the active provider is Codex\n\n## [0.14.2] - 2026-03-16\n\n### Fixed\n\n- **Quota polling interval**: Reduced quota refresh from every 30 seconds to every 5 minutes to avoid unnecessary API calls\n- **SessionsPanel `detailWidth()` call**: Removed unused parameter from `detailWidth()` in the Sessions panel quota rendering\n\n## [0.14.1] - 2026-03-14\n\n### Fixed\n\n- **Per-model context window sizes**: Dashboard context gauge now shows correct utilization for Claude Opus 4.6 (1M context) and other models with non-200K windows\n\n### Changed\n\n- **Shared model context lookup**: CLI dashboard now uses the centralized `getModelContextWindowSize()` from `sidekick-shared` instead of a local duplicate map\n\n## [0.14.0] - 2026-03-12\n\n### Added\n\n- **`sidekick account` Command**: Manage Claude Code accounts from the terminal \u2014 list saved accounts, add the current account with an optional label, switch to the next or a specific account, and remove accounts. Supports `--json` output for scripting\n- **Quota Account Label**: `sidekick quota` now shows the active account email and label above the quota bars when multi-account is enabled\n- **macOS Keychain Support**: `sidekick account` and `sidekick quota` now read and write credentials via the system Keychain on macOS, fixing account switching and quota checks on Mac\n\n## [0.13.8] - 2026-03-12\n\n### Changed\n\n- **Structured quota failure output**: `sidekick quota` now renders consistent auth, rate-limit, server, network, and unexpected-failure copy from shared quota failure descriptors while preserving `--json` machine-readable output\n- **Dashboard unavailable quota rendering**: The Sessions panel now shows Claude Code quota failures inline instead of hiding the quota section whenever subscription data is unavailable\n- **Quota transition toasts**: The Ink dashboard now fires low-noise toast notifications only when Claude Code quota failure state changes, avoiding repeated alerts every polling interval\n\n## [0.13.7] - 2026-03-11\n\n### Changed\n\n- **npm README sync**: Updated the published CLI package README to reflect current OpenCode monitoring behavior, platform-specific data directories, and the `sqlite3` runtime requirement\n- **README badge cleanup**: Removed the Ask DeepWiki badge from the published CLI package README; the repo root README still keeps it\n\n## [0.13.6] - 2026-03-11\n\n### Changed\n\n- **Refreshed CLI Dashboard Wordmark**: Updated the dashboard wordmark/header styling for a cleaner splash and dashboard identity\n\n### Fixed\n\n- **OpenCode dashboard startup**: OpenCode DB-backed session discovery now resolves projects by worktree, sandboxes, and session directory instead of quietly behaving like no session exists\n- **OpenCode runtime notices**: The CLI now prints an OpenCode-only actionable notice when `opencode.db` exists but `sqlite3` is missing, blocked, or otherwise unusable in the current shell environment\n\n## [0.13.5] - 2026-03-10\n\n### Added\n\n- **`sidekick status` Command**: One-shot Claude API status check with color-coded text output and `--json` mode\n- **Dashboard Status Banner**: Status bar shows a colored `\u25CF API minor/major/critical` indicator when Claude is degraded; Sessions panel Summary tab shows an "API Status" section with affected components and active incident details. Polls every 60s\n\n## [0.13.4] - 2026-03-08\n\n### Fixed\n\n- **Onboarding Phrase Spam**: Splash screen and detail pane motivational phrases memoized \u2014 no longer flicker every render tick (fixes [#13](https://github.com/cesarandreslopez/sidekick-agent-hub/issues/13))\n\n### Changed\n\n- **Simplified Logo**: Replaced 6-line ASCII robot art with compact text header in splash, help, and changelog overlays\n- **Removed Dead Code**: Removed unused `getSplashContent()` and `HELP_HEADER` exports from branding module\n\n## [0.13.3] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.2] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.1] - 2026-03-04\n\n### Added\n\n- **`sidekick quota` Command**: One-shot subscription quota check showing 5-hour and 7-day utilization with color-coded progress bars and reset countdowns \u2014 supports `--json` for machine-readable output\n- **Quota Projections**: Elapsed-time projections shown in `sidekick quota` output and TUI dashboard quota section \u2014 displays projected end-of-window utilization next to current value (e.g., `40% \u2192 100%`), included in `--json` output as `projectedFiveHour` / `projectedSevenDay`\n\n## [0.13.0] - 2026-03-03\n\n_No CLI-specific changes in this release._\n\n## [0.12.10] - 2026-03-01\n\n### Added\n\n- **Events Panel** (key 7): Scrollable live event stream with colored type badges (`[USR]`, `[AST]`, `[TOOL]`, `[RES]`), timestamps, and keyword-highlighted summaries; detail tabs for full event JSON and surrounding context\n- **Charts Panel** (key 8): Tool frequency horizontal bars, event type distribution, 60-minute activity heatmap using `\u2591\u2592\u2593\u2588` intensity characters, and pattern analysis with frequency bars and template text\n- **Multi-Mode Filter**: `/` filter overlay now supports four modes \u2014 substring, fuzzy, regex, and date range \u2014 Tab cycles modes, regex mode shows red validation errors\n- **Search Term Highlighting**: Active filter terms highlighted in blue within side list items\n- **Timeline Keyword Coloring**: Event summaries in the Sessions panel Timeline tab now use semantic keyword coloring \u2014 errors red, success green, tool names cyan, file paths magenta\n\n### Removed\n\n- **Search Panel**: Removed redundant Search panel (previously key 7) \u2014 the `/` filter with multi-mode support serves the same purpose\n\n## [0.12.9] - 2026-02-28\n\n### Added\n\n- **Standalone Data Commands**: `sidekick tasks`, `sidekick decisions`, `sidekick notes`, `sidekick stats`, `sidekick handoff` for accessing project data without launching the TUI\n- **`sidekick search <query>`**: Cross-session full-text search from the terminal\n- **`sidekick context`**: Composite output of tasks, decisions, notes, and handoff for piping into other tools\n- **`--list` flag on `sidekick dump`**: Discover available session IDs before requiring `--session <id>`\n- **Search Panel**: Search panel (panel 7) wired into the TUI dashboard\n\n### Changed\n\n- **`taskMerger` utility**: Duplicate `mergeTasks` logic extracted into shared `taskMerger` utility\n- **Model constants**: Hardcoded model IDs extracted to named constants\n\n### Fixed\n\n- **`convention` icon**: Notes panel icon replaced with valid `tip` type\n- **Linux clipboard**: Now supports Wayland (`wl-copy`) and `xsel` fallbacks, with error messages instead of silent failure\n- **`provider.dispose()`**: Added to `dump` and `report` commands (prevents SQLite connection leaks)\n\n## [0.12.8] - 2026-02-28\n\n### Changed\n\n- **Dashboard UI/UX Polish**: Visual overhaul for better hierarchy, consistency, and readability\n - Splash screen and help overlay now display the robot ASCII logo\n - Toast notifications show severity icons (\u2718 error, \u26A0 warning, \u25CF info) with inner padding\n - Focused pane uses double-border for clear focus indication\n - Section dividers (`\u2500\u2500 Title \u2500\u2500\u2500\u2500`) replace bare bold headers in summary, agents, and context attribution\n - Tab bar: active tab underlined in magenta, inactive tabs dimmed, bracket syntax removed\n - Status bar: segmented layout with `\u2502` separators; keys bold, labels dim\n - Summary metrics condensed: elapsed/events/compactions on one line, tokens on one line with cache rate and cost\n - Sparklines display peak metadata annotations\n - Progress bars use blessed color tags for consistent coloring\n - Help overlay uses dot-leader alignment for all keybinding rows\n - Empty state hints per panel (e.g. "Tasks appear as your agent works.")\n - Session picker groups sessions by provider with section headers when multiple providers are present\n\n## [0.12.7] - 2026-02-27\n\n### Added\n\n- **HTML Session Report**: `sidekick report` command generates a self-contained HTML report and opens it in the default browser\n - Options: `--session`, `--output`, `--theme` (dark/light), `--no-open`, `--no-thinking`\n - TUI Dashboard: press `r` to generate and open an HTML report for the current session\n\n## [0.12.6] - 2026-02-26\n\n### Added\n\n- **Session Dump Command**: `sidekick dump` exports session data in text, markdown, or JSON format with `--format`, `--width`, and `--expand` options\n- **Plans Panel Re-enabled**: Plans panel restored in CLI dashboard with plan file discovery from `~/.claude/plans/`\n- **Enhanced Status Bar**: Session info display improved with richer metadata\n\n### Fixed\n\n- **Old snapshot format migration**: Restoring pre-0.12.3 session snapshots no longer shows empty timeline entries\n\n### Changed\n\n- **Phrase library moved to shared**: CLI-specific phrase formatting kept local, all phrase content now from `sidekick-shared`\n\n## [0.12.5] - 2026-02-24\n\n### Fixed\n\n- **Update check too slow to notice new versions**: Reduced npm registry cache TTL from 24 hours to 4 hours so upgrade notices appear sooner after a new release\n\n## [0.12.4] - 2026-02-24\n\n### Fixed\n\n- **Session crash on upgrade**: Fixed `d.timestamp.getTime is not a function` error when restoring tool call data from session snapshots \u2014 `Date` objects were serialized to strings by JSON but not rehydrated on restore, causing the session monitor to crash on first run after upgrading from 0.12.2 to 0.12.3\n\n## [0.12.3] - 2026-02-24\n\n### Added\n\n- **Latest-node indicator**: The most recently added node in tree and boxed mind map views is now marked with a yellow indicator\n- **Plan analytics in mind map**: Tree and boxed views now display plan progress and per-step metrics\n - Tree view: plan header shows completion stats; steps show complexity, duration, tokens, tool calls, and errors in metadata brackets\n - Box view: progress bar with completion percentage; steps show right-aligned metrics; subtitle shows step count and total duration\n- **Cross-provider plan extraction**: Shared `PlanExtractor` now handles Claude Code (EnterPlanMode/ExitPlanMode) and OpenCode (`<proposed_plan>` XML) plans \u2014 previously only Codex plans were shown\n- **Enriched plan data model**: Plan steps include duration, token count, tool call count, and error messages\n- **Phase-grouped plan display**: When a plan has phase structure, tree and boxed views group steps under phase headers with context lines from the original plan markdown\n- **Node type filter**: Press `f` on the Mind Map tab to cycle through node type filters (file, tool, task, subagent, command, plan, knowledge-note) \u2014 non-matching sections render dimmed in grey\n\n### Fixed\n\n- **Kanban board regression**: Subagent and plan-step tasks now correctly appear in the kanban board\n\n### Changed\n\n- **Plans panel temporarily disabled**: The Plans panel in the CLI dashboard is disabled until plan-mode event capture is reliably working end-to-end. Plan nodes in the mind map remain active.\n- `DashboardState` now delegates to shared `EventAggregator` instead of maintaining its own aggregation logic\n\n## [0.12.2] - 2026-02-23\n\n### Added\n\n- **Update notifications**: The dashboard now checks the npm registry for newer versions on startup and shows a yellow banner in the status bar when an update is available (e.g., `v0.13.0 available \u2014 npm i -g sidekick-agent-hub`). Results are cached for 24 hours to avoid repeated network requests.\n\n## [0.12.1] - 2026-02-23\n\n### Fixed\n\n- **VS Code integration**: Fixed exit code 127 when the extension launches the CLI dashboard on systems using nvm or volta (node binary not found when shell init is bypassed)\n\n## [0.12.0] - 2026-02-22\n\n### Added\n\n- **"Open CLI Dashboard" VS Code Integration**: New VS Code command `Sidekick: Open CLI Dashboard` launches the TUI dashboard in an integrated terminal\n - Install the CLI with `npm install -g sidekick-agent-hub`\n\n## [0.11.0] - 2026-02-19\n\n### Added\n\n- **Initial Release**: Full-screen TUI dashboard for monitoring agent sessions from the terminal\n - Ink-based terminal UI with panels for sessions, tasks, kanban, mind map, notes, decisions, search, files, and git diff\n - Multi-provider support: auto-detects Claude Code, OpenCode, and Codex sessions\n - Reads from `~/.config/sidekick/` \u2014 the same data files the VS Code extension writes\n - Usage: `sidekick dashboard [--project <path>] [--provider <id>]`\n';
78572
+ CHANGELOG_default = '# Changelog\n\nAll notable changes to the Sidekick Agent Hub CLI will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [0.17.1] - 2026-04-13\n\n### Fixed\n\n- **Codex multi-home session discovery**: Provider detection now scans all candidate Codex home directories, fixing missed sessions when the managed profile home is empty but the system `~/.codex/` has activity\n\n## [0.17.0] - 2026-04-13\n\n### Added\n\n- **Multi-provider account management**: `sidekick account` now supports `--provider codex` for Codex profile management alongside Claude Code accounts\n- **Codex account lifecycle**: `--add` prepares a profile and spawns `codex login`; `--switch-to` and `--remove` accept email, label, or profile ID\n- **Quota snapshot fallback**: `sidekick quota` for Codex shows cached rate-limit snapshots when no active session exists, with "cached from" timestamp\n\n### Fixed\n\n- **Email normalization**: Claude account lookup normalizes email case for reliable matching\n\n## [0.16.1] - 2026-03-27\n\n### Fixed\n\n- **Dashboard provider status scoping**: The TUI now shows degraded-service notices only for the monitored provider \u2014 Claude for Claude Code sessions, OpenAI for Codex sessions, and no status banner for OpenCode\n\n## [0.16.0] - 2026-03-23\n\n### Changed\n\n- **Consistent cost formatting**: All cost displays (`stats`, `context`, Sessions panel, narrative prompt) now use shared `formatCost()` with intelligent decimal precision (4 places for < $0.01, 2 otherwise)\n- **QuotaService**: Rewritten to wrap shared `QuotaPoller` with exponential backoff instead of manual polling loop\n- **modelContext**: Now re-exports `getModelInfo` from shared library alongside `getContextWindowSize`\n\n## [0.15.2] - 2026-03-18\n\n### Fixed\n\n- **CLI help descriptions**: Updated `quota` and `status` command descriptions to reflect provider-aware behavior\n- **`sidekick quota --provider`**: Added local `--provider` option so `sidekick quota --provider codex` works naturally\n\n## [0.15.0] - 2026-03-18\n\n### Added\n\n- **OpenAI status page monitoring**: CLI dashboard now shows OpenAI API status alongside Claude API status\n- **Codex rate limits in dashboard**: Sessions panel displays Codex rate-limit data with "Rate Limits" header instead of "Quota"\n- **Provider-aware `sidekick quota` command**: Detects active provider and shows Codex rate limits, Claude subscription quota, or an informational message for OpenCode\n\n### Fixed\n\n- **QuotaService polling for Codex**: Dashboard no longer starts Claude OAuth quota polling when the active provider is Codex\n\n## [0.14.2] - 2026-03-16\n\n### Fixed\n\n- **Quota polling interval**: Reduced quota refresh from every 30 seconds to every 5 minutes to avoid unnecessary API calls\n- **SessionsPanel `detailWidth()` call**: Removed unused parameter from `detailWidth()` in the Sessions panel quota rendering\n\n## [0.14.1] - 2026-03-14\n\n### Fixed\n\n- **Per-model context window sizes**: Dashboard context gauge now shows correct utilization for Claude Opus 4.6 (1M context) and other models with non-200K windows\n\n### Changed\n\n- **Shared model context lookup**: CLI dashboard now uses the centralized `getModelContextWindowSize()` from `sidekick-shared` instead of a local duplicate map\n\n## [0.14.0] - 2026-03-12\n\n### Added\n\n- **`sidekick account` Command**: Manage Claude Code accounts from the terminal \u2014 list saved accounts, add the current account with an optional label, switch to the next or a specific account, and remove accounts. Supports `--json` output for scripting\n- **Quota Account Label**: `sidekick quota` now shows the active account email and label above the quota bars when multi-account is enabled\n- **macOS Keychain Support**: `sidekick account` and `sidekick quota` now read and write credentials via the system Keychain on macOS, fixing account switching and quota checks on Mac\n\n## [0.13.8] - 2026-03-12\n\n### Changed\n\n- **Structured quota failure output**: `sidekick quota` now renders consistent auth, rate-limit, server, network, and unexpected-failure copy from shared quota failure descriptors while preserving `--json` machine-readable output\n- **Dashboard unavailable quota rendering**: The Sessions panel now shows Claude Code quota failures inline instead of hiding the quota section whenever subscription data is unavailable\n- **Quota transition toasts**: The Ink dashboard now fires low-noise toast notifications only when Claude Code quota failure state changes, avoiding repeated alerts every polling interval\n\n## [0.13.7] - 2026-03-11\n\n### Changed\n\n- **npm README sync**: Updated the published CLI package README to reflect current OpenCode monitoring behavior, platform-specific data directories, and the `sqlite3` runtime requirement\n- **README badge cleanup**: Removed the Ask DeepWiki badge from the published CLI package README; the repo root README still keeps it\n\n## [0.13.6] - 2026-03-11\n\n### Changed\n\n- **Refreshed CLI Dashboard Wordmark**: Updated the dashboard wordmark/header styling for a cleaner splash and dashboard identity\n\n### Fixed\n\n- **OpenCode dashboard startup**: OpenCode DB-backed session discovery now resolves projects by worktree, sandboxes, and session directory instead of quietly behaving like no session exists\n- **OpenCode runtime notices**: The CLI now prints an OpenCode-only actionable notice when `opencode.db` exists but `sqlite3` is missing, blocked, or otherwise unusable in the current shell environment\n\n## [0.13.5] - 2026-03-10\n\n### Added\n\n- **`sidekick status` Command**: One-shot Claude API status check with color-coded text output and `--json` mode\n- **Dashboard Status Banner**: Status bar shows a colored `\u25CF API minor/major/critical` indicator when Claude is degraded; Sessions panel Summary tab shows an "API Status" section with affected components and active incident details. Polls every 60s\n\n## [0.13.4] - 2026-03-08\n\n### Fixed\n\n- **Onboarding Phrase Spam**: Splash screen and detail pane motivational phrases memoized \u2014 no longer flicker every render tick (fixes [#13](https://github.com/cesarandreslopez/sidekick-agent-hub/issues/13))\n\n### Changed\n\n- **Simplified Logo**: Replaced 6-line ASCII robot art with compact text header in splash, help, and changelog overlays\n- **Removed Dead Code**: Removed unused `getSplashContent()` and `HELP_HEADER` exports from branding module\n\n## [0.13.3] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.2] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.1] - 2026-03-04\n\n### Added\n\n- **`sidekick quota` Command**: One-shot subscription quota check showing 5-hour and 7-day utilization with color-coded progress bars and reset countdowns \u2014 supports `--json` for machine-readable output\n- **Quota Projections**: Elapsed-time projections shown in `sidekick quota` output and TUI dashboard quota section \u2014 displays projected end-of-window utilization next to current value (e.g., `40% \u2192 100%`), included in `--json` output as `projectedFiveHour` / `projectedSevenDay`\n\n## [0.13.0] - 2026-03-03\n\n_No CLI-specific changes in this release._\n\n## [0.12.10] - 2026-03-01\n\n### Added\n\n- **Events Panel** (key 7): Scrollable live event stream with colored type badges (`[USR]`, `[AST]`, `[TOOL]`, `[RES]`), timestamps, and keyword-highlighted summaries; detail tabs for full event JSON and surrounding context\n- **Charts Panel** (key 8): Tool frequency horizontal bars, event type distribution, 60-minute activity heatmap using `\u2591\u2592\u2593\u2588` intensity characters, and pattern analysis with frequency bars and template text\n- **Multi-Mode Filter**: `/` filter overlay now supports four modes \u2014 substring, fuzzy, regex, and date range \u2014 Tab cycles modes, regex mode shows red validation errors\n- **Search Term Highlighting**: Active filter terms highlighted in blue within side list items\n- **Timeline Keyword Coloring**: Event summaries in the Sessions panel Timeline tab now use semantic keyword coloring \u2014 errors red, success green, tool names cyan, file paths magenta\n\n### Removed\n\n- **Search Panel**: Removed redundant Search panel (previously key 7) \u2014 the `/` filter with multi-mode support serves the same purpose\n\n## [0.12.9] - 2026-02-28\n\n### Added\n\n- **Standalone Data Commands**: `sidekick tasks`, `sidekick decisions`, `sidekick notes`, `sidekick stats`, `sidekick handoff` for accessing project data without launching the TUI\n- **`sidekick search <query>`**: Cross-session full-text search from the terminal\n- **`sidekick context`**: Composite output of tasks, decisions, notes, and handoff for piping into other tools\n- **`--list` flag on `sidekick dump`**: Discover available session IDs before requiring `--session <id>`\n- **Search Panel**: Search panel (panel 7) wired into the TUI dashboard\n\n### Changed\n\n- **`taskMerger` utility**: Duplicate `mergeTasks` logic extracted into shared `taskMerger` utility\n- **Model constants**: Hardcoded model IDs extracted to named constants\n\n### Fixed\n\n- **`convention` icon**: Notes panel icon replaced with valid `tip` type\n- **Linux clipboard**: Now supports Wayland (`wl-copy`) and `xsel` fallbacks, with error messages instead of silent failure\n- **`provider.dispose()`**: Added to `dump` and `report` commands (prevents SQLite connection leaks)\n\n## [0.12.8] - 2026-02-28\n\n### Changed\n\n- **Dashboard UI/UX Polish**: Visual overhaul for better hierarchy, consistency, and readability\n - Splash screen and help overlay now display the robot ASCII logo\n - Toast notifications show severity icons (\u2718 error, \u26A0 warning, \u25CF info) with inner padding\n - Focused pane uses double-border for clear focus indication\n - Section dividers (`\u2500\u2500 Title \u2500\u2500\u2500\u2500`) replace bare bold headers in summary, agents, and context attribution\n - Tab bar: active tab underlined in magenta, inactive tabs dimmed, bracket syntax removed\n - Status bar: segmented layout with `\u2502` separators; keys bold, labels dim\n - Summary metrics condensed: elapsed/events/compactions on one line, tokens on one line with cache rate and cost\n - Sparklines display peak metadata annotations\n - Progress bars use blessed color tags for consistent coloring\n - Help overlay uses dot-leader alignment for all keybinding rows\n - Empty state hints per panel (e.g. "Tasks appear as your agent works.")\n - Session picker groups sessions by provider with section headers when multiple providers are present\n\n## [0.12.7] - 2026-02-27\n\n### Added\n\n- **HTML Session Report**: `sidekick report` command generates a self-contained HTML report and opens it in the default browser\n - Options: `--session`, `--output`, `--theme` (dark/light), `--no-open`, `--no-thinking`\n - TUI Dashboard: press `r` to generate and open an HTML report for the current session\n\n## [0.12.6] - 2026-02-26\n\n### Added\n\n- **Session Dump Command**: `sidekick dump` exports session data in text, markdown, or JSON format with `--format`, `--width`, and `--expand` options\n- **Plans Panel Re-enabled**: Plans panel restored in CLI dashboard with plan file discovery from `~/.claude/plans/`\n- **Enhanced Status Bar**: Session info display improved with richer metadata\n\n### Fixed\n\n- **Old snapshot format migration**: Restoring pre-0.12.3 session snapshots no longer shows empty timeline entries\n\n### Changed\n\n- **Phrase library moved to shared**: CLI-specific phrase formatting kept local, all phrase content now from `sidekick-shared`\n\n## [0.12.5] - 2026-02-24\n\n### Fixed\n\n- **Update check too slow to notice new versions**: Reduced npm registry cache TTL from 24 hours to 4 hours so upgrade notices appear sooner after a new release\n\n## [0.12.4] - 2026-02-24\n\n### Fixed\n\n- **Session crash on upgrade**: Fixed `d.timestamp.getTime is not a function` error when restoring tool call data from session snapshots \u2014 `Date` objects were serialized to strings by JSON but not rehydrated on restore, causing the session monitor to crash on first run after upgrading from 0.12.2 to 0.12.3\n\n## [0.12.3] - 2026-02-24\n\n### Added\n\n- **Latest-node indicator**: The most recently added node in tree and boxed mind map views is now marked with a yellow indicator\n- **Plan analytics in mind map**: Tree and boxed views now display plan progress and per-step metrics\n - Tree view: plan header shows completion stats; steps show complexity, duration, tokens, tool calls, and errors in metadata brackets\n - Box view: progress bar with completion percentage; steps show right-aligned metrics; subtitle shows step count and total duration\n- **Cross-provider plan extraction**: Shared `PlanExtractor` now handles Claude Code (EnterPlanMode/ExitPlanMode) and OpenCode (`<proposed_plan>` XML) plans \u2014 previously only Codex plans were shown\n- **Enriched plan data model**: Plan steps include duration, token count, tool call count, and error messages\n- **Phase-grouped plan display**: When a plan has phase structure, tree and boxed views group steps under phase headers with context lines from the original plan markdown\n- **Node type filter**: Press `f` on the Mind Map tab to cycle through node type filters (file, tool, task, subagent, command, plan, knowledge-note) \u2014 non-matching sections render dimmed in grey\n\n### Fixed\n\n- **Kanban board regression**: Subagent and plan-step tasks now correctly appear in the kanban board\n\n### Changed\n\n- **Plans panel temporarily disabled**: The Plans panel in the CLI dashboard is disabled until plan-mode event capture is reliably working end-to-end. Plan nodes in the mind map remain active.\n- `DashboardState` now delegates to shared `EventAggregator` instead of maintaining its own aggregation logic\n\n## [0.12.2] - 2026-02-23\n\n### Added\n\n- **Update notifications**: The dashboard now checks the npm registry for newer versions on startup and shows a yellow banner in the status bar when an update is available (e.g., `v0.13.0 available \u2014 npm i -g sidekick-agent-hub`). Results are cached for 24 hours to avoid repeated network requests.\n\n## [0.12.1] - 2026-02-23\n\n### Fixed\n\n- **VS Code integration**: Fixed exit code 127 when the extension launches the CLI dashboard on systems using nvm or volta (node binary not found when shell init is bypassed)\n\n## [0.12.0] - 2026-02-22\n\n### Added\n\n- **"Open CLI Dashboard" VS Code Integration**: New VS Code command `Sidekick: Open CLI Dashboard` launches the TUI dashboard in an integrated terminal\n - Install the CLI with `npm install -g sidekick-agent-hub`\n\n## [0.11.0] - 2026-02-19\n\n### Added\n\n- **Initial Release**: Full-screen TUI dashboard for monitoring agent sessions from the terminal\n - Ink-based terminal UI with panels for sessions, tasks, kanban, mind map, notes, decisions, search, files, and git diff\n - Multi-provider support: auto-detects Claude Code, OpenCode, and Codex sessions\n - Reads from `~/.config/sidekick/` \u2014 the same data files the VS Code extension writes\n - Usage: `sidekick dashboard [--project <path>] [--provider <id>]`\n';
78520
78573
  }
78521
78574
  });
78522
78575
 
@@ -81257,7 +81310,7 @@ var init_cli = __esm({
81257
81310
  import_sidekick_shared32 = __toESM(require_dist(), 1);
81258
81311
  import_sidekick_shared33 = __toESM(require_dist(), 1);
81259
81312
  program2 = new Command();
81260
- program2.name("sidekick").description("Query Sidekick project intelligence from the command line").version("0.17.0").option("--json", "Output as JSON").option("--project <path>", "Override project path (default: cwd)").option("--provider <id>", "Provider: claude-code, opencode, codex, auto (default: auto)");
81313
+ program2.name("sidekick").description("Query Sidekick project intelligence from the command line").version("0.17.1").option("--json", "Output as JSON").option("--project <path>", "Override project path (default: cwd)").option("--provider <id>", "Provider: claude-code, opencode, codex, auto (default: auto)");
81261
81314
  dashCmd = new Command("dashboard").description("Full-screen TUI dashboard with live session metrics").option("--session <id>", "Follow a specific session (default: most recent)").option("--replay", "Replay existing events before streaming new ones").action(async (_opts, cmd) => {
81262
81315
  const { dashboardAction: dashboardAction2 } = await init_dashboard().then(() => dashboard_exports);
81263
81316
  return dashboardAction2(_opts, cmd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sidekick-agent-hub",
3
- "version": "0.17.0",
3
+ "version": "0.17.1",
4
4
  "description": "Terminal dashboard for monitoring AI coding agent sessions",
5
5
  "type": "module",
6
6
  "bin": {