claude-threads 1.35.1 → 1.36.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.
@@ -12676,6 +12676,77 @@ var init_emoji = __esm(() => {
12676
12676
  ALLOW_ALL_EMOJIS = ["white_check_mark", "heavy_check_mark"];
12677
12677
  });
12678
12678
 
12679
+ // src/utils/logger.ts
12680
+ function createLogger(component, useStderr = false, sessionId) {
12681
+ const isDebug = () => process.env.DEBUG === "1";
12682
+ const consoleLog = useStderr ? console.error : console.log;
12683
+ const paddedComponent = component.length > COMPONENT_WIDTH ? component.substring(0, COMPONENT_WIDTH) : component.padEnd(COMPONENT_WIDTH);
12684
+ const formatMessage = (msg, args) => {
12685
+ if (args.length === 0)
12686
+ return msg;
12687
+ return `${msg} ${args.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")}`;
12688
+ };
12689
+ const DEFAULT_JSON_MAX_LEN = 60;
12690
+ return {
12691
+ debug: (msg, ...args) => {
12692
+ if (isDebug()) {
12693
+ const fullMsg = formatMessage(msg, args);
12694
+ if (globalLogHandler) {
12695
+ globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
12696
+ } else {
12697
+ consoleLog(`[${paddedComponent}] ${fullMsg}`);
12698
+ }
12699
+ }
12700
+ },
12701
+ debugJson: (label, data, maxLen = DEFAULT_JSON_MAX_LEN) => {
12702
+ if (isDebug()) {
12703
+ const json = JSON.stringify(data);
12704
+ const truncated = json.length > maxLen ? `${json.substring(0, maxLen)}…` : json;
12705
+ const fullMsg = `${label}: ${truncated}`;
12706
+ if (globalLogHandler) {
12707
+ globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
12708
+ } else {
12709
+ consoleLog(`[${paddedComponent}] ${fullMsg}`);
12710
+ }
12711
+ }
12712
+ },
12713
+ info: (msg, ...args) => {
12714
+ const fullMsg = formatMessage(msg, args);
12715
+ if (globalLogHandler) {
12716
+ globalLogHandler("info", paddedComponent, fullMsg, sessionId);
12717
+ } else {
12718
+ consoleLog(`[${paddedComponent}] ${fullMsg}`);
12719
+ }
12720
+ },
12721
+ warn: (msg, ...args) => {
12722
+ const fullMsg = formatMessage(msg, args);
12723
+ if (globalLogHandler) {
12724
+ globalLogHandler("warn", paddedComponent, fullMsg, sessionId);
12725
+ } else {
12726
+ console.warn(`[${paddedComponent}] ⚠️ ${fullMsg}`);
12727
+ }
12728
+ },
12729
+ error: (msg, err) => {
12730
+ const fullMsg = err && isDebug() ? `${msg}
12731
+ ${err.stack || err.message}` : msg;
12732
+ if (globalLogHandler) {
12733
+ globalLogHandler("error", paddedComponent, fullMsg, sessionId);
12734
+ } else {
12735
+ console.error(`[${paddedComponent}] ❌ ${msg}`);
12736
+ if (err && isDebug()) {
12737
+ console.error(err);
12738
+ }
12739
+ }
12740
+ },
12741
+ forSession: (sid) => createLogger(component, useStderr, sid)
12742
+ };
12743
+ }
12744
+ var globalLogHandler = null, COMPONENT_WIDTH = 10, mcpLogger, wsLogger;
12745
+ var init_logger = __esm(() => {
12746
+ mcpLogger = createLogger("MCP", true);
12747
+ wsLogger = createLogger("ws", false);
12748
+ });
12749
+
12679
12750
  // node_modules/semver/internal/constants.js
12680
12751
  var require_constants = __commonJS(function(exports, module) {
12681
12752
  var SEMVER_SPEC_VERSION = "2.0.0";
@@ -14521,8 +14592,71 @@ var require_semver2 = __commonJS(function(exports, module) {
14521
14592
  });
14522
14593
 
14523
14594
  // src/claude/version-check.ts
14595
+ import { execSync } from "child_process";
14596
+ import { existsSync as existsSync2 } from "fs";
14524
14597
  import { join } from "path";
14525
- var import_semver, COMMON_CLAUDE_PATHS;
14598
+ function tryClaudeVersion(claudePath) {
14599
+ try {
14600
+ const output = execSync(`"${claudePath}" --version`, {
14601
+ encoding: "utf8",
14602
+ timeout: 5000,
14603
+ stdio: ["pipe", "pipe", "pipe"]
14604
+ }).trim();
14605
+ const patterns = [
14606
+ /^([\d]+\.[\d]+\.[\d]+)/,
14607
+ /version\s+([\d]+\.[\d]+\.[\d]+)/i,
14608
+ /v?([\d]+\.[\d]+\.[\d]+)/
14609
+ ];
14610
+ for (const pattern of patterns) {
14611
+ const match = output.match(pattern);
14612
+ if (match) {
14613
+ return { version: match[1], rawOutput: output, error: null, foundAt: claudePath };
14614
+ }
14615
+ }
14616
+ return { version: null, rawOutput: output, error: null, foundAt: claudePath };
14617
+ } catch (err) {
14618
+ const errorMessage = err instanceof Error ? err.message : "Unknown error";
14619
+ return { version: null, rawOutput: null, error: errorMessage };
14620
+ }
14621
+ }
14622
+ function findClaudeInPath() {
14623
+ try {
14624
+ const findCommand = process.platform === "win32" ? "where claude" : "which claude";
14625
+ const result = execSync(findCommand, {
14626
+ encoding: "utf8",
14627
+ timeout: 5000,
14628
+ stdio: ["pipe", "pipe", "pipe"]
14629
+ }).trim();
14630
+ const firstLine = result.split(/\r?\n/)[0];
14631
+ return firstLine || null;
14632
+ } catch {
14633
+ return null;
14634
+ }
14635
+ }
14636
+ function getClaudePath() {
14637
+ if (process.env.CLAUDE_PATH) {
14638
+ return process.env.CLAUDE_PATH;
14639
+ }
14640
+ if (discoveredClaudePath !== null) {
14641
+ return discoveredClaudePath;
14642
+ }
14643
+ const whichResult = findClaudeInPath();
14644
+ if (whichResult) {
14645
+ discoveredClaudePath = whichResult;
14646
+ return whichResult;
14647
+ }
14648
+ for (const path of COMMON_CLAUDE_PATHS) {
14649
+ if (existsSync2(path)) {
14650
+ const result = tryClaudeVersion(path);
14651
+ if (!result.error) {
14652
+ discoveredClaudePath = path;
14653
+ return path;
14654
+ }
14655
+ }
14656
+ }
14657
+ return "claude";
14658
+ }
14659
+ var import_semver, COMMON_CLAUDE_PATHS, discoveredClaudePath = null;
14526
14660
  var init_version_check = __esm(() => {
14527
14661
  import_semver = __toESM(require_semver2(), 1);
14528
14662
  COMMON_CLAUDE_PATHS = process.platform === "win32" ? [
@@ -14540,75 +14674,20 @@ var init_version_check = __esm(() => {
14540
14674
  ];
14541
14675
  });
14542
14676
 
14543
- // src/utils/logger.ts
14544
- function createLogger(component, useStderr = false, sessionId) {
14545
- const isDebug = () => process.env.DEBUG === "1";
14546
- const consoleLog = useStderr ? console.error : console.log;
14547
- const paddedComponent = component.length > COMPONENT_WIDTH ? component.substring(0, COMPONENT_WIDTH) : component.padEnd(COMPONENT_WIDTH);
14548
- const formatMessage = (msg, args) => {
14549
- if (args.length === 0)
14550
- return msg;
14551
- return `${msg} ${args.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")}`;
14552
- };
14553
- const DEFAULT_JSON_MAX_LEN = 60;
14554
- return {
14555
- debug: (msg, ...args) => {
14556
- if (isDebug()) {
14557
- const fullMsg = formatMessage(msg, args);
14558
- if (globalLogHandler) {
14559
- globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
14560
- } else {
14561
- consoleLog(`[${paddedComponent}] ${fullMsg}`);
14562
- }
14563
- }
14564
- },
14565
- debugJson: (label, data, maxLen = DEFAULT_JSON_MAX_LEN) => {
14566
- if (isDebug()) {
14567
- const json = JSON.stringify(data);
14568
- const truncated = json.length > maxLen ? `${json.substring(0, maxLen)}…` : json;
14569
- const fullMsg = `${label}: ${truncated}`;
14570
- if (globalLogHandler) {
14571
- globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
14572
- } else {
14573
- consoleLog(`[${paddedComponent}] ${fullMsg}`);
14574
- }
14575
- }
14576
- },
14577
- info: (msg, ...args) => {
14578
- const fullMsg = formatMessage(msg, args);
14579
- if (globalLogHandler) {
14580
- globalLogHandler("info", paddedComponent, fullMsg, sessionId);
14581
- } else {
14582
- consoleLog(`[${paddedComponent}] ${fullMsg}`);
14583
- }
14584
- },
14585
- warn: (msg, ...args) => {
14586
- const fullMsg = formatMessage(msg, args);
14587
- if (globalLogHandler) {
14588
- globalLogHandler("warn", paddedComponent, fullMsg, sessionId);
14589
- } else {
14590
- console.warn(`[${paddedComponent}] ⚠️ ${fullMsg}`);
14591
- }
14592
- },
14593
- error: (msg, err) => {
14594
- const fullMsg = err && isDebug() ? `${msg}
14595
- ${err.stack || err.message}` : msg;
14596
- if (globalLogHandler) {
14597
- globalLogHandler("error", paddedComponent, fullMsg, sessionId);
14598
- } else {
14599
- console.error(`[${paddedComponent}] ❌ ${msg}`);
14600
- if (err && isDebug()) {
14601
- console.error(err);
14602
- }
14603
- }
14604
- },
14605
- forSession: (sid) => createLogger(component, useStderr, sid)
14606
- };
14677
+ // src/utils/spawn.ts
14678
+ import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "child_process";
14679
+ function addWindowsShell(options) {
14680
+ if (isWindows && options.shell === undefined) {
14681
+ return { ...options, shell: true };
14682
+ }
14683
+ return options;
14607
14684
  }
14608
- var globalLogHandler = null, COMPONENT_WIDTH = 10, mcpLogger, wsLogger;
14609
- var init_logger = __esm(() => {
14610
- mcpLogger = createLogger("MCP", true);
14611
- wsLogger = createLogger("ws", false);
14685
+ function crossSpawn(command, args, options) {
14686
+ return nodeSpawn(command, args, addWindowsShell(options ?? {}));
14687
+ }
14688
+ var isWindows;
14689
+ var init_spawn = __esm(() => {
14690
+ isWindows = process.platform === "win32";
14612
14691
  });
14613
14692
 
14614
14693
  // src/config/types.ts
@@ -14618,12 +14697,6 @@ var init_types = __esm(() => {
14618
14697
  REMOTE_KEYS = new Set(["type", "url", "headers"]);
14619
14698
  });
14620
14699
 
14621
- // src/utils/spawn.ts
14622
- var isWindows;
14623
- var init_spawn = __esm(() => {
14624
- isWindows = process.platform === "win32";
14625
- });
14626
-
14627
14700
  // src/mcp/outbound-env.ts
14628
14701
  var OUTBOUND_ENV;
14629
14702
  var init_outbound_env = __esm(() => {
@@ -14654,7 +14727,39 @@ var init_rate_limit_detector = __esm(() => {
14654
14727
  });
14655
14728
 
14656
14729
  // src/claude/cli.ts
14657
- var log11, STDERR_AGGREGATE_SOFT_CAP;
14730
+ function buildClaudeChildEnv(parentEnv, account, opts) {
14731
+ const env = { ...parentEnv };
14732
+ if (opts?.claudeAiConnectors !== true) {
14733
+ env.ENABLE_CLAUDEAI_MCP_SERVERS = "false";
14734
+ }
14735
+ if (env.MCP_CONNECTION_NONBLOCKING === undefined) {
14736
+ env.MCP_CONNECTION_NONBLOCKING = "true";
14737
+ }
14738
+ if (env.ENABLE_PROMPT_CACHING_1H === undefined) {
14739
+ env.ENABLE_PROMPT_CACHING_1H = "true";
14740
+ }
14741
+ if (opts?.disableAutoMemory) {
14742
+ env.CLAUDE_CODE_DISABLE_AUTO_MEMORY = "1";
14743
+ }
14744
+ if (opts?.decisionBridge && env.MCP_TOOL_TIMEOUT === undefined) {
14745
+ env.MCP_TOOL_TIMEOUT = "3600000";
14746
+ }
14747
+ if (account?.home) {
14748
+ env.HOME = account.home;
14749
+ env.USERPROFILE = account.home;
14750
+ delete env.ANTHROPIC_API_KEY;
14751
+ delete env.CLAUDE_CODE_OAUTH_TOKEN;
14752
+ delete env.ANTHROPIC_AUTH_TOKEN;
14753
+ delete env.CLAUDE_CONFIG_DIR;
14754
+ delete env.CLAUDE_SECURESTORAGE_CONFIG_DIR;
14755
+ } else if (account?.apiKey) {
14756
+ env.ANTHROPIC_API_KEY = account.apiKey;
14757
+ delete env.CLAUDE_CODE_OAUTH_TOKEN;
14758
+ delete env.ANTHROPIC_AUTH_TOKEN;
14759
+ }
14760
+ return env;
14761
+ }
14762
+ var log14, STDERR_AGGREGATE_SOFT_CAP;
14658
14763
  var init_cli = __esm(() => {
14659
14764
  init_types();
14660
14765
  init_spawn();
@@ -14663,18 +14768,314 @@ var init_cli = __esm(() => {
14663
14768
  init_outbound_env();
14664
14769
  init_agent_features_env();
14665
14770
  init_rate_limit_detector();
14666
- log11 = createLogger("claude");
14771
+ log14 = createLogger("claude");
14667
14772
  STDERR_AGGREGATE_SOFT_CAP = 10 * 1024 * 1024;
14668
14773
  });
14669
14774
 
14775
+ // src/claude/usage-probe.ts
14776
+ function parseUsageOutput(text) {
14777
+ if (!text)
14778
+ return null;
14779
+ const sessionMatch = text.match(/Current session:\s*(\d+)%\s*used(?:\s*·\s*resets\s*([^\n]+?))?\s*(?:\n|$)/i);
14780
+ const weekAllMatch = text.match(/Current week(?: \(all models\))?:\s*(\d+)%\s*used(?:\s*·\s*resets\s*([^\n]+?))?\s*(?:\n|$)/i);
14781
+ if (!sessionMatch && !weekAllMatch)
14782
+ return null;
14783
+ const sessionPct = sessionMatch ? clampPct(Number(sessionMatch[1])) : 0;
14784
+ const weekAllModelsPct = weekAllMatch ? clampPct(Number(weekAllMatch[1])) : 0;
14785
+ let weekPerModelPct = null;
14786
+ const perModelRe = /Current week \((?!all models\))[^)]+\):\s*(\d+)%\s*used/gi;
14787
+ for (const m of text.matchAll(perModelRe)) {
14788
+ const pct = clampPct(Number(m[1]));
14789
+ weekPerModelPct = weekPerModelPct === null ? pct : Math.max(weekPerModelPct, pct);
14790
+ }
14791
+ return {
14792
+ sessionPct,
14793
+ weekAllModelsPct,
14794
+ weekPerModelPct,
14795
+ sessionResetsAt: sessionMatch?.[2]?.trim() || null,
14796
+ weekResetsAt: weekAllMatch?.[2]?.trim() || null
14797
+ };
14798
+ }
14799
+ function clampPct(n) {
14800
+ if (!Number.isFinite(n))
14801
+ return 0;
14802
+ return Math.max(0, Math.min(100, Math.round(n)));
14803
+ }
14804
+ async function probeAccountUsage(account, opts = {}) {
14805
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_USAGE_PROBE_TIMEOUT_MS;
14806
+ const claudePath = getClaudePath();
14807
+ const env = buildClaudeChildEnv(process.env, account);
14808
+ return new Promise((resolve) => {
14809
+ let settled = false;
14810
+ const finish = (value) => {
14811
+ if (settled)
14812
+ return;
14813
+ settled = true;
14814
+ clearTimeout(timer);
14815
+ resolve(value);
14816
+ };
14817
+ let child;
14818
+ try {
14819
+ child = crossSpawn(claudePath, ["-p", "/usage", "--output-format", "json"], {
14820
+ env,
14821
+ stdio: ["ignore", "pipe", "pipe"]
14822
+ });
14823
+ } catch (err) {
14824
+ log15.warn(`Failed to spawn /usage probe for "${account.id}": ${err}`);
14825
+ resolve(null);
14826
+ return;
14827
+ }
14828
+ const timer = setTimeout(() => {
14829
+ log15.warn(`/usage probe for "${account.id}" timed out after ${timeoutMs}ms`);
14830
+ try {
14831
+ child.kill("SIGKILL");
14832
+ } catch {}
14833
+ finish(null);
14834
+ }, timeoutMs);
14835
+ let stdout = "";
14836
+ child.stdout?.on("data", (chunk) => {
14837
+ stdout += chunk.toString();
14838
+ });
14839
+ child.stderr?.on("data", () => {});
14840
+ child.on("error", (err) => {
14841
+ log15.warn(`/usage probe for "${account.id}" errored: ${err}`);
14842
+ finish(null);
14843
+ });
14844
+ child.on("close", () => {
14845
+ const usage = extractUsage(stdout);
14846
+ if (!usage) {
14847
+ log15.debug(`/usage probe for "${account.id}" returned no parseable usage`);
14848
+ }
14849
+ finish(usage);
14850
+ });
14851
+ });
14852
+ }
14853
+ function extractUsage(stdout) {
14854
+ const trimmed = stdout.trim();
14855
+ if (!trimmed)
14856
+ return null;
14857
+ let text = trimmed;
14858
+ try {
14859
+ const parsed = JSON.parse(trimmed);
14860
+ if (typeof parsed.result === "string") {
14861
+ text = parsed.result;
14862
+ }
14863
+ } catch {}
14864
+ return parseUsageOutput(text);
14865
+ }
14866
+ var log15, DEFAULT_USAGE_PROBE_TIMEOUT_MS = 30000;
14867
+ var init_usage_probe = __esm(() => {
14868
+ init_spawn();
14869
+ init_version_check();
14870
+ init_cli();
14871
+ init_logger();
14872
+ log15 = createLogger("usage-probe");
14873
+ });
14874
+
14875
+ // src/usage/plan.ts
14876
+ function titleCase(text) {
14877
+ const spaced = text.replace(/_/g, " ").trim();
14878
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
14879
+ }
14880
+ function planLabel(creds) {
14881
+ const tier = creds.rateLimitTier?.trim();
14882
+ if (tier) {
14883
+ const bare = tier.replace(TIER_PREFIX, "");
14884
+ const known = bare.match(/^(max|pro|team|enterprise)(?:_(\d+)x)?$/i);
14885
+ if (known) {
14886
+ const plan = titleCase(known[1]);
14887
+ return known[2] ? `${plan} ${known[2]}×` : plan;
14888
+ }
14889
+ return creds.subscriptionType?.trim() ? titleCase(creds.subscriptionType.trim()) : undefined;
14890
+ }
14891
+ return creds.subscriptionType?.trim() ? titleCase(creds.subscriptionType.trim()) : undefined;
14892
+ }
14893
+ var TIER_PREFIX;
14894
+ var init_plan = __esm(() => {
14895
+ TIER_PREFIX = /^default_claude_/;
14896
+ });
14897
+
14898
+ // src/usage/profiles.ts
14899
+ import { readFile } from "fs/promises";
14900
+ import path2 from "path";
14901
+ function profileNameFor(configDir) {
14902
+ const base = path2.basename(configDir.replace(/\/+$/, ""));
14903
+ return base === ".claude" ? "default" : base.replace(/^\.claude-/, "");
14904
+ }
14905
+ function metadataCandidates(configDir) {
14906
+ const inside = path2.join(configDir, ".claude.json");
14907
+ const sibling = path2.join(path2.dirname(configDir), ".claude.json");
14908
+ return inside === sibling ? [inside] : [inside, sibling];
14909
+ }
14910
+ async function readMetadata(configDir) {
14911
+ for (const candidate of metadataCandidates(configDir)) {
14912
+ try {
14913
+ const parsed = JSON.parse(await readFile(candidate, "utf8"));
14914
+ if (parsed.oauthAccount)
14915
+ return parsed.oauthAccount;
14916
+ } catch {}
14917
+ }
14918
+ return;
14919
+ }
14920
+ async function accountEmail(configDir) {
14921
+ return (await readMetadata(configDir))?.emailAddress;
14922
+ }
14923
+ async function accountPlan(configDir) {
14924
+ const meta = await readMetadata(configDir);
14925
+ if (!meta)
14926
+ return;
14927
+ return planLabel({
14928
+ rateLimitTier: meta.userRateLimitTier ?? meta.organizationRateLimitTier,
14929
+ subscriptionType: meta.organizationType?.replace(/^claude_/, "")
14930
+ });
14931
+ }
14932
+ var init_profiles = __esm(() => {
14933
+ init_plan();
14934
+ });
14935
+
14936
+ // src/usage/accounts.ts
14937
+ import path3 from "path";
14938
+ function accountTargets(accounts, onlyId) {
14939
+ if (!accounts?.length)
14940
+ return [];
14941
+ if (onlyId && !accounts.some((a) => a.id === onlyId)) {
14942
+ return [
14943
+ {
14944
+ name: onlyId,
14945
+ note: "this thread is bound to an account that is no longer configured"
14946
+ }
14947
+ ];
14948
+ }
14949
+ const selected = onlyId ? accounts.filter((a) => a.id === onlyId) : accounts;
14950
+ return selected.map((account) => {
14951
+ const name = account.displayName ?? account.id;
14952
+ if (!account.home) {
14953
+ return { name, note: "billed by API key — no subscription limits to report" };
14954
+ }
14955
+ return { name, configDir: path3.join(account.home, ".claude") };
14956
+ });
14957
+ }
14958
+ var init_accounts = () => {};
14959
+
14960
+ // src/usage/render.ts
14961
+ function heading(limit) {
14962
+ switch (limit.kind) {
14963
+ case "session":
14964
+ return "Current session";
14965
+ case "weekly_all":
14966
+ return "Current week (all models)";
14967
+ case "weekly_scoped":
14968
+ return `Current week (${limit.model ?? "scoped"})`;
14969
+ }
14970
+ }
14971
+ function bar(percent, width = DEFAULT_BAR_WIDTH) {
14972
+ const clamped = Math.max(0, Math.min(100, percent));
14973
+ let filled = Math.round(clamped / 100 * width);
14974
+ if (clamped > 0 && filled === 0)
14975
+ filled = 1;
14976
+ if (clamped < 100 && filled === width)
14977
+ filled = width - 1;
14978
+ return "█".repeat(filled) + "░".repeat(width - filled);
14979
+ }
14980
+ function renderUsage(limits, options = {}) {
14981
+ const width = options.barWidth ?? DEFAULT_BAR_WIDTH;
14982
+ const ordered = KIND_ORDER.map((kind) => limits.find((l) => l.kind === kind)).filter((l) => l !== undefined);
14983
+ return ordered.map((limit) => [
14984
+ heading(limit),
14985
+ `${bar(limit.percent, width)} ${String(limit.percent).padStart(3)}% used`,
14986
+ ...limit.resetsAt ? [`Resets ${limit.resetsAt}`] : []
14987
+ ].join(`
14988
+ `)).join(`
14989
+
14990
+ `);
14991
+ }
14992
+ function renderProfiles(profiles, options = {}) {
14993
+ return profiles.map((p) => {
14994
+ const body = p.error ? `⚠️ could not read usage: ${p.error}` : renderUsage(p.limits ?? [], options);
14995
+ const detail = [options.showEmails ? p.email : undefined, p.plan].filter(Boolean).join(" · ");
14996
+ const header = detail ? `${p.profile} (${detail})` : p.profile;
14997
+ return `${header}
14998
+ ${"─".repeat(header.length)}
14999
+ ${body}`;
15000
+ }).join(`
15001
+
15002
+ `);
15003
+ }
15004
+ var DEFAULT_BAR_WIDTH = 24, KIND_ORDER;
15005
+ var init_render = __esm(() => {
15006
+ KIND_ORDER = ["session", "weekly_all", "weekly_scoped"];
15007
+ });
15008
+
15009
+ // src/usage/index.ts
15010
+ import { homedir as homedir5 } from "os";
15011
+ import path4 from "path";
15012
+ function toLimits(usage) {
15013
+ const limits = [
15014
+ {
15015
+ kind: "session",
15016
+ percent: usage.sessionPct,
15017
+ resetsAt: usage.sessionResetsAt ?? undefined
15018
+ },
15019
+ {
15020
+ kind: "weekly_all",
15021
+ percent: usage.weekAllModelsPct,
15022
+ resetsAt: usage.weekResetsAt ?? undefined
15023
+ }
15024
+ ];
15025
+ if (usage.weekPerModelPct !== null) {
15026
+ limits.push({
15027
+ kind: "weekly_scoped",
15028
+ percent: usage.weekPerModelPct
15029
+ });
15030
+ }
15031
+ return limits;
15032
+ }
15033
+ async function readSeat(name, configDir, home) {
15034
+ const email = await accountEmail(configDir);
15035
+ const plan = await accountPlan(configDir);
15036
+ const usage = await probeAccountUsage({ id: name, home }, { timeoutMs: USAGE_PROBE_TIMEOUT_MS });
15037
+ if (!usage) {
15038
+ return {
15039
+ profile: name,
15040
+ email,
15041
+ plan,
15042
+ error: `usage unknown — the seat may be logged out (try \`claude login\` for ${name})`
15043
+ };
15044
+ }
15045
+ return { profile: name, email, plan, limits: toLimits(usage) };
15046
+ }
15047
+ async function collectUsage(options) {
15048
+ const targets = accountTargets(options.accounts, options.all ? undefined : options.sessionAccountId);
15049
+ const results = [];
15050
+ if (targets.length > 0) {
15051
+ for (const target of targets) {
15052
+ if (!target.configDir) {
15053
+ results.push({ profile: target.name, error: target.note });
15054
+ continue;
15055
+ }
15056
+ results.push(await readSeat(target.name, target.configDir, path4.dirname(target.configDir)));
15057
+ }
15058
+ return results;
15059
+ }
15060
+ const configDir = process.env.CLAUDE_CONFIG_DIR ?? path4.join(homedir5(), ".claude");
15061
+ return [await readSeat(profileNameFor(configDir), configDir)];
15062
+ }
15063
+ var USAGE_PROBE_TIMEOUT_MS = 1e4;
15064
+ var init_usage = __esm(() => {
15065
+ init_usage_probe();
15066
+ init_profiles();
15067
+ init_accounts();
15068
+ init_render();
15069
+ });
15070
+
14670
15071
  // src/claude/quick-query.ts
14671
- var log16;
15072
+ var log17;
14672
15073
  var init_quick_query = __esm(() => {
14673
15074
  init_spawn();
14674
15075
  init_cli();
14675
15076
  init_version_check();
14676
15077
  init_logger();
14677
- log16 = createLogger("query");
15078
+ log17 = createLogger("query");
14678
15079
  });
14679
15080
 
14680
15081
  // node_modules/ws/lib/constants.js
@@ -33511,6 +33912,107 @@ function formatToolForPermission(toolName, input, formatter, options = {}) {
33511
33912
  });
33512
33913
  return result.permissionText ?? result.display ?? toolName;
33513
33914
  }
33915
+ // src/session/lifecycle-fsm.ts
33916
+ init_logger();
33917
+ var log = createLogger("fsm");
33918
+ var ALLOWED_TRANSITIONS = {
33919
+ starting: new Set(["active", "paused", "interrupted", "cancelling", "restarting"]),
33920
+ active: new Set([
33921
+ "active",
33922
+ "processing",
33923
+ "paused",
33924
+ "interrupted",
33925
+ "restarting",
33926
+ "cancelling",
33927
+ "ending"
33928
+ ]),
33929
+ processing: new Set([
33930
+ "active",
33931
+ "paused",
33932
+ "interrupted",
33933
+ "restarting",
33934
+ "cancelling"
33935
+ ]),
33936
+ paused: new Set(["active", "cancelling", "restarting"]),
33937
+ interrupted: new Set(["active", "cancelling", "restarting", "paused"]),
33938
+ restarting: new Set(["active", "paused", "cancelling"]),
33939
+ cancelling: new Set(["ending"]),
33940
+ ending: new Set
33941
+ };
33942
+ // src/operations/post-helpers/index.ts
33943
+ init_logger();
33944
+
33945
+ // src/utils/session-log.ts
33946
+ function createSessionLog(baseLog) {
33947
+ return (session) => {
33948
+ if (session?.sessionId) {
33949
+ return baseLog.forSession(session.sessionId);
33950
+ }
33951
+ return baseLog;
33952
+ };
33953
+ }
33954
+
33955
+ // src/utils/error-handler/index.ts
33956
+ init_logger();
33957
+
33958
+ // src/version.ts
33959
+ import { readFileSync, existsSync } from "fs";
33960
+ import { dirname, resolve } from "path";
33961
+ import { fileURLToPath } from "url";
33962
+ var __dirname2 = dirname(fileURLToPath(import.meta.url));
33963
+ function loadPackageJson() {
33964
+ const candidates = [
33965
+ resolve(__dirname2, "..", "package.json"),
33966
+ resolve(__dirname2, "..", "..", "package.json"),
33967
+ resolve(process.cwd(), "package.json")
33968
+ ];
33969
+ for (const candidate of candidates) {
33970
+ if (existsSync(candidate)) {
33971
+ try {
33972
+ const pkg = JSON.parse(readFileSync(candidate, "utf-8"));
33973
+ if (pkg.name === "claude-threads") {
33974
+ return { version: pkg.version, name: pkg.name };
33975
+ }
33976
+ } catch {}
33977
+ }
33978
+ }
33979
+ return { version: "unknown", name: "claude-threads" };
33980
+ }
33981
+ var pkgInfo = loadPackageJson();
33982
+ var VERSION = pkgInfo.version;
33983
+
33984
+ // src/utils/format.ts
33985
+ init_version_check();
33986
+ function extractThreadId(sessionId) {
33987
+ const colonIndex = sessionId.indexOf(":");
33988
+ return colonIndex >= 0 ? sessionId.substring(colonIndex + 1) : sessionId;
33989
+ }
33990
+ function formatShortId(id) {
33991
+ const threadId = extractThreadId(id);
33992
+ if (threadId.length <= 8)
33993
+ return threadId;
33994
+ return `${threadId.substring(0, 8)}…`;
33995
+ }
33996
+
33997
+ // src/utils/error-handler/index.ts
33998
+ var log2 = createLogger("error");
33999
+
34000
+ // src/operations/post-helpers/index.ts
34001
+ init_emoji();
34002
+
34003
+ // src/git/worktree.ts
34004
+ init_spawn();
34005
+ import * as path from "path";
34006
+ init_logger();
34007
+ import { homedir } from "os";
34008
+ var log3 = createLogger("git-wt");
34009
+ var WORKTREES_DIR = path.join(homedir(), ".claude-threads", "worktrees");
34010
+ var METADATA_STORE_PATH = path.join(homedir(), ".claude-threads", "worktree-metadata.json");
34011
+
34012
+ // src/operations/post-helpers/index.ts
34013
+ var log4 = createLogger("helpers");
34014
+ var sessionLog = createSessionLog(log4);
34015
+
33514
34016
  // src/operations/task-tracker.ts
33515
34017
  var VALID_STATUSES = new Set(["pending", "in_progress", "completed"]);
33516
34018
  // src/platform/utils.ts
@@ -33633,45 +34135,6 @@ function isDcmThreadId(threadId) {
33633
34135
  function resolvePostThreadId(threadId) {
33634
34136
  return isDcmThreadId(threadId) ? undefined : threadId;
33635
34137
  }
33636
-
33637
- // src/version.ts
33638
- import { readFileSync, existsSync } from "fs";
33639
- import { dirname, resolve } from "path";
33640
- import { fileURLToPath } from "url";
33641
- var __dirname2 = dirname(fileURLToPath(import.meta.url));
33642
- function loadPackageJson() {
33643
- const candidates = [
33644
- resolve(__dirname2, "..", "package.json"),
33645
- resolve(__dirname2, "..", "..", "package.json"),
33646
- resolve(process.cwd(), "package.json")
33647
- ];
33648
- for (const candidate of candidates) {
33649
- if (existsSync(candidate)) {
33650
- try {
33651
- const pkg = JSON.parse(readFileSync(candidate, "utf-8"));
33652
- if (pkg.name === "claude-threads") {
33653
- return { version: pkg.version, name: pkg.name };
33654
- }
33655
- } catch {}
33656
- }
33657
- }
33658
- return { version: "unknown", name: "claude-threads" };
33659
- }
33660
- var pkgInfo = loadPackageJson();
33661
- var VERSION = pkgInfo.version;
33662
-
33663
- // src/utils/format.ts
33664
- init_version_check();
33665
- function extractThreadId(sessionId) {
33666
- const colonIndex = sessionId.indexOf(":");
33667
- return colonIndex >= 0 ? sessionId.substring(colonIndex + 1) : sessionId;
33668
- }
33669
- function formatShortId(id) {
33670
- const threadId = extractThreadId(id);
33671
- if (threadId.length <= 8)
33672
- return threadId;
33673
- return `${threadId.substring(0, 8)}…`;
33674
- }
33675
34138
  // src/operations/executors/task-list.ts
33676
34139
  init_emoji();
33677
34140
  // src/operations/executors/subagent.ts
@@ -33681,7 +34144,7 @@ init_emoji();
33681
34144
 
33682
34145
  // src/persistence/audit-log.ts
33683
34146
  init_logger();
33684
- var log = createLogger("audit");
34147
+ var log5 = createLogger("audit");
33685
34148
  var enabledPlatforms = new Set;
33686
34149
  var preparedDirs = new Set;
33687
34150
  var openFds = new Map;
@@ -33694,13 +34157,13 @@ init_emoji();
33694
34157
  // src/operations/executors/worktree-prompt.ts
33695
34158
  init_emoji();
33696
34159
  init_logger();
33697
- var log2 = createLogger("wt-prompt");
34160
+ var log6 = createLogger("wt-prompt");
33698
34161
  // src/operations/message-manager.ts
33699
34162
  init_logger();
33700
34163
 
33701
34164
  // src/transcription/elevenlabs.ts
33702
34165
  init_logger();
33703
- var log3 = createLogger("transcribe");
34166
+ var log7 = createLogger("transcribe");
33704
34167
 
33705
34168
  // src/transcription/types.ts
33706
34169
  var AUDIO_EXTENSIONS = new Set(["m4a", "mp3", "ogg", "opus", "wav", "aac", "flac", "webm"]);
@@ -33709,9 +34172,9 @@ var GENERIC_MIME_TYPES = new Set(["", "application/octet-stream", "binary/octet-
33709
34172
  init_logger();
33710
34173
 
33711
34174
  // src/utils/safe-filename.ts
33712
- import { basename } from "path";
34175
+ import { basename as basename2 } from "path";
33713
34176
  function sanitizeFilename(name) {
33714
- const flat = basename(name.replace(/\\/g, "/"));
34177
+ const flat = basename2(name.replace(/\\/g, "/"));
33715
34178
  const cleaned = flat.replace(/[\x00-\x1F\x7F]/g, "_").trim();
33716
34179
  if (!cleaned || cleaned === "." || cleaned === "..") {
33717
34180
  return "attachment";
@@ -33729,40 +34192,13 @@ function formatBytes(bytes) {
33729
34192
  }
33730
34193
 
33731
34194
  // src/operations/streaming/handler.ts
33732
- var log4 = createLogger("streaming");
34195
+ var log8 = createLogger("streaming");
33733
34196
  // src/operations/message-manager.ts
33734
- var log5 = createLogger("msg-mgr");
33735
- // src/session/lifecycle-fsm.ts
33736
- init_logger();
33737
- var log6 = createLogger("fsm");
33738
- var ALLOWED_TRANSITIONS = {
33739
- starting: new Set(["active", "paused", "interrupted", "cancelling", "restarting"]),
33740
- active: new Set([
33741
- "active",
33742
- "processing",
33743
- "paused",
33744
- "interrupted",
33745
- "restarting",
33746
- "cancelling",
33747
- "ending"
33748
- ]),
33749
- processing: new Set([
33750
- "active",
33751
- "paused",
33752
- "interrupted",
33753
- "restarting",
33754
- "cancelling"
33755
- ]),
33756
- paused: new Set(["active", "cancelling", "restarting"]),
33757
- interrupted: new Set(["active", "cancelling", "restarting", "paused"]),
33758
- restarting: new Set(["active", "paused", "cancelling"]),
33759
- cancelling: new Set(["ending"]),
33760
- ending: new Set
33761
- };
34197
+ var log9 = createLogger("msg-mgr");
33762
34198
  // src/persistence/session-store.ts
33763
34199
  init_logger();
33764
- import { homedir } from "os";
33765
- import { join as join2 } from "path";
34200
+ import { homedir as homedir2 } from "os";
34201
+ import { join as join3 } from "path";
33766
34202
 
33767
34203
  // src/sponsor.ts
33768
34204
  var SPONSOR_URL = "https://github.com/sponsors/axolotl-systems";
@@ -33772,13 +34208,13 @@ function formatSponsorFooter(formatter) {
33772
34208
  }
33773
34209
 
33774
34210
  // src/persistence/session-store.ts
33775
- var log7 = createLogger("persist");
33776
- var DEFAULT_CONFIG_DIR = join2(homedir(), ".config", "claude-threads");
33777
- var DEFAULT_SESSIONS_FILE = join2(DEFAULT_CONFIG_DIR, "sessions.json");
34211
+ var log10 = createLogger("persist");
34212
+ var DEFAULT_CONFIG_DIR = join3(homedir2(), ".config", "claude-threads");
34213
+ var DEFAULT_SESSIONS_FILE = join3(DEFAULT_CONFIG_DIR, "sessions.json");
33778
34214
 
33779
34215
  // src/config/index.ts
33780
- import { resolve as resolve2, dirname as dirname2 } from "path";
33781
- import { homedir as homedir2 } from "os";
34216
+ import { resolve as resolve3, dirname as dirname3 } from "path";
34217
+ import { homedir as homedir3 } from "os";
33782
34218
 
33783
34219
  // node_modules/js-yaml/dist/js-yaml.mjs
33784
34220
  function getDefaultExportFromCjs(x) {
@@ -36920,7 +37356,7 @@ init_types();
36920
37356
  init_types();
36921
37357
 
36922
37358
  // src/config/index.ts
36923
- var CONFIG_PATH = resolve2(homedir2(), ".config", "claude-threads", "config.yaml");
37359
+ var CONFIG_PATH = resolve3(homedir3(), ".config", "claude-threads", "config.yaml");
36924
37360
 
36925
37361
  // src/utils/battery.ts
36926
37362
  import { exec } from "child_process";
@@ -36928,18 +37364,18 @@ import { promisify } from "util";
36928
37364
  var execAsync = promisify(exec);
36929
37365
 
36930
37366
  // src/changelog.ts
36931
- import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
36932
- import { dirname as dirname3, resolve as resolve3 } from "path";
37367
+ import { readFileSync as readFileSync2, existsSync as existsSync3 } from "fs";
37368
+ import { dirname as dirname4, resolve as resolve4 } from "path";
36933
37369
  import { fileURLToPath as fileURLToPath2 } from "url";
36934
- var __dirname3 = dirname3(fileURLToPath2(import.meta.url));
37370
+ var __dirname3 = dirname4(fileURLToPath2(import.meta.url));
36935
37371
  function getReleaseNotes(version) {
36936
37372
  const possiblePaths = [
36937
- resolve3(__dirname3, "..", "CHANGELOG.md"),
36938
- resolve3(__dirname3, "..", "..", "CHANGELOG.md")
37373
+ resolve4(__dirname3, "..", "CHANGELOG.md"),
37374
+ resolve4(__dirname3, "..", "..", "CHANGELOG.md")
36939
37375
  ];
36940
37376
  let changelogPath = null;
36941
37377
  for (const p of possiblePaths) {
36942
- if (existsSync2(p)) {
37378
+ if (existsSync3(p)) {
36943
37379
  changelogPath = p;
36944
37380
  break;
36945
37381
  }
@@ -37029,7 +37465,7 @@ init_logger();
37029
37465
  // src/utils/keep-alive.ts
37030
37466
  init_logger();
37031
37467
  import { spawn } from "child_process";
37032
- var log8 = createLogger("keepalive");
37468
+ var log11 = createLogger("keepalive");
37033
37469
  function keepAliveSpawnSpec(platform, parentPid) {
37034
37470
  switch (platform) {
37035
37471
  case "darwin":
@@ -37085,7 +37521,7 @@ class KeepAliveManager {
37085
37521
  if (!enabled && this.keepAliveProcess) {
37086
37522
  this.stopKeepAlive();
37087
37523
  }
37088
- log8.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
37524
+ log11.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
37089
37525
  }
37090
37526
  isEnabled() {
37091
37527
  return this.enabled;
@@ -37095,7 +37531,7 @@ class KeepAliveManager {
37095
37531
  }
37096
37532
  sessionStarted() {
37097
37533
  this.activeSessionCount++;
37098
- log8.debug(`Session started (${this.activeSessionCount} active)`);
37534
+ log11.debug(`Session started (${this.activeSessionCount} active)`);
37099
37535
  if (this.activeSessionCount === 1) {
37100
37536
  this.startKeepAlive();
37101
37537
  }
@@ -37104,7 +37540,7 @@ class KeepAliveManager {
37104
37540
  if (this.activeSessionCount > 0) {
37105
37541
  this.activeSessionCount--;
37106
37542
  }
37107
- log8.debug(`Session ended (${this.activeSessionCount} active)`);
37543
+ log11.debug(`Session ended (${this.activeSessionCount} active)`);
37108
37544
  if (this.activeSessionCount === 0) {
37109
37545
  this.stopKeepAlive();
37110
37546
  }
@@ -37118,11 +37554,11 @@ class KeepAliveManager {
37118
37554
  }
37119
37555
  startKeepAlive() {
37120
37556
  if (!this.enabled) {
37121
- log8.debug("Keep-alive disabled, skipping");
37557
+ log11.debug("Keep-alive disabled, skipping");
37122
37558
  return;
37123
37559
  }
37124
37560
  if (this.keepAliveProcess) {
37125
- log8.debug("Keep-alive already running");
37561
+ log11.debug("Keep-alive already running");
37126
37562
  return;
37127
37563
  }
37128
37564
  switch (this.platform) {
@@ -37136,12 +37572,12 @@ class KeepAliveManager {
37136
37572
  this.startWindowsKeepAlive();
37137
37573
  break;
37138
37574
  default:
37139
- log8.warn(`Keep-alive not supported on ${this.platform}`);
37575
+ log11.warn(`Keep-alive not supported on ${this.platform}`);
37140
37576
  }
37141
37577
  }
37142
37578
  stopKeepAlive() {
37143
37579
  if (this.keepAliveProcess) {
37144
- log8.debug("Stopping keep-alive");
37580
+ log11.debug("Stopping keep-alive");
37145
37581
  this.keepAliveProcess.kill();
37146
37582
  this.keepAliveProcess = null;
37147
37583
  }
@@ -37156,18 +37592,18 @@ class KeepAliveManager {
37156
37592
  detached: false
37157
37593
  });
37158
37594
  this.keepAliveProcess.on("error", (err) => {
37159
- log8.error(`Failed to start caffeinate: ${err.message}`);
37595
+ log11.error(`Failed to start caffeinate: ${err.message}`);
37160
37596
  this.keepAliveProcess = null;
37161
37597
  });
37162
37598
  this.keepAliveProcess.on("exit", (code) => {
37163
37599
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
37164
- log8.debug(`caffeinate exited with code ${code}`);
37600
+ log11.debug(`caffeinate exited with code ${code}`);
37165
37601
  }
37166
37602
  this.keepAliveProcess = null;
37167
37603
  });
37168
- log8.info("Sleep prevention active (caffeinate)");
37604
+ log11.info("Sleep prevention active (caffeinate)");
37169
37605
  } catch (err) {
37170
- log8.error(`Failed to start caffeinate: ${err}`);
37606
+ log11.error(`Failed to start caffeinate: ${err}`);
37171
37607
  }
37172
37608
  }
37173
37609
  startLinuxKeepAlive() {
@@ -37180,19 +37616,19 @@ class KeepAliveManager {
37180
37616
  detached: false
37181
37617
  });
37182
37618
  this.keepAliveProcess.on("error", (err) => {
37183
- log8.debug(`systemd-inhibit not available: ${err.message}`);
37619
+ log11.debug(`systemd-inhibit not available: ${err.message}`);
37184
37620
  this.keepAliveProcess = null;
37185
37621
  this.startLinuxKeepAliveFallback();
37186
37622
  });
37187
37623
  this.keepAliveProcess.on("exit", (code) => {
37188
37624
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
37189
- log8.debug(`systemd-inhibit exited with code ${code}`);
37625
+ log11.debug(`systemd-inhibit exited with code ${code}`);
37190
37626
  }
37191
37627
  this.keepAliveProcess = null;
37192
37628
  });
37193
- log8.info("Sleep prevention active (systemd-inhibit)");
37629
+ log11.info("Sleep prevention active (systemd-inhibit)");
37194
37630
  } catch (err) {
37195
- log8.debug(`Failed to start systemd-inhibit: ${err}`);
37631
+ log11.debug(`Failed to start systemd-inhibit: ${err}`);
37196
37632
  this.startLinuxKeepAliveFallback();
37197
37633
  }
37198
37634
  }
@@ -37203,15 +37639,15 @@ class KeepAliveManager {
37203
37639
  detached: false
37204
37640
  });
37205
37641
  this.keepAliveProcess.on("error", (err) => {
37206
- log8.warn(`Linux keep-alive fallback not available: ${err.message}`);
37642
+ log11.warn(`Linux keep-alive fallback not available: ${err.message}`);
37207
37643
  this.keepAliveProcess = null;
37208
37644
  });
37209
37645
  this.keepAliveProcess.on("exit", () => {
37210
37646
  this.keepAliveProcess = null;
37211
37647
  });
37212
- log8.info("Sleep prevention active (xdg-screensaver)");
37648
+ log11.info("Sleep prevention active (xdg-screensaver)");
37213
37649
  } catch (err) {
37214
- log8.warn(`Linux keep-alive not available: ${err}`);
37650
+ log11.warn(`Linux keep-alive not available: ${err}`);
37215
37651
  }
37216
37652
  }
37217
37653
  startWindowsKeepAlive() {
@@ -37223,25 +37659,25 @@ class KeepAliveManager {
37223
37659
  windowsHide: true
37224
37660
  });
37225
37661
  this.keepAliveProcess.on("error", (err) => {
37226
- log8.warn(`Windows keep-alive not available: ${err.message}`);
37662
+ log11.warn(`Windows keep-alive not available: ${err.message}`);
37227
37663
  this.keepAliveProcess = null;
37228
37664
  });
37229
37665
  this.keepAliveProcess.on("exit", (code) => {
37230
37666
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
37231
- log8.debug(`PowerShell keep-alive exited with code ${code}`);
37667
+ log11.debug(`PowerShell keep-alive exited with code ${code}`);
37232
37668
  }
37233
37669
  this.keepAliveProcess = null;
37234
37670
  });
37235
- log8.info("Sleep prevention active (SetThreadExecutionState)");
37671
+ log11.info("Sleep prevention active (SetThreadExecutionState)");
37236
37672
  } catch (err) {
37237
- log8.warn(`Windows keep-alive not available: ${err}`);
37673
+ log11.warn(`Windows keep-alive not available: ${err}`);
37238
37674
  }
37239
37675
  }
37240
37676
  }
37241
37677
  var keepAlive = new KeepAliveManager;
37242
37678
 
37243
37679
  // src/operations/sticky-message/handler.ts
37244
- var log9 = createLogger("sticky");
37680
+ var log12 = createLogger("sticky");
37245
37681
  var botStartedAt = new Date;
37246
37682
  var stickyPostIds = new Map;
37247
37683
  var needsBump = new Map;
@@ -37484,10 +37920,10 @@ init_version_check();
37484
37920
 
37485
37921
  // src/persistence/thread-logger.ts
37486
37922
  init_logger();
37487
- import { homedir as homedir3 } from "os";
37488
- import { join as join3, dirname as dirname4 } from "path";
37489
- var log10 = createLogger("thread-log");
37490
- var LOGS_BASE_DIR = join3(homedir3(), ".claude-threads", "logs");
37923
+ import { homedir as homedir4 } from "os";
37924
+ import { join as join4, dirname as dirname5 } from "path";
37925
+ var log13 = createLogger("thread-log");
37926
+ var LOGS_BASE_DIR = join4(homedir4(), ".claude-threads", "logs");
37491
37927
 
37492
37928
  // src/operations/bug-report/handler.ts
37493
37929
  var piiRedactor = new Redactor({ aggressive: true });
@@ -37756,6 +38192,19 @@ var COMMAND_REGISTRY = [
37756
38192
  { name: "uninstall", description: "Uninstall a plugin (restarts Claude)", args: "<name>" }
37757
38193
  ]
37758
38194
  },
38195
+ {
38196
+ command: "usage",
38197
+ description: "Subscription quota: the session and weekly windows for this profile",
38198
+ args: "[all]",
38199
+ category: "system",
38200
+ audience: "both",
38201
+ worksInFirstMessage: true,
38202
+ isImmediate: true,
38203
+ claudeNotes: "Quota windows, not this session's cost — see !cost for that",
38204
+ subcommands: [
38205
+ { name: "all", description: "Every account this bot is configured with", worksInFirstMessage: true }
38206
+ ]
38207
+ },
37759
38208
  {
37760
38209
  command: "context",
37761
38210
  description: "Show context usage",
@@ -37839,9 +38288,9 @@ function formatCommandRows(cmd, code) {
37839
38288
  }
37840
38289
  return rows;
37841
38290
  }
37842
- function generateHelpMessage(formatter) {
38291
+ function generateHelpMessage(formatter, options) {
37843
38292
  const code = formatter.formatCode.bind(formatter);
37844
- const commands = getUserHelpCommands();
38293
+ const commands = getUserHelpCommands().filter((c) => c.command !== "bug" || options?.bugReportsEnabled !== false);
37845
38294
  const rows = [];
37846
38295
  for (const cmd of commands) {
37847
38296
  rows.push(...formatCommandRows(cmd, code));
@@ -37872,7 +38321,9 @@ function getSubcommandDef(command, subcommand) {
37872
38321
  return cmdDef?.subcommands?.find((s) => s.name === subcommand);
37873
38322
  }
37874
38323
  var handleHelp = async (ctx) => {
37875
- const helpMessage = generateHelpMessage(ctx.formatter);
38324
+ const helpMessage = generateHelpMessage(ctx.formatter, {
38325
+ bugReportsEnabled: ctx.sessionManager.getBugReportsEnabled()
38326
+ });
37876
38327
  await ctx.client.createPost(helpMessage, ctx.threadId);
37877
38328
  return { handled: true };
37878
38329
  };
@@ -37904,6 +38355,22 @@ var handleUpdate = async (ctx, args) => {
37904
38355
  }
37905
38356
  return { handled: true };
37906
38357
  };
38358
+ var handleUsage = async (ctx, args) => {
38359
+ if (!ctx.isAllowed) {
38360
+ return { handled: true };
38361
+ }
38362
+ const all = args?.trim().toLowerCase() === "all";
38363
+ await Promise.resolve().then(() => init_usage());
38364
+ const rendered = renderProfiles(await collectUsage({
38365
+ all,
38366
+ accounts: ctx.sessionManager.getClaudeAccounts(),
38367
+ sessionAccountId: ctx.sessionManager.getPersistedSession(ctx.threadId, ctx.client.platformId)?.claudeAccountId
38368
+ }), { showEmails: ctx.sessionManager.getUsageShowEmails() });
38369
+ await ctx.client.createPost(`\`\`\`
38370
+ ${rendered}
38371
+ \`\`\``, ctx.threadId);
38372
+ return { handled: true };
38373
+ };
37907
38374
  var handleStop = async (ctx) => {
37908
38375
  if (ctx.commandContext === "first-message") {
37909
38376
  return { handled: false };
@@ -38221,6 +38688,7 @@ function createPassthroughHandler(slashCommand) {
38221
38688
  handlers.set("help", handleHelp);
38222
38689
  handlers.set("release-notes", handleReleaseNotes);
38223
38690
  handlers.set("update", handleUpdate);
38691
+ handlers.set("usage", handleUsage);
38224
38692
  handlers.set("stop", handleStop);
38225
38693
  handlers.set("escape", handleEscape);
38226
38694
  handlers.set("approve", handleApprove);
@@ -38246,7 +38714,7 @@ handlers.set("model", createPassthroughHandler("model"));
38246
38714
  handlers.set("effort", createPassthroughHandler("effort"));
38247
38715
  // src/commands/system-prompt-generator.ts
38248
38716
  init_logger();
38249
- var log12 = createLogger("system-prompt");
38717
+ var log16 = createLogger("system-prompt");
38250
38718
  function formatUserCommand(cmd) {
38251
38719
  const cmdStr = cmd.args ? `\`!${cmd.command} ${cmd.args}\`` : `\`!${cmd.command}\``;
38252
38720
  const description = cmd.description;
@@ -38336,74 +38804,43 @@ ${avoidCommands.map((c) => `- \`!${c.command}\` - ${c.reason}`).join(`
38336
38804
  `)}
38337
38805
  `.trim();
38338
38806
  }
38339
- // src/utils/error-handler/index.ts
38340
- init_logger();
38341
- var log13 = createLogger("error");
38342
-
38343
38807
  // src/session/lifecycle.ts
38344
38808
  init_logger();
38345
38809
 
38346
- // src/utils/session-log.ts
38347
- function createSessionLog(baseLog) {
38348
- return (session) => {
38349
- if (session?.sessionId) {
38350
- return baseLog.forSession(session.sessionId);
38351
- }
38352
- return baseLog;
38353
- };
38354
- }
38355
-
38356
- // src/operations/post-helpers/index.ts
38357
- init_logger();
38358
- init_emoji();
38359
-
38360
- // src/git/worktree.ts
38361
- init_spawn();
38362
- import * as path from "path";
38363
- init_logger();
38364
- import { homedir as homedir4 } from "os";
38365
- var log14 = createLogger("git-wt");
38366
- var WORKTREES_DIR = path.join(homedir4(), ".claude-threads", "worktrees");
38367
- var METADATA_STORE_PATH = path.join(homedir4(), ".claude-threads", "worktree-metadata.json");
38368
-
38369
- // src/operations/post-helpers/index.ts
38370
- var log15 = createLogger("helpers");
38371
- var sessionLog = createSessionLog(log15);
38372
-
38373
38810
  // src/operations/suggestions/title.ts
38374
38811
  init_quick_query();
38375
38812
  init_logger();
38376
- var log17 = createLogger("title");
38813
+ var log18 = createLogger("title");
38377
38814
 
38378
38815
  // src/operations/suggestions/tag.ts
38379
38816
  init_quick_query();
38380
38817
  init_logger();
38381
- var log18 = createLogger("tags");
38818
+ var log19 = createLogger("tags");
38382
38819
 
38383
38820
  // src/session/metadata-suggestions.ts
38384
38821
  init_logger();
38385
- var log19 = createLogger("session");
38386
- var sessionLog2 = createSessionLog(log19);
38822
+ var log20 = createLogger("session");
38823
+ var sessionLog2 = createSessionLog(log20);
38387
38824
 
38388
38825
  // src/operations/context-prompt/handler.ts
38389
38826
  init_emoji();
38390
38827
  init_logger();
38391
- var log20 = createLogger("context");
38392
- var sessionLog3 = createSessionLog(log20);
38828
+ var log21 = createLogger("context");
38829
+ var sessionLog3 = createSessionLog(log21);
38393
38830
  var contextPromptTimeouts = new Map;
38394
38831
  var contextPromptFiles = new Map;
38395
38832
  // src/memory/store.ts
38396
- import { homedir as homedir5 } from "os";
38833
+ import { homedir as homedir6 } from "os";
38397
38834
  import { basename as basename3, dirname as dirname6, join as join5, sep as sep2 } from "path";
38398
38835
  init_logger();
38399
- var log21 = createLogger("memory");
38400
- var DEFAULT_ROOT = join5(homedir5(), ".config", "claude-threads", "memory");
38836
+ var log22 = createLogger("memory");
38837
+ var DEFAULT_ROOT = join5(homedir6(), ".config", "claude-threads", "memory");
38401
38838
  var CHANNEL_BLOCK_MAX_BYTES = 25 * 1024;
38402
38839
 
38403
38840
  // src/memory/distiller.ts
38404
38841
  init_quick_query();
38405
38842
  init_logger();
38406
- var log22 = createLogger("memory");
38843
+ var log23 = createLogger("memory");
38407
38844
  // src/operations/commands/automation.ts
38408
38845
  init_emoji();
38409
38846
 
@@ -38412,46 +38849,46 @@ import { join as join7 } from "path";
38412
38849
  init_logger();
38413
38850
 
38414
38851
  // src/persistence/platform-list-store.ts
38415
- import { homedir as homedir6 } from "os";
38852
+ import { homedir as homedir7 } from "os";
38416
38853
  import { join as join6 } from "path";
38417
- var STORES_CONFIG_DIR = join6(homedir6(), ".config", "claude-threads");
38854
+ var STORES_CONFIG_DIR = join6(homedir7(), ".config", "claude-threads");
38418
38855
 
38419
38856
  // src/persistence/routines-store.ts
38420
- var log23 = createLogger("routines");
38857
+ var log24 = createLogger("routines");
38421
38858
  var DEFAULT_FILE = join7(STORES_CONFIG_DIR, "routines.yaml");
38422
38859
 
38423
38860
  // src/routines/parser.ts
38424
38861
  init_logger();
38425
- var log24 = createLogger("routines");
38862
+ var log25 = createLogger("routines");
38426
38863
 
38427
38864
  // src/persistence/watches-store.ts
38428
38865
  import { join as join8 } from "path";
38429
38866
  init_logger();
38430
- var log25 = createLogger("watches");
38867
+ var log26 = createLogger("watches");
38431
38868
  var DEFAULT_FILE2 = join8(STORES_CONFIG_DIR, "watches.yaml");
38432
38869
 
38433
38870
  // src/watches/parser.ts
38434
38871
  init_logger();
38435
- var log26 = createLogger("watches");
38872
+ var log27 = createLogger("watches");
38436
38873
 
38437
38874
  // src/operations/commands/guards.ts
38438
38875
  init_logger();
38439
- var log27 = createLogger("commands");
38440
- var sessionLog4 = createSessionLog(log27);
38876
+ var log28 = createLogger("commands");
38877
+ var sessionLog4 = createSessionLog(log28);
38441
38878
 
38442
38879
  // src/operations/commands/automation.ts
38443
38880
  init_logger();
38444
- var log28 = createLogger("commands");
38445
- var sessionLog5 = createSessionLog(log28);
38881
+ var log29 = createLogger("commands");
38882
+ var sessionLog5 = createSessionLog(log29);
38446
38883
 
38447
38884
  // src/operations/agent-actions/handler.ts
38448
38885
  init_logger();
38449
- var log29 = createLogger("agent-actions");
38450
- var sessionLog6 = createSessionLog(log29);
38886
+ var log30 = createLogger("agent-actions");
38887
+ var sessionLog6 = createSessionLog(log30);
38451
38888
 
38452
38889
  // src/session/lifecycle.ts
38453
- var log30 = createLogger("lifecycle");
38454
- var sessionLog7 = createSessionLog(log30);
38890
+ var log31 = createLogger("lifecycle");
38891
+ var sessionLog7 = createSessionLog(log31);
38455
38892
  var _inFlightSessionStarts = new Map;
38456
38893
  var CHAT_PLATFORM_PROMPT = generateChatPlatformPrompt();
38457
38894
 
@@ -38467,40 +38904,40 @@ init_logger();
38467
38904
  init_quick_query();
38468
38905
 
38469
38906
  // src/persistence/github-emails-store.ts
38470
- import { homedir as homedir7 } from "os";
38907
+ import { homedir as homedir8 } from "os";
38471
38908
  import { join as join9 } from "path";
38472
38909
  init_logger();
38473
- var log31 = createLogger("gh-emails");
38474
- var DEFAULT_CONFIG_DIR2 = join9(homedir7(), ".config", "claude-threads");
38910
+ var log32 = createLogger("gh-emails");
38911
+ var DEFAULT_CONFIG_DIR2 = join9(homedir8(), ".config", "claude-threads");
38475
38912
  var DEFAULT_FILE3 = join9(DEFAULT_CONFIG_DIR2, "github-emails.yaml");
38476
38913
 
38477
38914
  // src/operations/commands/handler.ts
38478
- var log32 = createLogger("commands");
38479
- var sessionLog8 = createSessionLog(log32);
38915
+ var log33 = createLogger("commands");
38916
+ var sessionLog8 = createSessionLog(log33);
38480
38917
  // src/operations/commands/memory.ts
38481
38918
  init_logger();
38482
- var log33 = createLogger("commands");
38483
- var sessionLog9 = createSessionLog(log33);
38919
+ var log34 = createLogger("commands");
38920
+ var sessionLog9 = createSessionLog(log34);
38484
38921
  // src/operations/suggestions/branch.ts
38485
38922
  init_quick_query();
38486
38923
  init_logger();
38487
38924
  import { exec as exec2 } from "child_process";
38488
38925
  import { promisify as promisify2 } from "util";
38489
38926
  var execAsync2 = promisify2(exec2);
38490
- var log34 = createLogger("branch");
38927
+ var log35 = createLogger("branch");
38491
38928
 
38492
38929
  // src/operations/worktree/handler.ts
38493
38930
  init_cli();
38494
38931
  init_logger();
38495
- var log35 = createLogger("worktree");
38496
- var sessionLog10 = createSessionLog(log35);
38932
+ var log36 = createLogger("worktree");
38933
+ var sessionLog10 = createSessionLog(log36);
38497
38934
  // src/operations/events/handler.ts
38498
38935
  init_logger();
38499
- var log36 = createLogger("events");
38500
- var sessionLog11 = createSessionLog(log36);
38936
+ var log37 = createLogger("events");
38937
+ var sessionLog11 = createSessionLog(log37);
38501
38938
  // src/operations/monitor/handler.ts
38502
38939
  init_logger();
38503
- var log37 = createLogger("monitor");
38940
+ var log38 = createLogger("monitor");
38504
38941
  var DEFAULT_INTERVAL_MS = 60 * 1000;
38505
38942
  // src/mcp/mcp-server.ts
38506
38943
  init_logger();
@@ -38588,16 +39025,16 @@ init_logger();
38588
39025
 
38589
39026
  // src/platform/mattermost/upload.ts
38590
39027
  init_logger();
38591
- import { readFile } from "fs/promises";
38592
- var log38 = createLogger("mm-upload");
39028
+ import { readFile as readFile2 } from "fs/promises";
39029
+ var log39 = createLogger("mm-upload");
38593
39030
  async function uploadFileMattermost(args) {
38594
39031
  const { url, token, channelId, threadId, filePath, filename, caption } = args;
38595
- const buffer = await readFile(filePath);
39032
+ const buffer = await readFile2(filePath);
38596
39033
  const uploadUrl = `${url}/api/v4/files?channel_id=${encodeURIComponent(channelId)}`;
38597
39034
  const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
38598
39035
  const formData = new FormData;
38599
39036
  formData.append("files", new Blob([arrayBuffer]), filename);
38600
- log38.debug(`POST /files (${buffer.length} bytes, ${filename})`);
39037
+ log39.debug(`POST /files (${buffer.length} bytes, ${filename})`);
38601
39038
  const uploadResponse = await fetch(uploadUrl, {
38602
39039
  method: "POST",
38603
39040
  headers: {
@@ -38621,7 +39058,7 @@ async function uploadFileMattermost(args) {
38621
39058
  root_id: resolvePostThreadId(threadId),
38622
39059
  file_ids: [fileInfo.id]
38623
39060
  };
38624
- log38.debug(`POST /posts (file_ids=[${fileInfo.id}])`);
39061
+ log39.debug(`POST /posts (file_ids=[${fileInfo.id}])`);
38625
39062
  const postResponse = await fetch(postUrl, {
38626
39063
  method: "POST",
38627
39064
  headers: {
@@ -39118,16 +39555,16 @@ ${code}
39118
39555
 
39119
39556
  // src/platform/slack/upload.ts
39120
39557
  init_logger();
39121
- import { readFile as readFile2 } from "fs/promises";
39122
- var log39 = createLogger("slack-upload");
39558
+ import { readFile as readFile3 } from "fs/promises";
39559
+ var log40 = createLogger("slack-upload");
39123
39560
  var DEFAULT_API_URL = "https://slack.com/api";
39124
39561
  async function uploadFileSlack(args) {
39125
39562
  const { botToken, channelId, threadTs, filePath, filename, caption } = args;
39126
39563
  const apiUrl = args.apiUrl ?? DEFAULT_API_URL;
39127
- const buffer = await readFile2(filePath);
39564
+ const buffer = await readFile3(filePath);
39128
39565
  const params = new URLSearchParams({ filename, length: String(buffer.length) });
39129
39566
  const step1Url = `${apiUrl}/files.getUploadURLExternal?${params.toString()}`;
39130
- log39.debug(`GET files.getUploadURLExternal (${buffer.length} bytes, ${filename})`);
39567
+ log40.debug(`GET files.getUploadURLExternal (${buffer.length} bytes, ${filename})`);
39131
39568
  const step1Response = await fetch(step1Url, {
39132
39569
  method: "GET",
39133
39570
  headers: {
@@ -39145,7 +39582,7 @@ async function uploadFileSlack(args) {
39145
39582
  const uploadUrl = step1Data.upload_url;
39146
39583
  const fileId = step1Data.file_id;
39147
39584
  const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
39148
- log39.debug(`POST <upload_url>`);
39585
+ log40.debug(`POST <upload_url>`);
39149
39586
  const step2Response = await fetch(uploadUrl, {
39150
39587
  method: "POST",
39151
39588
  headers: {
@@ -39165,7 +39602,7 @@ async function uploadFileSlack(args) {
39165
39602
  if (caption !== undefined) {
39166
39603
  step3Body.initial_comment = caption;
39167
39604
  }
39168
- log39.debug(`POST files.completeUploadExternal (file_id=${fileId}, thread_ts=${threadTs})`);
39605
+ log40.debug(`POST files.completeUploadExternal (file_id=${fileId}, thread_ts=${threadTs})`);
39169
39606
  const step3Response = await fetch(`${apiUrl}/files.completeUploadExternal`, {
39170
39607
  method: "POST",
39171
39608
  headers: {
@@ -39183,7 +39620,7 @@ async function uploadFileSlack(args) {
39183
39620
  throw new Error(`Slack completeUploadExternal error: ${step3Data.error || "unknown"}`);
39184
39621
  }
39185
39622
  if (!step3Data.ts) {
39186
- log39.warn(`Slack completeUploadExternal returned no ts; using fileId ${fileId} as postId. ` + `Do not use this id for updatePost/addReaction.`);
39623
+ log40.warn(`Slack completeUploadExternal returned no ts; using fileId ${fileId} as postId. ` + `Do not use this id for updatePost/addReaction.`);
39187
39624
  }
39188
39625
  return { fileId, postId: step3Data.ts ?? fileId };
39189
39626
  }