sidekick-agent-hub 0.17.5 → 0.17.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/dist/sidekick-cli.mjs +228 -56
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,6 +95,16 @@ sidekick status
|
|
|
95
95
|
|
|
96
96
|
Check API health for both Claude (status.claude.com) and OpenAI (status.openai.com). Shows indicators with color coding (green/yellow/red), affected components, and active incident details. Use `--json` for machine-readable output. In the dashboard, provider-status surfaces are scoped to the monitored provider: Claude for Claude Code sessions, OpenAI for Codex sessions, and hidden for OpenCode.
|
|
97
97
|
|
|
98
|
+
When the active provider is `claude-code`, the output also includes a **Claude Peak Hours** block (see below).
|
|
99
|
+
|
|
100
|
+
## Peak Hours
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
sidekick peak
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Show whether Claude is currently in peak hours (weekdays 13:00–19:00 UTC — when session limits drain faster on Free/Pro/Max/Team subscriptions). Data comes from the public `promoclock.co/api/status` endpoint (third-party, unaffiliated with Anthropic). Use `--json` for machine-readable output. The peak-hours summary also appears under the bars in `sidekick quota` for Claude subscriptions.
|
|
107
|
+
|
|
98
108
|
## Quota & Rate Limits
|
|
99
109
|
|
|
100
110
|
```bash
|
|
@@ -103,7 +113,7 @@ sidekick quota
|
|
|
103
113
|
|
|
104
114
|
Provider-aware quota and rate-limit display. The command auto-detects the active provider:
|
|
105
115
|
|
|
106
|
-
- **Claude Code**: Shows Claude Max subscription quota — 5-hour and 7-day windows with color-coded progress bars, projections, and reset countdowns.
|
|
116
|
+
- **Claude Code**: Shows Claude Max subscription quota — 5-hour and 7-day windows with color-coded progress bars, projections, and reset countdowns. Includes a peak-hours summary line.
|
|
107
117
|
- **Codex**: Shows rate limits from the latest session's event stream — primary and secondary windows with progress bars and reset countdowns.
|
|
108
118
|
- **OpenCode**: Prints an informational message (no rate-limit data available).
|
|
109
119
|
|
package/dist/sidekick-cli.mjs
CHANGED
|
@@ -18485,6 +18485,7 @@ var require_quotaSnapshots = __commonJS({
|
|
|
18485
18485
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18486
18486
|
exports.writeQuotaSnapshot = writeQuotaSnapshot2;
|
|
18487
18487
|
exports.readQuotaSnapshot = readQuotaSnapshot2;
|
|
18488
|
+
var crypto = __importStar(__require("crypto"));
|
|
18488
18489
|
var fs9 = __importStar(__require("fs"));
|
|
18489
18490
|
var path8 = __importStar(__require("path"));
|
|
18490
18491
|
var paths_1 = require_paths();
|
|
@@ -18495,11 +18496,19 @@ var require_quotaSnapshots = __commonJS({
|
|
|
18495
18496
|
fs9.mkdirSync((0, paths_1.getConfigDir)(), { recursive: true, mode: 448 });
|
|
18496
18497
|
}
|
|
18497
18498
|
function atomicWriteJson(filePath, data, mode = 384) {
|
|
18498
|
-
const tmp = filePath
|
|
18499
|
+
const tmp = `${filePath}.${process.pid}.${Date.now()}.${crypto.randomBytes(8).toString("hex")}.tmp`;
|
|
18499
18500
|
const json = JSON.stringify(data, null, 2);
|
|
18500
18501
|
JSON.parse(json);
|
|
18501
|
-
|
|
18502
|
-
|
|
18502
|
+
try {
|
|
18503
|
+
fs9.writeFileSync(tmp, json, { encoding: "utf8", mode });
|
|
18504
|
+
fs9.renameSync(tmp, filePath);
|
|
18505
|
+
} catch (error) {
|
|
18506
|
+
try {
|
|
18507
|
+
fs9.rmSync(tmp, { force: true });
|
|
18508
|
+
} catch {
|
|
18509
|
+
}
|
|
18510
|
+
throw error;
|
|
18511
|
+
}
|
|
18503
18512
|
}
|
|
18504
18513
|
function readStore() {
|
|
18505
18514
|
try {
|
|
@@ -34929,6 +34938,65 @@ var require_providerStatus = __commonJS({
|
|
|
34929
34938
|
}
|
|
34930
34939
|
});
|
|
34931
34940
|
|
|
34941
|
+
// ../sidekick-shared/dist/peakHours.js
|
|
34942
|
+
var require_peakHours = __commonJS({
|
|
34943
|
+
"../sidekick-shared/dist/peakHours.js"(exports) {
|
|
34944
|
+
"use strict";
|
|
34945
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34946
|
+
exports.fetchPeakHoursStatus = fetchPeakHoursStatus4;
|
|
34947
|
+
var PROMOCLOCK_ENDPOINT = "https://promoclock.co/api/status";
|
|
34948
|
+
function unavailableState() {
|
|
34949
|
+
return {
|
|
34950
|
+
status: "unknown",
|
|
34951
|
+
isPeak: false,
|
|
34952
|
+
sessionLimitSpeed: "unknown",
|
|
34953
|
+
label: "Peak-hours status unavailable",
|
|
34954
|
+
peakHoursDescription: "",
|
|
34955
|
+
nextChange: null,
|
|
34956
|
+
minutesUntilChange: null,
|
|
34957
|
+
note: "",
|
|
34958
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34959
|
+
unavailable: true
|
|
34960
|
+
};
|
|
34961
|
+
}
|
|
34962
|
+
function normalizeStatus(raw) {
|
|
34963
|
+
if (raw === "peak" || raw === "off_peak")
|
|
34964
|
+
return raw;
|
|
34965
|
+
return "unknown";
|
|
34966
|
+
}
|
|
34967
|
+
function normalizeSpeed(raw) {
|
|
34968
|
+
if (raw === "normal" || raw === "faster")
|
|
34969
|
+
return raw;
|
|
34970
|
+
return "unknown";
|
|
34971
|
+
}
|
|
34972
|
+
async function fetchPeakHoursStatus4() {
|
|
34973
|
+
try {
|
|
34974
|
+
const res = await fetch(PROMOCLOCK_ENDPOINT);
|
|
34975
|
+
if (!res.ok)
|
|
34976
|
+
return unavailableState();
|
|
34977
|
+
const data = await res.json();
|
|
34978
|
+
const status = normalizeStatus(data.status);
|
|
34979
|
+
const sessionLimitSpeed = normalizeSpeed(data.sessionLimitSpeed);
|
|
34980
|
+
const isPeak = typeof data.isPeak === "boolean" ? data.isPeak : status === "peak";
|
|
34981
|
+
return {
|
|
34982
|
+
status,
|
|
34983
|
+
isPeak,
|
|
34984
|
+
sessionLimitSpeed,
|
|
34985
|
+
label: data.label ?? (isPeak ? "Peak Hours" : "Off-Peak"),
|
|
34986
|
+
peakHoursDescription: data.peakHours ?? "",
|
|
34987
|
+
nextChange: data.nextChange ?? null,
|
|
34988
|
+
minutesUntilChange: typeof data.minutesUntilChange === "number" ? data.minutesUntilChange : null,
|
|
34989
|
+
note: data.note ?? "",
|
|
34990
|
+
updatedAt: data.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
34991
|
+
unavailable: false
|
|
34992
|
+
};
|
|
34993
|
+
} catch {
|
|
34994
|
+
return unavailableState();
|
|
34995
|
+
}
|
|
34996
|
+
}
|
|
34997
|
+
}
|
|
34998
|
+
});
|
|
34999
|
+
|
|
34932
35000
|
// ../sidekick-shared/dist/index.js
|
|
34933
35001
|
var require_dist = __commonJS({
|
|
34934
35002
|
"../sidekick-shared/dist/index.js"(exports) {
|
|
@@ -34937,7 +35005,7 @@ var require_dist = __commonJS({
|
|
|
34937
35005
|
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;
|
|
34938
35006
|
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;
|
|
34939
35007
|
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.ensureDefaultAccounts = exports.readClaudeMaxAccessTokenSync = exports.readClaudeMaxCredentials = exports.writeActiveCredentials = exports.readActiveCredentials = exports.openInBrowser = exports.parseTranscript = exports.generateHtmlReport = exports.PatternExtractor = void 0;
|
|
34940
|
-
exports.fetchOpenAIStatus = exports.fetchProviderStatus = exports.permissionModeSchema = exports.sessionEventSchema = exports.sessionMessageSchema = exports.messageUsageSchema = exports.extractToolCalls = exports.extractTokenUsage = exports.LITELLM_CATALOG_URL = exports.normalizeLiteLlmCatalog = exports.hydratePricingCatalog = exports.formatCost = exports.calculateCostWithPricing = exports.calculateCost = void 0;
|
|
35008
|
+
exports.fetchPeakHoursStatus = exports.fetchOpenAIStatus = exports.fetchProviderStatus = exports.permissionModeSchema = exports.sessionEventSchema = exports.sessionMessageSchema = exports.messageUsageSchema = exports.extractToolCalls = exports.extractTokenUsage = exports.LITELLM_CATALOG_URL = exports.normalizeLiteLlmCatalog = exports.hydratePricingCatalog = exports.formatCost = exports.calculateCostWithPricing = exports.calculateCost = void 0;
|
|
34941
35009
|
var taskPersistence_1 = require_taskPersistence();
|
|
34942
35010
|
Object.defineProperty(exports, "TASK_PERSISTENCE_SCHEMA_VERSION", { enumerable: true, get: function() {
|
|
34943
35011
|
return taskPersistence_1.TASK_PERSISTENCE_SCHEMA_VERSION;
|
|
@@ -35492,6 +35560,10 @@ var require_dist = __commonJS({
|
|
|
35492
35560
|
Object.defineProperty(exports, "fetchOpenAIStatus", { enumerable: true, get: function() {
|
|
35493
35561
|
return providerStatus_1.fetchOpenAIStatus;
|
|
35494
35562
|
} });
|
|
35563
|
+
var peakHours_1 = require_peakHours();
|
|
35564
|
+
Object.defineProperty(exports, "fetchPeakHoursStatus", { enumerable: true, get: function() {
|
|
35565
|
+
return peakHours_1.fetchPeakHoursStatus;
|
|
35566
|
+
} });
|
|
35495
35567
|
}
|
|
35496
35568
|
});
|
|
35497
35569
|
|
|
@@ -37727,7 +37799,7 @@ var init_UpdateCheckService = __esm({
|
|
|
37727
37799
|
/** Run the update check (one-shot). */
|
|
37728
37800
|
async check() {
|
|
37729
37801
|
try {
|
|
37730
|
-
const current = "0.17.
|
|
37802
|
+
const current = "0.17.7";
|
|
37731
37803
|
const cached = this.readCache();
|
|
37732
37804
|
let latest;
|
|
37733
37805
|
if (cached && Date.now() - cached.checkedAt < CACHE_TTL_MS) {
|
|
@@ -78345,7 +78417,7 @@ function StatusBar({
|
|
|
78345
78417
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: parseBlessedTags(BRAND_INLINE) }),
|
|
78346
78418
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { dimColor: true, children: [
|
|
78347
78419
|
" v",
|
|
78348
|
-
"0.17.
|
|
78420
|
+
"0.17.7"
|
|
78349
78421
|
] }),
|
|
78350
78422
|
updateInfo && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { color: "yellow", children: [
|
|
78351
78423
|
" (v",
|
|
@@ -78735,7 +78807,7 @@ function ChangelogOverlay({ entries, scrollOffset }) {
|
|
|
78735
78807
|
" ",
|
|
78736
78808
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { bold: true, color: "cyan", children: [
|
|
78737
78809
|
"Terminal Dashboard v",
|
|
78738
|
-
"0.17.
|
|
78810
|
+
"0.17.7"
|
|
78739
78811
|
] }),
|
|
78740
78812
|
latestDate ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: "gray", children: [
|
|
78741
78813
|
" \u2014 ",
|
|
@@ -79057,7 +79129,7 @@ var init_mouse = __esm({
|
|
|
79057
79129
|
var CHANGELOG_default;
|
|
79058
79130
|
var init_CHANGELOG = __esm({
|
|
79059
79131
|
"CHANGELOG.md"() {
|
|
79060
|
-
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.5] - 2026-04-18\n\n### Added\n\n- **Default account bootstrap at CLI startup**: The CLI now calls `ensureDefaultAccounts()` from `sidekick-shared` at module load and awaits the result inside a Commander `preAction` hook, so the first real subcommand blocks briefly on the bootstrap while `--version` and `--help` stay instant. When a system Claude Code or Codex credential exists and no saved account is active for that provider yet, the CLI registers it as "Default" \u2014 `sidekick quota`, `sidekick account`, and `sidekick stats` now reflect the active account on first run without requiring an explicit `sidekick account --add` first. Idempotent, never overwrites manually saved accounts, and all errors are swallowed so startup is never blocked\n\nThanks to [@B33pBeeps](https://github.com/B33pBeeps) (Juan Fourie) for contributing this feature in [#16](https://github.com/cesarandreslopez/sidekick-agent-hub/pull/16).\n\n## [0.17.4] - 2026-04-17\n\n### Changed\n\n- **Pricing hydration import migrated to `sidekick-shared/node`**: `cli.ts` now imports `hydratePricingCatalog` from the new Node-only subpath and keeps `detectProvider` on the package root. Runtime behavior is unchanged; the split makes the CLI\'s import surface self-documenting (hydration is explicitly a Node API) and aligns the CLI with the shared library\'s new versioned public API contract\n\n## [0.17.3] - 2026-04-17\n\n### Changed\n\n- **Version sync with the VS Code extension**: Republished to keep CLI, extension, and shared-library versions aligned after a cosmetic changelog fix in 0.17.3. No CLI code changes \u2014 functionally identical to 0.17.2\n\n## [0.17.2] - 2026-04-17\n\n### Added\n\n- **LiteLLM pricing hydration on startup**: The CLI now fetches the LiteLLM pricing catalog on startup and caches to `~/.config/sidekick/pricing-catalog.json` with a 24-hour TTL, 3s timeout, and stale-cache fallback \u2014 new model prices are picked up without a CLI upgrade\n- **Expanded pricing coverage**: GPT-4o, GPT-4.1, GPT-5.x, o1, o3, and o3-mini families are now priced alongside the existing Claude entries\n- **Real-dollar Codex / Claude Code costs**: `EventAggregator` computes cost from the pricing table when the session provider doesn\'t report one, so `sidekick` live dashboards now show actual dollars for Codex and Claude Code sessions\n- **`stats` footer lists unpriced models**: `sidekick stats` prints any models encountered with no pricing entry so missing coverage is visible\n\n### Fixed\n\n- **Context-gauge % wrong for Opus 4.7 (1M) and other new models**: The dashboard\'s context gauge was dividing by 200K for Claude Opus 4.7 (native 1M), inflating the displayed %. The shared model \u2192 context-window map now includes Opus/Sonnet 4.7 (1M), GPT-5.4 (1.05M), GPT-5.3-Codex (400K), and GPT-5.3-Codex-Spark (128K). Claude Code\'s `[1m]` suffix is now also honored as an explicit 1M marker\n- **Silent Sonnet-priced fallback for unknown models**: Codex, GPT-5.x, and o-series rows were being rendered at Sonnet rates. Unknown-model rows now render as `\u2014` in yellow instead of inventing a dollar figure\n\n### Changed\n\n- **`historical-data.json` schema v2**: reads `priced` flag and `unpricedModelIds` from records written by the latest VS Code extension; v1 records still read correctly\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';
|
|
79132
|
+
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.7] - 2026-04-28\n\n### Fixed\n\n- **Quota snapshot write race**: Updated the bundled `sidekick-shared` snapshot writer so concurrent `sidekick quota` / Codex session updates no longer collide on `quota-snapshots.json.tmp` or throw `ENOENT`. Failed writes now also clean up their partial temp files instead of leaving orphans in `~/.config/sidekick/`\n\n## [0.17.6] - 2026-04-19\n\n### Added\n\n- **`sidekick peak` command**: One-shot check for Claude\'s current peak-hours state \u2014 weekdays 13:00\u201319:00 UTC, when session limits drain faster on Free/Pro/Max/Team subscriptions. Prints a color-coded status block with a countdown to the next transition. Data comes from the public `promoclock.co/api/status` endpoint (third-party, unaffiliated with Anthropic) with a graceful fallback when unreachable. `--json` emits the full raw state\n- **Peak-hours block in `sidekick status`**: When the active provider is `claude-code`, the Claude + OpenAI health blocks are now followed by a **Claude Peak Hours** block (off-peak or in-peak, with countdown). Gated on the provider so OpenCode / Codex users don\'t trigger an unnecessary third-party fetch. `--json` output includes the new `peak` field\n- **Peak-hours summary in `sidekick quota`**: Claude subscription quota output now shows a **Peak** line under the 5-hour / 7-day bars \u2014 green dot off-peak, orange dot during an active peak, with a countdown to the next transition. `--json` output includes the new `peak` field\n\n## [0.17.5] - 2026-04-18\n\n### Added\n\n- **Default account bootstrap at CLI startup**: The CLI now calls `ensureDefaultAccounts()` from `sidekick-shared` at module load and awaits the result inside a Commander `preAction` hook, so the first real subcommand blocks briefly on the bootstrap while `--version` and `--help` stay instant. When a system Claude Code or Codex credential exists and no saved account is active for that provider yet, the CLI registers it as "Default" \u2014 `sidekick quota`, `sidekick account`, and `sidekick stats` now reflect the active account on first run without requiring an explicit `sidekick account --add` first. Idempotent, never overwrites manually saved accounts, and all errors are swallowed so startup is never blocked\n\nThanks to [@B33pBeeps](https://github.com/B33pBeeps) (Juan Fourie) for contributing this feature in [#16](https://github.com/cesarandreslopez/sidekick-agent-hub/pull/16).\n\n## [0.17.4] - 2026-04-17\n\n### Changed\n\n- **Pricing hydration import migrated to `sidekick-shared/node`**: `cli.ts` now imports `hydratePricingCatalog` from the new Node-only subpath and keeps `detectProvider` on the package root. Runtime behavior is unchanged; the split makes the CLI\'s import surface self-documenting (hydration is explicitly a Node API) and aligns the CLI with the shared library\'s new versioned public API contract\n\n## [0.17.3] - 2026-04-17\n\n### Changed\n\n- **Version sync with the VS Code extension**: Republished to keep CLI, extension, and shared-library versions aligned after a cosmetic changelog fix in 0.17.3. No CLI code changes \u2014 functionally identical to 0.17.2\n\n## [0.17.2] - 2026-04-17\n\n### Added\n\n- **LiteLLM pricing hydration on startup**: The CLI now fetches the LiteLLM pricing catalog on startup and caches to `~/.config/sidekick/pricing-catalog.json` with a 24-hour TTL, 3s timeout, and stale-cache fallback \u2014 new model prices are picked up without a CLI upgrade\n- **Expanded pricing coverage**: GPT-4o, GPT-4.1, GPT-5.x, o1, o3, and o3-mini families are now priced alongside the existing Claude entries\n- **Real-dollar Codex / Claude Code costs**: `EventAggregator` computes cost from the pricing table when the session provider doesn\'t report one, so `sidekick` live dashboards now show actual dollars for Codex and Claude Code sessions\n- **`stats` footer lists unpriced models**: `sidekick stats` prints any models encountered with no pricing entry so missing coverage is visible\n\n### Fixed\n\n- **Context-gauge % wrong for Opus 4.7 (1M) and other new models**: The dashboard\'s context gauge was dividing by 200K for Claude Opus 4.7 (native 1M), inflating the displayed %. The shared model \u2192 context-window map now includes Opus/Sonnet 4.7 (1M), GPT-5.4 (1.05M), GPT-5.3-Codex (400K), and GPT-5.3-Codex-Spark (128K). Claude Code\'s `[1m]` suffix is now also honored as an explicit 1M marker\n- **Silent Sonnet-priced fallback for unknown models**: Codex, GPT-5.x, and o-series rows were being rendered at Sonnet rates. Unknown-model rows now render as `\u2014` in yellow instead of inventing a dollar figure\n\n### Changed\n\n- **`historical-data.json` schema v2**: reads `priced` flag and `unpricedModelIds` from records written by the latest VS Code extension; v1 records still read correctly\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';
|
|
79061
79133
|
}
|
|
79062
79134
|
});
|
|
79063
79135
|
|
|
@@ -81136,6 +81208,57 @@ var init_stats = __esm({
|
|
|
81136
81208
|
}
|
|
81137
81209
|
});
|
|
81138
81210
|
|
|
81211
|
+
// src/commands/peakHoursRender.ts
|
|
81212
|
+
function formatCountdown(minutes) {
|
|
81213
|
+
if (typeof minutes !== "number" || minutes <= 0) return "";
|
|
81214
|
+
const h = Math.floor(minutes / 60);
|
|
81215
|
+
const m = minutes % 60;
|
|
81216
|
+
return h > 0 ? `${h}h ${m}m` : `${m}m`;
|
|
81217
|
+
}
|
|
81218
|
+
function printPeakHoursBlock(state) {
|
|
81219
|
+
process.stdout.write(source_default.bold("Claude Peak Hours\n"));
|
|
81220
|
+
process.stdout.write(source_default.dim("\u2500".repeat(50) + "\n"));
|
|
81221
|
+
if (state.unavailable) {
|
|
81222
|
+
process.stdout.write(source_default.dim(" Peak-hours status unavailable (promoclock.co unreachable).\n"));
|
|
81223
|
+
return;
|
|
81224
|
+
}
|
|
81225
|
+
const color = state.isPeak ? source_default.hex("#E59C4F") : source_default.green;
|
|
81226
|
+
const dot = "\u25CF";
|
|
81227
|
+
process.stdout.write(` ${color(dot)} ${color(state.label || (state.isPeak ? "Peak" : "Off-Peak"))}
|
|
81228
|
+
`);
|
|
81229
|
+
const countdown = formatCountdown(state.minutesUntilChange);
|
|
81230
|
+
if (countdown) {
|
|
81231
|
+
const label = state.isPeak ? "Off-peak in" : "Next peak in";
|
|
81232
|
+
process.stdout.write(source_default.dim(` ${label} ${countdown}
|
|
81233
|
+
`));
|
|
81234
|
+
}
|
|
81235
|
+
if (state.peakHoursDescription) {
|
|
81236
|
+
process.stdout.write(source_default.dim(` ${state.peakHoursDescription}
|
|
81237
|
+
`));
|
|
81238
|
+
}
|
|
81239
|
+
if (state.note) {
|
|
81240
|
+
process.stdout.write(source_default.dim(` ${state.note}
|
|
81241
|
+
`));
|
|
81242
|
+
}
|
|
81243
|
+
process.stdout.write(source_default.dim(" Source: promoclock.co (third-party, unaffiliated with Anthropic)\n"));
|
|
81244
|
+
}
|
|
81245
|
+
function formatPeakHoursLine(state) {
|
|
81246
|
+
if (state.unavailable) return "";
|
|
81247
|
+
const countdown = formatCountdown(state.minutesUntilChange);
|
|
81248
|
+
if (state.isPeak) {
|
|
81249
|
+
const suffix2 = countdown ? ` ${source_default.dim("(off-peak in " + countdown + ")")}` : "";
|
|
81250
|
+
return `${source_default.hex("#E59C4F")("\u25CF")} ${source_default.hex("#E59C4F")(state.label || "Peak Hours \u2014 Faster Drain")}${suffix2}`;
|
|
81251
|
+
}
|
|
81252
|
+
const suffix = countdown ? ` ${source_default.dim("(peak in " + countdown + ")")}` : "";
|
|
81253
|
+
return `${source_default.green("\u25CF")} ${source_default.green(state.label || "Off-Peak \u2014 Normal Speed")}${suffix}`;
|
|
81254
|
+
}
|
|
81255
|
+
var init_peakHoursRender = __esm({
|
|
81256
|
+
"src/commands/peakHoursRender.ts"() {
|
|
81257
|
+
"use strict";
|
|
81258
|
+
init_source();
|
|
81259
|
+
}
|
|
81260
|
+
});
|
|
81261
|
+
|
|
81139
81262
|
// src/commands/quota.ts
|
|
81140
81263
|
var quota_exports = {};
|
|
81141
81264
|
__export(quota_exports, {
|
|
@@ -81198,10 +81321,13 @@ async function quotaAction(_opts, cmd) {
|
|
|
81198
81321
|
}
|
|
81199
81322
|
async function claudeQuotaAction(jsonOutput) {
|
|
81200
81323
|
const service = new QuotaService();
|
|
81201
|
-
const quota = await
|
|
81324
|
+
const [quota, peak] = await Promise.all([
|
|
81325
|
+
service.fetchOnce(),
|
|
81326
|
+
(0, import_sidekick_shared28.fetchPeakHoursStatus)()
|
|
81327
|
+
]);
|
|
81202
81328
|
if (!quota.available) {
|
|
81203
81329
|
if (jsonOutput) {
|
|
81204
|
-
process.stdout.write(JSON.stringify(quota, null, 2) + "\n");
|
|
81330
|
+
process.stdout.write(JSON.stringify({ ...quota, peak }, null, 2) + "\n");
|
|
81205
81331
|
return;
|
|
81206
81332
|
}
|
|
81207
81333
|
const descriptor = (0, import_sidekick_shared28.describeQuotaFailure)(quota);
|
|
@@ -81229,7 +81355,7 @@ async function claudeQuotaAction(jsonOutput) {
|
|
|
81229
81355
|
process.exit(1);
|
|
81230
81356
|
}
|
|
81231
81357
|
if (jsonOutput) {
|
|
81232
|
-
process.stdout.write(JSON.stringify(quota, null, 2) + "\n");
|
|
81358
|
+
process.stdout.write(JSON.stringify({ ...quota, peak }, null, 2) + "\n");
|
|
81233
81359
|
return;
|
|
81234
81360
|
}
|
|
81235
81361
|
const barWidth = 30;
|
|
@@ -81249,6 +81375,13 @@ async function claudeQuotaAction(jsonOutput) {
|
|
|
81249
81375
|
process.stdout.write(` ${source_default.dim("5-Hour")} ${makeChalkBar(fivePct, barWidth)} ${String(fivePct).padStart(3)}%${fiveProj} ${source_default.dim("resets " + fiveReset)}
|
|
81250
81376
|
`);
|
|
81251
81377
|
process.stdout.write(` ${source_default.dim("7-Day")} ${makeChalkBar(sevenPct, barWidth)} ${String(sevenPct).padStart(3)}%${sevenProj} ${source_default.dim("resets " + sevenReset)}
|
|
81378
|
+
`);
|
|
81379
|
+
printPeakHoursSummary(peak);
|
|
81380
|
+
}
|
|
81381
|
+
function printPeakHoursSummary(peak) {
|
|
81382
|
+
const line = formatPeakHoursLine(peak);
|
|
81383
|
+
if (!line) return;
|
|
81384
|
+
process.stdout.write(` ${source_default.dim("Peak")} ${line}
|
|
81252
81385
|
`);
|
|
81253
81386
|
}
|
|
81254
81387
|
async function codexQuotaAction(provider, globalOpts, jsonOutput) {
|
|
@@ -81343,6 +81476,7 @@ var init_quota = __esm({
|
|
|
81343
81476
|
import_sidekick_shared28 = __toESM(require_dist(), 1);
|
|
81344
81477
|
init_cli();
|
|
81345
81478
|
init_QuotaService();
|
|
81479
|
+
init_peakHoursRender();
|
|
81346
81480
|
}
|
|
81347
81481
|
});
|
|
81348
81482
|
|
|
@@ -81389,17 +81523,24 @@ function printStatus(label, statusPageHost, status) {
|
|
|
81389
81523
|
async function statusAction(_opts, cmd) {
|
|
81390
81524
|
const globalOpts = cmd.parent.opts();
|
|
81391
81525
|
const jsonOutput = !!globalOpts.json;
|
|
81392
|
-
const
|
|
81526
|
+
const providerId = resolveProviderId(globalOpts);
|
|
81527
|
+
const wantsPeak = providerId === "claude-code";
|
|
81528
|
+
const [claude, openai, peak] = await Promise.all([
|
|
81393
81529
|
(0, import_sidekick_shared29.fetchProviderStatus)(),
|
|
81394
|
-
(0, import_sidekick_shared29.fetchOpenAIStatus)()
|
|
81530
|
+
(0, import_sidekick_shared29.fetchOpenAIStatus)(),
|
|
81531
|
+
wantsPeak ? (0, import_sidekick_shared29.fetchPeakHoursStatus)() : Promise.resolve(null)
|
|
81395
81532
|
]);
|
|
81396
81533
|
if (jsonOutput) {
|
|
81397
|
-
process.stdout.write(JSON.stringify({ claude, openai }, null, 2) + "\n");
|
|
81534
|
+
process.stdout.write(JSON.stringify({ claude, openai, peak }, null, 2) + "\n");
|
|
81398
81535
|
return;
|
|
81399
81536
|
}
|
|
81400
81537
|
printStatus("Claude API Status", "status.claude.com", claude);
|
|
81401
81538
|
process.stdout.write("\n");
|
|
81402
81539
|
printStatus("OpenAI API Status", "status.openai.com", openai);
|
|
81540
|
+
if (peak) {
|
|
81541
|
+
process.stdout.write("\n");
|
|
81542
|
+
printPeakHoursBlock(peak);
|
|
81543
|
+
}
|
|
81403
81544
|
}
|
|
81404
81545
|
var import_sidekick_shared29;
|
|
81405
81546
|
var init_status = __esm({
|
|
@@ -81407,6 +81548,32 @@ var init_status = __esm({
|
|
|
81407
81548
|
"use strict";
|
|
81408
81549
|
init_source();
|
|
81409
81550
|
import_sidekick_shared29 = __toESM(require_dist(), 1);
|
|
81551
|
+
init_peakHoursRender();
|
|
81552
|
+
init_cli();
|
|
81553
|
+
}
|
|
81554
|
+
});
|
|
81555
|
+
|
|
81556
|
+
// src/commands/peak.ts
|
|
81557
|
+
var peak_exports = {};
|
|
81558
|
+
__export(peak_exports, {
|
|
81559
|
+
peakAction: () => peakAction
|
|
81560
|
+
});
|
|
81561
|
+
async function peakAction(_opts, cmd) {
|
|
81562
|
+
const globalOpts = cmd.parent.opts();
|
|
81563
|
+
const jsonOutput = !!globalOpts.json;
|
|
81564
|
+
const state = await (0, import_sidekick_shared30.fetchPeakHoursStatus)();
|
|
81565
|
+
if (jsonOutput) {
|
|
81566
|
+
process.stdout.write(JSON.stringify(state, null, 2) + "\n");
|
|
81567
|
+
return;
|
|
81568
|
+
}
|
|
81569
|
+
printPeakHoursBlock(state);
|
|
81570
|
+
}
|
|
81571
|
+
var import_sidekick_shared30;
|
|
81572
|
+
var init_peak = __esm({
|
|
81573
|
+
"src/commands/peak.ts"() {
|
|
81574
|
+
"use strict";
|
|
81575
|
+
import_sidekick_shared30 = __toESM(require_dist(), 1);
|
|
81576
|
+
init_peakHoursRender();
|
|
81410
81577
|
}
|
|
81411
81578
|
});
|
|
81412
81579
|
|
|
@@ -81437,13 +81604,13 @@ async function accountAction(_opts, cmd) {
|
|
|
81437
81604
|
}
|
|
81438
81605
|
function claudeAccountAction(opts, jsonOutput) {
|
|
81439
81606
|
if (opts.add) {
|
|
81440
|
-
const result = (0,
|
|
81607
|
+
const result = (0, import_sidekick_shared31.addCurrentAccount)(opts.label);
|
|
81441
81608
|
if (!result.success) {
|
|
81442
81609
|
process.stderr.write(source_default.red(result.error ?? "Failed to save account.") + "\n");
|
|
81443
81610
|
process.exit(1);
|
|
81444
81611
|
return;
|
|
81445
81612
|
}
|
|
81446
|
-
const active2 = (0,
|
|
81613
|
+
const active2 = (0, import_sidekick_shared31.readActiveClaudeAccount)();
|
|
81447
81614
|
if (jsonOutput) {
|
|
81448
81615
|
process.stdout.write(JSON.stringify({ action: "added", provider: "claude-code", email: active2?.email, label: opts.label }) + "\n");
|
|
81449
81616
|
} else {
|
|
@@ -81452,14 +81619,14 @@ function claudeAccountAction(opts, jsonOutput) {
|
|
|
81452
81619
|
return;
|
|
81453
81620
|
}
|
|
81454
81621
|
if (opts.remove) {
|
|
81455
|
-
const accounts2 = (0,
|
|
81622
|
+
const accounts2 = (0, import_sidekick_shared31.listAccounts)();
|
|
81456
81623
|
const target = findClaudeAccount(opts.remove, accounts2);
|
|
81457
81624
|
if (!target) {
|
|
81458
81625
|
process.stderr.write(source_default.red(`Account "${opts.remove}" not found.`) + "\n");
|
|
81459
81626
|
process.exit(1);
|
|
81460
81627
|
return;
|
|
81461
81628
|
}
|
|
81462
|
-
const result = (0,
|
|
81629
|
+
const result = (0, import_sidekick_shared31.removeAccount)(target.uuid);
|
|
81463
81630
|
if (!result.success) {
|
|
81464
81631
|
process.stderr.write(source_default.red(result.error ?? "Failed to remove account.") + "\n");
|
|
81465
81632
|
process.exit(1);
|
|
@@ -81473,14 +81640,14 @@ function claudeAccountAction(opts, jsonOutput) {
|
|
|
81473
81640
|
return;
|
|
81474
81641
|
}
|
|
81475
81642
|
if (opts.switchTo) {
|
|
81476
|
-
const accounts2 = (0,
|
|
81643
|
+
const accounts2 = (0, import_sidekick_shared31.listAccounts)();
|
|
81477
81644
|
const target = findClaudeAccount(opts.switchTo, accounts2);
|
|
81478
81645
|
if (!target) {
|
|
81479
81646
|
process.stderr.write(source_default.red(`Account "${opts.switchTo}" not found.`) + "\n");
|
|
81480
81647
|
process.exit(1);
|
|
81481
81648
|
return;
|
|
81482
81649
|
}
|
|
81483
|
-
const result = (0,
|
|
81650
|
+
const result = (0, import_sidekick_shared31.switchToAccount)(target.uuid);
|
|
81484
81651
|
if (!result.success) {
|
|
81485
81652
|
process.stderr.write(source_default.red(result.error ?? "Failed to switch.") + "\n");
|
|
81486
81653
|
process.exit(1);
|
|
@@ -81494,17 +81661,17 @@ function claudeAccountAction(opts, jsonOutput) {
|
|
|
81494
81661
|
return;
|
|
81495
81662
|
}
|
|
81496
81663
|
if (opts.switch) {
|
|
81497
|
-
const accounts2 = (0,
|
|
81664
|
+
const accounts2 = (0, import_sidekick_shared31.listAccounts)();
|
|
81498
81665
|
if (accounts2.length < 2) {
|
|
81499
81666
|
process.stderr.write(source_default.yellow("Need at least 2 saved accounts to switch.") + "\n");
|
|
81500
81667
|
process.exit(1);
|
|
81501
81668
|
return;
|
|
81502
81669
|
}
|
|
81503
|
-
const active2 = (0,
|
|
81670
|
+
const active2 = (0, import_sidekick_shared31.getActiveAccount)();
|
|
81504
81671
|
const currentIdx = active2 ? accounts2.findIndex((a) => a.uuid === active2.uuid) : -1;
|
|
81505
81672
|
const nextIdx = (currentIdx + 1) % accounts2.length;
|
|
81506
81673
|
const target = accounts2[nextIdx];
|
|
81507
|
-
const result = (0,
|
|
81674
|
+
const result = (0, import_sidekick_shared31.switchToAccount)(target.uuid);
|
|
81508
81675
|
if (!result.success) {
|
|
81509
81676
|
process.stderr.write(source_default.red(result.error ?? "Failed to switch.") + "\n");
|
|
81510
81677
|
process.exit(1);
|
|
@@ -81517,9 +81684,9 @@ function claudeAccountAction(opts, jsonOutput) {
|
|
|
81517
81684
|
}
|
|
81518
81685
|
return;
|
|
81519
81686
|
}
|
|
81520
|
-
const accounts = (0,
|
|
81687
|
+
const accounts = (0, import_sidekick_shared31.listAccounts)();
|
|
81521
81688
|
if (accounts.length === 0) {
|
|
81522
|
-
const current = (0,
|
|
81689
|
+
const current = (0, import_sidekick_shared31.readActiveClaudeAccount)();
|
|
81523
81690
|
if (jsonOutput) {
|
|
81524
81691
|
process.stdout.write(JSON.stringify({ provider: "claude-code", accounts: [], current: current ?? null }) + "\n");
|
|
81525
81692
|
} else if (current) {
|
|
@@ -81531,14 +81698,14 @@ function claudeAccountAction(opts, jsonOutput) {
|
|
|
81531
81698
|
return;
|
|
81532
81699
|
}
|
|
81533
81700
|
if (jsonOutput) {
|
|
81534
|
-
const active2 = (0,
|
|
81701
|
+
const active2 = (0, import_sidekick_shared31.getActiveAccount)();
|
|
81535
81702
|
process.stdout.write(JSON.stringify({
|
|
81536
81703
|
provider: "claude-code",
|
|
81537
81704
|
accounts: accounts.map((a) => ({ ...a, active: a.uuid === active2?.uuid }))
|
|
81538
81705
|
}, null, 2) + "\n");
|
|
81539
81706
|
return;
|
|
81540
81707
|
}
|
|
81541
|
-
const active = (0,
|
|
81708
|
+
const active = (0, import_sidekick_shared31.getActiveAccount)();
|
|
81542
81709
|
process.stdout.write(source_default.bold("Claude Accounts\n"));
|
|
81543
81710
|
process.stdout.write(source_default.dim("\u2500".repeat(50) + "\n"));
|
|
81544
81711
|
for (const account of accounts) {
|
|
@@ -81585,7 +81752,7 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81585
81752
|
process.exit(1);
|
|
81586
81753
|
return;
|
|
81587
81754
|
}
|
|
81588
|
-
const prepared = (0,
|
|
81755
|
+
const prepared = (0, import_sidekick_shared31.prepareCodexAccount)(opts.label);
|
|
81589
81756
|
if (!prepared.success) {
|
|
81590
81757
|
process.stderr.write(source_default.red(prepared.error ?? "Failed to prepare Codex account.") + "\n");
|
|
81591
81758
|
process.exit(1);
|
|
@@ -81603,14 +81770,14 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81603
81770
|
process.exit(1);
|
|
81604
81771
|
return;
|
|
81605
81772
|
}
|
|
81606
|
-
const finalized = (0,
|
|
81773
|
+
const finalized = (0, import_sidekick_shared31.finalizeCodexAccount)(prepared.profileId);
|
|
81607
81774
|
if (!finalized.success) {
|
|
81608
81775
|
process.stderr.write(source_default.red(finalized.error ?? "Failed to finalize Codex account.") + "\n");
|
|
81609
81776
|
process.exit(1);
|
|
81610
81777
|
return;
|
|
81611
81778
|
}
|
|
81612
81779
|
}
|
|
81613
|
-
const active2 = (0,
|
|
81780
|
+
const active2 = (0, import_sidekick_shared31.getActiveCodexAccount)();
|
|
81614
81781
|
if (jsonOutput) {
|
|
81615
81782
|
process.stdout.write(JSON.stringify({
|
|
81616
81783
|
action: "added",
|
|
@@ -81626,14 +81793,14 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81626
81793
|
return;
|
|
81627
81794
|
}
|
|
81628
81795
|
if (opts.remove) {
|
|
81629
|
-
const accounts2 = (0,
|
|
81796
|
+
const accounts2 = (0, import_sidekick_shared31.listCodexAccounts)();
|
|
81630
81797
|
const target = findCodexAccount(opts.remove, accounts2);
|
|
81631
81798
|
if (!target) {
|
|
81632
81799
|
process.stderr.write(source_default.red(`Codex account "${opts.remove}" not found.`) + "\n");
|
|
81633
81800
|
process.exit(1);
|
|
81634
81801
|
return;
|
|
81635
81802
|
}
|
|
81636
|
-
const result = (0,
|
|
81803
|
+
const result = (0, import_sidekick_shared31.removeCodexAccount)(target.id);
|
|
81637
81804
|
if (!result.success) {
|
|
81638
81805
|
process.stderr.write(source_default.red(result.error ?? "Failed to remove Codex account.") + "\n");
|
|
81639
81806
|
process.exit(1);
|
|
@@ -81647,14 +81814,14 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81647
81814
|
return;
|
|
81648
81815
|
}
|
|
81649
81816
|
if (opts.switchTo) {
|
|
81650
|
-
const accounts2 = (0,
|
|
81817
|
+
const accounts2 = (0, import_sidekick_shared31.listCodexAccounts)();
|
|
81651
81818
|
const target = findCodexAccount(opts.switchTo, accounts2);
|
|
81652
81819
|
if (!target) {
|
|
81653
81820
|
process.stderr.write(source_default.red(`Codex account "${opts.switchTo}" not found.`) + "\n");
|
|
81654
81821
|
process.exit(1);
|
|
81655
81822
|
return;
|
|
81656
81823
|
}
|
|
81657
|
-
const result = (0,
|
|
81824
|
+
const result = (0, import_sidekick_shared31.switchToCodexAccount)(target.id);
|
|
81658
81825
|
if (!result.success) {
|
|
81659
81826
|
process.stderr.write(source_default.red(result.error ?? "Failed to switch Codex account.") + "\n");
|
|
81660
81827
|
process.exit(1);
|
|
@@ -81668,17 +81835,17 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81668
81835
|
return;
|
|
81669
81836
|
}
|
|
81670
81837
|
if (opts.switch) {
|
|
81671
|
-
const accounts2 = (0,
|
|
81838
|
+
const accounts2 = (0, import_sidekick_shared31.listCodexAccounts)();
|
|
81672
81839
|
if (accounts2.length < 2) {
|
|
81673
81840
|
process.stderr.write(source_default.yellow("Need at least 2 saved Codex accounts to switch.") + "\n");
|
|
81674
81841
|
process.exit(1);
|
|
81675
81842
|
return;
|
|
81676
81843
|
}
|
|
81677
|
-
const active2 = (0,
|
|
81844
|
+
const active2 = (0, import_sidekick_shared31.getActiveCodexAccount)();
|
|
81678
81845
|
const currentIdx = active2 ? accounts2.findIndex((account) => account.id === active2.id) : -1;
|
|
81679
81846
|
const nextIdx = (currentIdx + 1) % accounts2.length;
|
|
81680
81847
|
const target = accounts2[nextIdx];
|
|
81681
|
-
const result = (0,
|
|
81848
|
+
const result = (0, import_sidekick_shared31.switchToCodexAccount)(target.id);
|
|
81682
81849
|
if (!result.success) {
|
|
81683
81850
|
process.stderr.write(source_default.red(result.error ?? "Failed to switch Codex account.") + "\n");
|
|
81684
81851
|
process.exit(1);
|
|
@@ -81691,7 +81858,7 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81691
81858
|
}
|
|
81692
81859
|
return;
|
|
81693
81860
|
}
|
|
81694
|
-
const accounts = (0,
|
|
81861
|
+
const accounts = (0, import_sidekick_shared31.listCodexAccounts)();
|
|
81695
81862
|
if (accounts.length === 0) {
|
|
81696
81863
|
if (jsonOutput) {
|
|
81697
81864
|
process.stdout.write(JSON.stringify({ provider: "codex", accounts: [], current: null }) + "\n");
|
|
@@ -81701,7 +81868,7 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81701
81868
|
return;
|
|
81702
81869
|
}
|
|
81703
81870
|
if (jsonOutput) {
|
|
81704
|
-
const active2 = (0,
|
|
81871
|
+
const active2 = (0, import_sidekick_shared31.getActiveCodexAccount)();
|
|
81705
81872
|
process.stdout.write(JSON.stringify({
|
|
81706
81873
|
provider: "codex",
|
|
81707
81874
|
accounts: accounts.map((account) => ({
|
|
@@ -81711,7 +81878,7 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81711
81878
|
}, null, 2) + "\n");
|
|
81712
81879
|
return;
|
|
81713
81880
|
}
|
|
81714
|
-
const active = (0,
|
|
81881
|
+
const active = (0, import_sidekick_shared31.getActiveCodexAccount)();
|
|
81715
81882
|
process.stdout.write(source_default.bold("Codex Accounts\n"));
|
|
81716
81883
|
process.stdout.write(source_default.dim("\u2500".repeat(50) + "\n"));
|
|
81717
81884
|
for (const account of accounts) {
|
|
@@ -81722,12 +81889,12 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81722
81889
|
`);
|
|
81723
81890
|
}
|
|
81724
81891
|
}
|
|
81725
|
-
var
|
|
81892
|
+
var import_sidekick_shared31;
|
|
81726
81893
|
var init_account = __esm({
|
|
81727
81894
|
"src/commands/account.ts"() {
|
|
81728
81895
|
"use strict";
|
|
81729
81896
|
init_source();
|
|
81730
|
-
|
|
81897
|
+
import_sidekick_shared31 = __toESM(require_dist(), 1);
|
|
81731
81898
|
init_cli();
|
|
81732
81899
|
}
|
|
81733
81900
|
});
|
|
@@ -81742,12 +81909,12 @@ async function handoffAction(_opts, cmd) {
|
|
|
81742
81909
|
const workspacePath = globalOpts.project || process.cwd();
|
|
81743
81910
|
const jsonOutput = !!globalOpts.json;
|
|
81744
81911
|
try {
|
|
81745
|
-
const rawSlug = (0,
|
|
81746
|
-
const resolvedSlug = (0,
|
|
81912
|
+
const rawSlug = (0, import_sidekick_shared32.getProjectSlugRaw)(workspacePath);
|
|
81913
|
+
const resolvedSlug = (0, import_sidekick_shared32.getProjectSlug)(workspacePath);
|
|
81747
81914
|
const slugs = rawSlug !== resolvedSlug ? [rawSlug, resolvedSlug] : [rawSlug];
|
|
81748
81915
|
let content = null;
|
|
81749
81916
|
for (const slug of slugs) {
|
|
81750
|
-
content = await (0,
|
|
81917
|
+
content = await (0, import_sidekick_shared32.readLatestHandoff)(slug);
|
|
81751
81918
|
if (content) break;
|
|
81752
81919
|
}
|
|
81753
81920
|
if (!content) {
|
|
@@ -81772,12 +81939,12 @@ async function handoffAction(_opts, cmd) {
|
|
|
81772
81939
|
process.exit(1);
|
|
81773
81940
|
}
|
|
81774
81941
|
}
|
|
81775
|
-
var
|
|
81942
|
+
var import_sidekick_shared32;
|
|
81776
81943
|
var init_handoff = __esm({
|
|
81777
81944
|
"src/commands/handoff.ts"() {
|
|
81778
81945
|
"use strict";
|
|
81779
81946
|
init_source();
|
|
81780
|
-
|
|
81947
|
+
import_sidekick_shared32 = __toESM(require_dist(), 1);
|
|
81781
81948
|
}
|
|
81782
81949
|
});
|
|
81783
81950
|
|
|
@@ -81791,35 +81958,35 @@ function resolveProviderId(opts, defaultProvider = "auto") {
|
|
|
81791
81958
|
if (defaultProvider !== "auto") {
|
|
81792
81959
|
return defaultProvider;
|
|
81793
81960
|
}
|
|
81794
|
-
return (0,
|
|
81961
|
+
return (0, import_sidekick_shared33.detectProvider)();
|
|
81795
81962
|
}
|
|
81796
81963
|
function resolveProvider(opts) {
|
|
81797
81964
|
const id = resolveProviderId(opts);
|
|
81798
81965
|
switch (id) {
|
|
81799
81966
|
case "opencode":
|
|
81800
|
-
return new
|
|
81967
|
+
return new import_sidekick_shared34.OpenCodeProvider();
|
|
81801
81968
|
case "codex":
|
|
81802
|
-
return new
|
|
81969
|
+
return new import_sidekick_shared34.CodexProvider();
|
|
81803
81970
|
case "claude-code":
|
|
81804
81971
|
default:
|
|
81805
|
-
return new
|
|
81972
|
+
return new import_sidekick_shared34.ClaudeCodeProvider();
|
|
81806
81973
|
}
|
|
81807
81974
|
}
|
|
81808
|
-
var
|
|
81975
|
+
var import_sidekick_shared33, import_node, import_sidekick_shared34, defaultAccountsReady, program2, dashCmd, dumpCmd, ctxCmd, reportCmd, searchCmd, tasksCmd, decisionsCmd, notesCmd, statsCmd, quotaCmd, statusCmd, peakCmd, accountCmd, handoffCmd;
|
|
81809
81976
|
var init_cli = __esm({
|
|
81810
81977
|
"src/cli.ts"() {
|
|
81811
81978
|
init_esm();
|
|
81812
|
-
import_sidekick_shared32 = __toESM(require_dist(), 1);
|
|
81813
|
-
import_node = __toESM(require_node(), 1);
|
|
81814
81979
|
import_sidekick_shared33 = __toESM(require_dist(), 1);
|
|
81980
|
+
import_node = __toESM(require_node(), 1);
|
|
81981
|
+
import_sidekick_shared34 = __toESM(require_dist(), 1);
|
|
81815
81982
|
(0, import_node.hydratePricingCatalog)({
|
|
81816
81983
|
cacheDir: path7.join(os5.homedir(), ".config", "sidekick")
|
|
81817
81984
|
}).catch(() => {
|
|
81818
81985
|
});
|
|
81819
|
-
defaultAccountsReady = (0,
|
|
81986
|
+
defaultAccountsReady = (0, import_sidekick_shared33.ensureDefaultAccounts)().catch(() => {
|
|
81820
81987
|
});
|
|
81821
81988
|
program2 = new Command();
|
|
81822
|
-
program2.name("sidekick").description("Query Sidekick project intelligence from the command line").version("0.17.
|
|
81989
|
+
program2.name("sidekick").description("Query Sidekick project intelligence from the command line").version("0.17.7").option("--json", "Output as JSON").option("--project <path>", "Override project path (default: cwd)").option("--provider <id>", "Provider: claude-code, opencode, codex, auto (default: auto)");
|
|
81823
81990
|
program2.hook("preAction", async () => {
|
|
81824
81991
|
await defaultAccountsReady;
|
|
81825
81992
|
});
|
|
@@ -81879,6 +82046,11 @@ var init_cli = __esm({
|
|
|
81879
82046
|
return statusAction2(_opts, cmd);
|
|
81880
82047
|
});
|
|
81881
82048
|
program2.addCommand(statusCmd);
|
|
82049
|
+
peakCmd = new Command("peak").description("Show whether Claude is currently in peak hours (faster session-limit drain)").action(async (_opts, cmd) => {
|
|
82050
|
+
const { peakAction: peakAction2 } = await Promise.resolve().then(() => (init_peak(), peak_exports));
|
|
82051
|
+
return peakAction2(_opts, cmd);
|
|
82052
|
+
});
|
|
82053
|
+
program2.addCommand(peakCmd);
|
|
81882
82054
|
accountCmd = new Command("account").description("Manage saved accounts (list, add, switch, remove)").option("--provider <id>", "Provider: claude-code, codex, auto (default: claude-code)").option("--add", "Save the currently signed-in account").option("--label <name>", "Label for the account (required for Codex, optional for Claude)").option("--switch", "Switch to the next saved account").option("--switch-to <identifier>", "Switch to a specific account by email, label, or id").option("--remove <identifier>", "Remove a saved account by email, label, or id").action(async (_opts, cmd) => {
|
|
81883
82055
|
const { accountAction: accountAction2 } = await Promise.resolve().then(() => (init_account(), account_exports));
|
|
81884
82056
|
return accountAction2(_opts, cmd);
|