claude-threads 1.0.11 → 1.0.13

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/CHANGELOG.md CHANGED
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.13] - 2026-01-16
9
+
10
+ ### Fixed
11
+ - **Claude CLI detection for non-standard installations** - Improved detection for users who installed Claude CLI via non-npm methods (#222)
12
+ - Searches common installation paths (`/usr/local/bin`, `~/.local/bin`, `~/.bun/bin`, etc.)
13
+ - Uses `which claude` to resolve symlinks
14
+ - Parses multiple version output formats
15
+ - Shows helpful debug info (PATH directories) when not found
16
+ - Added `getClaudePath()` helper shared between version check and CLI spawning
17
+
18
+ ## [1.0.12] - 2026-01-15
19
+
20
+ ### Fixed
21
+ - **Skipped file feedback posting** - Fixed swapped arguments in createPost call that caused "Invalid RootId parameter" errors when posting feedback for skipped files (#221)
22
+
8
23
  ## [1.0.11] - 2026-01-15
9
24
 
10
25
  ### Added
package/dist/index.js CHANGED
@@ -46546,7 +46546,7 @@ function configExists() {
46546
46546
 
46547
46547
  // src/onboarding.ts
46548
46548
  var import_prompts = __toESM(require_prompts3(), 1);
46549
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
46549
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
46550
46550
  import { join, dirname as dirname2 } from "path";
46551
46551
  import { fileURLToPath } from "url";
46552
46552
 
@@ -46570,52 +46570,147 @@ var red = (s) => `${colors.red}${s}${colors.reset}`;
46570
46570
  // src/claude/version-check.ts
46571
46571
  var import_semver = __toESM(require_semver2(), 1);
46572
46572
  import { execSync } from "child_process";
46573
+ import { existsSync as existsSync2 } from "fs";
46574
+ var COMMON_CLAUDE_PATHS = [
46575
+ "/usr/local/bin/claude",
46576
+ "/opt/homebrew/bin/claude",
46577
+ `${process.env.HOME}/.local/bin/claude`,
46578
+ `${process.env.HOME}/.npm-global/bin/claude`,
46579
+ `${process.env.HOME}/.bun/bin/claude`,
46580
+ "/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js"
46581
+ ];
46573
46582
  var CLAUDE_CLI_VERSION_RANGE = ">=2.0.74 <2.2.0";
46574
- function getClaudeCliVersion() {
46575
- const claudePath = process.env.CLAUDE_PATH || "claude";
46583
+ function tryClaudeVersion(claudePath) {
46584
+ try {
46585
+ const output = execSync(`"${claudePath}" --version`, {
46586
+ encoding: "utf8",
46587
+ timeout: 5000,
46588
+ stdio: ["pipe", "pipe", "pipe"]
46589
+ }).trim();
46590
+ const patterns = [
46591
+ /^([\d]+\.[\d]+\.[\d]+)/,
46592
+ /version\s+([\d]+\.[\d]+\.[\d]+)/i,
46593
+ /v?([\d]+\.[\d]+\.[\d]+)/
46594
+ ];
46595
+ for (const pattern of patterns) {
46596
+ const match = output.match(pattern);
46597
+ if (match) {
46598
+ return { version: match[1], rawOutput: output, error: null, foundAt: claudePath };
46599
+ }
46600
+ }
46601
+ return { version: null, rawOutput: output, error: null, foundAt: claudePath };
46602
+ } catch (err) {
46603
+ const errorMessage = err instanceof Error ? err.message : "Unknown error";
46604
+ return { version: null, rawOutput: null, error: errorMessage };
46605
+ }
46606
+ }
46607
+ function findClaudeInPath() {
46576
46608
  try {
46577
- const output = execSync(`${claudePath} --version`, {
46609
+ const result = execSync("which claude", {
46578
46610
  encoding: "utf8",
46579
46611
  timeout: 5000,
46580
46612
  stdio: ["pipe", "pipe", "pipe"]
46581
46613
  }).trim();
46582
- const match = output.match(/^([\d.]+)/);
46583
- return match ? match[1] : null;
46614
+ return result || null;
46584
46615
  } catch {
46585
46616
  return null;
46586
46617
  }
46587
46618
  }
46619
+ function getClaudeCliVersion() {
46620
+ if (process.env.CLAUDE_PATH) {
46621
+ const result = tryClaudeVersion(process.env.CLAUDE_PATH);
46622
+ if (!result.error) {
46623
+ return result;
46624
+ }
46625
+ }
46626
+ const whichResult = findClaudeInPath();
46627
+ if (whichResult) {
46628
+ const result = tryClaudeVersion(whichResult);
46629
+ if (!result.error) {
46630
+ return result;
46631
+ }
46632
+ }
46633
+ const pathResult = tryClaudeVersion("claude");
46634
+ if (!pathResult.error) {
46635
+ return pathResult;
46636
+ }
46637
+ for (const path of COMMON_CLAUDE_PATHS) {
46638
+ if (existsSync2(path)) {
46639
+ const result = tryClaudeVersion(path);
46640
+ if (!result.error) {
46641
+ return result;
46642
+ }
46643
+ }
46644
+ }
46645
+ const checkedPaths = process.env.CLAUDE_PATH ? [process.env.CLAUDE_PATH, "claude (in PATH)", ...COMMON_CLAUDE_PATHS] : ["claude (in PATH)", ...COMMON_CLAUDE_PATHS];
46646
+ return {
46647
+ version: null,
46648
+ rawOutput: null,
46649
+ error: `Command 'claude' not found. Searched: ${checkedPaths.slice(0, 3).join(", ")}...`
46650
+ };
46651
+ }
46588
46652
  function isVersionCompatible(version) {
46589
46653
  const semverVersion = import_semver.coerce(version);
46590
46654
  if (!semverVersion)
46591
46655
  return false;
46592
46656
  return import_semver.satisfies(semverVersion, CLAUDE_CLI_VERSION_RANGE);
46593
46657
  }
46658
+ function getClaudePath() {
46659
+ if (process.env.CLAUDE_PATH) {
46660
+ return process.env.CLAUDE_PATH;
46661
+ }
46662
+ const whichResult = findClaudeInPath();
46663
+ if (whichResult) {
46664
+ return whichResult;
46665
+ }
46666
+ for (const path of COMMON_CLAUDE_PATHS) {
46667
+ if (existsSync2(path)) {
46668
+ const result = tryClaudeVersion(path);
46669
+ if (!result.error) {
46670
+ return path;
46671
+ }
46672
+ }
46673
+ }
46674
+ return "claude";
46675
+ }
46594
46676
  function validateClaudeCli() {
46595
- const version = getClaudeCliVersion();
46596
- if (!version) {
46677
+ const result = getClaudeCliVersion();
46678
+ if (result.error) {
46679
+ const claudePath = process.env.CLAUDE_PATH || "claude";
46597
46680
  return {
46598
46681
  installed: false,
46599
46682
  version: null,
46600
46683
  compatible: false,
46601
- message: "Claude CLI not found. Install it with: bun install -g @anthropic-ai/claude-code"
46684
+ message: `Claude CLI not found at '${claudePath}'. Install it with: npm install -g @anthropic-ai/claude-code`,
46685
+ error: result.error
46686
+ };
46687
+ }
46688
+ if (!result.version && result.rawOutput) {
46689
+ return {
46690
+ installed: true,
46691
+ version: null,
46692
+ compatible: true,
46693
+ message: `Claude CLI found (version unknown)`,
46694
+ rawOutput: result.rawOutput
46602
46695
  };
46603
46696
  }
46604
- const compatible = isVersionCompatible(version);
46697
+ const compatible = isVersionCompatible(result.version);
46605
46698
  if (!compatible) {
46606
46699
  return {
46607
46700
  installed: true,
46608
- version,
46701
+ version: result.version,
46609
46702
  compatible: false,
46610
- message: `Claude CLI version ${version} is not compatible. Required: ${CLAUDE_CLI_VERSION_RANGE}
46611
- ` + `Install a compatible version: bun install -g @anthropic-ai/claude-code@2.0.76`
46703
+ message: `Claude CLI version ${result.version} is not compatible. Required: ${CLAUDE_CLI_VERSION_RANGE}
46704
+ ` + `Install a compatible version: npm install -g @anthropic-ai/claude-code@2.1.1`,
46705
+ rawOutput: result.rawOutput ?? undefined
46612
46706
  };
46613
46707
  }
46614
46708
  return {
46615
46709
  installed: true,
46616
- version,
46710
+ version: result.version,
46617
46711
  compatible: true,
46618
- message: `Claude CLI ${version} \u2713`
46712
+ message: `Claude CLI ${result.version} \u2713`,
46713
+ rawOutput: result.rawOutput ?? undefined
46619
46714
  };
46620
46715
  }
46621
46716
 
@@ -46759,7 +46854,7 @@ async function runOnboarding(reconfigure = false) {
46759
46854
  console.log(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
46760
46855
  console.log("");
46761
46856
  let existingConfig = null;
46762
- if (reconfigure && existsSync2(CONFIG_PATH)) {
46857
+ if (reconfigure && existsSync3(CONFIG_PATH)) {
46763
46858
  try {
46764
46859
  const content = readFileSync2(CONFIG_PATH, "utf-8");
46765
46860
  existingConfig = Bun.YAML.parse(content);
@@ -46785,25 +46880,52 @@ async function runOnboarding(reconfigure = false) {
46785
46880
  console.log("");
46786
46881
  console.log(dim(" \u274C Claude Code CLI not found"));
46787
46882
  console.log("");
46788
- console.log(dim(" Install it with:"));
46789
- console.log(dim(" bun install -g @anthropic-ai/claude-code"));
46883
+ if (claudeCheck.error) {
46884
+ console.log(dim(` Error: ${claudeCheck.error}`));
46885
+ console.log("");
46886
+ }
46887
+ console.log(dim(" Debug info:"));
46888
+ const pathDirs = (process.env.PATH || "").split(":").slice(0, 5);
46889
+ console.log(dim(` PATH (first 5 dirs): ${pathDirs.join(":")}`));
46890
+ console.log("");
46891
+ console.log(dim(" Solutions:"));
46790
46892
  console.log("");
46791
- console.log(dim(" Then run `claude-threads` again."));
46893
+ console.log(dim(" 1. Install Claude Code CLI:"));
46894
+ console.log(dim(" npm install -g @anthropic-ai/claude-code"));
46895
+ console.log("");
46896
+ console.log(dim(" 2. If already installed, find it and set CLAUDE_PATH:"));
46897
+ console.log(dim(" # Find where it is:"));
46898
+ console.log(dim(" which claude"));
46899
+ console.log(dim(" # Or search common locations:"));
46900
+ console.log(dim(" ls ~/.local/bin/claude ~/.bun/bin/claude /usr/local/bin/claude 2>/dev/null"));
46901
+ console.log(dim(" # Then run with the path:"));
46902
+ console.log(dim(" CLAUDE_PATH=/path/to/claude claude-threads"));
46903
+ console.log("");
46904
+ console.log(dim(" 3. Add Claude's directory to PATH in your shell config"));
46792
46905
  console.log("");
46793
46906
  process.exit(1);
46794
46907
  }
46795
46908
  if (!claudeCheck.compatible) {
46796
46909
  console.log("");
46797
- console.log(dim(` \u26A0\uFE0F Claude Code CLI ${claudeCheck.version} is not compatible`));
46798
- console.log("");
46799
- console.log(dim(` Install a compatible version:`));
46800
- console.log(dim(" bun install -g @anthropic-ai/claude-code@2.0.76"));
46910
+ if (claudeCheck.version) {
46911
+ console.log(dim(` \u26A0\uFE0F Claude Code CLI ${claudeCheck.version} is not compatible`));
46912
+ console.log("");
46913
+ console.log(dim(` Install a compatible version:`));
46914
+ console.log(dim(" npm install -g @anthropic-ai/claude-code@2.1.1"));
46915
+ } else {
46916
+ console.log(dim(" \u26A0\uFE0F Claude Code CLI found but version could not be determined"));
46917
+ if (claudeCheck.rawOutput) {
46918
+ console.log(dim(` Output from "claude --version": ${claudeCheck.rawOutput}`));
46919
+ }
46920
+ console.log("");
46921
+ console.log(dim(" This may work fine - Claude was installed in a non-standard way."));
46922
+ }
46801
46923
  console.log("");
46802
46924
  const { continueAnyway } = await import_prompts.default({
46803
46925
  type: "confirm",
46804
46926
  name: "continueAnyway",
46805
46927
  message: "Continue anyway? (may not work correctly)",
46806
- initial: false
46928
+ initial: !claudeCheck.version
46807
46929
  }, { onCancel });
46808
46930
  if (!continueAnyway) {
46809
46931
  console.log("");
@@ -46811,7 +46933,8 @@ async function runOnboarding(reconfigure = false) {
46811
46933
  process.exit(0);
46812
46934
  }
46813
46935
  } else {
46814
- console.log(dim(` \u2713 Claude Code CLI ${claudeCheck.version}`));
46936
+ const versionInfo = claudeCheck.version ?? "version unknown";
46937
+ console.log(dim(` \u2713 Claude Code CLI ${versionInfo}`));
46815
46938
  }
46816
46939
  console.log("");
46817
46940
  console.log(dim(" \uD83D\uDCD6 Need help creating a bot?"));
@@ -49911,7 +50034,7 @@ class SlackPermissionApi {
49911
50034
  import { EventEmitter as EventEmitter4 } from "events";
49912
50035
 
49913
50036
  // src/persistence/session-store.ts
49914
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync } from "fs";
50037
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync } from "fs";
49915
50038
  import { homedir as homedir2 } from "os";
49916
50039
  import { join as join2 } from "path";
49917
50040
  var log5 = createLogger("persist");
@@ -49932,13 +50055,13 @@ class SessionStore {
49932
50055
  this.sessionsFile = DEFAULT_SESSIONS_FILE;
49933
50056
  this.configDir = DEFAULT_CONFIG_DIR;
49934
50057
  }
49935
- if (!existsSync3(this.configDir)) {
50058
+ if (!existsSync4(this.configDir)) {
49936
50059
  mkdirSync2(this.configDir, { recursive: true });
49937
50060
  }
49938
50061
  }
49939
50062
  load() {
49940
50063
  const sessions = new Map;
49941
- if (!existsSync3(this.sessionsFile)) {
50064
+ if (!existsSync4(this.sessionsFile)) {
49942
50065
  log5.debug("No sessions file found");
49943
50066
  return sessions;
49944
50067
  }
@@ -50117,7 +50240,7 @@ class SessionStore {
50117
50240
  return;
50118
50241
  }
50119
50242
  loadRaw() {
50120
- if (!existsSync3(this.sessionsFile)) {
50243
+ if (!existsSync4(this.sessionsFile)) {
50121
50244
  return { version: STORE_VERSION, sessions: {} };
50122
50245
  }
50123
50246
  try {
@@ -50136,12 +50259,12 @@ class SessionStore {
50136
50259
  init_emoji();
50137
50260
 
50138
50261
  // src/cleanup/scheduler.ts
50139
- import { existsSync as existsSync5 } from "fs";
50262
+ import { existsSync as existsSync6 } from "fs";
50140
50263
  import { readdir, rm } from "fs/promises";
50141
50264
  import { join as join5 } from "path";
50142
50265
 
50143
50266
  // src/persistence/thread-logger.ts
50144
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, appendFileSync, readdirSync, statSync, unlinkSync, rmdirSync, readFileSync as readFileSync4 } from "fs";
50267
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, appendFileSync, readdirSync, statSync, unlinkSync, rmdirSync, readFileSync as readFileSync4 } from "fs";
50145
50268
  import { homedir as homedir3 } from "os";
50146
50269
  import { join as join3, dirname as dirname3 } from "path";
50147
50270
  var log6 = createLogger("thread-log");
@@ -50168,7 +50291,7 @@ class ThreadLoggerImpl {
50168
50291
  this.logPath = join3(LOGS_BASE_DIR, platformId, `${claudeSessionId}.jsonl`);
50169
50292
  if (this.enabled) {
50170
50293
  const dir = dirname3(this.logPath);
50171
- if (!existsSync4(dir)) {
50294
+ if (!existsSync5(dir)) {
50172
50295
  mkdirSync3(dir, { recursive: true });
50173
50296
  }
50174
50297
  this.flushTimer = setInterval(() => {
@@ -50337,7 +50460,7 @@ function createThreadLogger(platformId, threadId, claudeSessionId, options2) {
50337
50460
  function cleanupOldLogs(retentionDays = 30) {
50338
50461
  const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1000;
50339
50462
  let deletedCount = 0;
50340
- if (!existsSync4(LOGS_BASE_DIR)) {
50463
+ if (!existsSync5(LOGS_BASE_DIR)) {
50341
50464
  return 0;
50342
50465
  }
50343
50466
  try {
@@ -50385,7 +50508,7 @@ function getLogFilePath(platformId, sessionId) {
50385
50508
  function readRecentLogEntries(platformId, sessionId, maxLines = 50) {
50386
50509
  const logPath = getLogFilePath(platformId, sessionId);
50387
50510
  log6.debug(`Reading log entries from: ${logPath}`);
50388
- if (!existsSync4(logPath)) {
50511
+ if (!existsSync5(logPath)) {
50389
50512
  log6.debug(`Log file does not exist: ${logPath}`);
50390
50513
  return [];
50391
50514
  }
@@ -50809,7 +50932,7 @@ class CleanupScheduler {
50809
50932
  async cleanupOrphanedWorktrees() {
50810
50933
  const worktreesDir = getWorktreesDir();
50811
50934
  const result = { cleaned: 0, metadata: 0 };
50812
- if (!existsSync5(worktreesDir)) {
50935
+ if (!existsSync6(worktreesDir)) {
50813
50936
  log8.debug("No worktrees directory exists, nothing to clean");
50814
50937
  return result;
50815
50938
  }
@@ -50951,7 +51074,7 @@ import { spawn as spawn2 } from "child_process";
50951
51074
  import { EventEmitter as EventEmitter2 } from "events";
50952
51075
  import { resolve as resolve2, dirname as dirname5 } from "path";
50953
51076
  import { fileURLToPath as fileURLToPath2 } from "url";
50954
- import { existsSync as existsSync6, readFileSync as readFileSync5, watchFile, unwatchFile, unlinkSync as unlinkSync2, statSync as statSync2, readdirSync as readdirSync2 } from "fs";
51077
+ import { existsSync as existsSync7, readFileSync as readFileSync5, watchFile, unwatchFile, unlinkSync as unlinkSync2, statSync as statSync2, readdirSync as readdirSync2 } from "fs";
50955
51078
  import { tmpdir } from "os";
50956
51079
  import { join as join6 } from "path";
50957
51080
  var log9 = createLogger("claude");
@@ -50997,7 +51120,7 @@ class ClaudeCli extends EventEmitter2 {
50997
51120
  if (!this.statusFilePath)
50998
51121
  return null;
50999
51122
  try {
51000
- if (existsSync6(this.statusFilePath)) {
51123
+ if (existsSync7(this.statusFilePath)) {
51001
51124
  const data = readFileSync5(this.statusFilePath, "utf8");
51002
51125
  this.lastStatusData = JSON.parse(data);
51003
51126
  }
@@ -51025,7 +51148,7 @@ class ClaudeCli extends EventEmitter2 {
51025
51148
  if (this.statusFilePath) {
51026
51149
  unwatchFile(this.statusFilePath);
51027
51150
  try {
51028
- if (existsSync6(this.statusFilePath)) {
51151
+ if (existsSync7(this.statusFilePath)) {
51029
51152
  unlinkSync2(this.statusFilePath);
51030
51153
  }
51031
51154
  } catch {}
@@ -51036,7 +51159,7 @@ class ClaudeCli extends EventEmitter2 {
51036
51159
  throw new Error("Already running");
51037
51160
  this.stderrBuffer = "";
51038
51161
  cleanupBrowserBridgeSockets();
51039
- const claudePath = process.env.CLAUDE_PATH || "claude";
51162
+ const claudePath = getClaudePath();
51040
51163
  const args = [
51041
51164
  "--input-format",
51042
51165
  "stream-json",
@@ -51258,7 +51381,7 @@ class ClaudeCli extends EventEmitter2 {
51258
51381
  }
51259
51382
 
51260
51383
  // src/version.ts
51261
- import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
51384
+ import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
51262
51385
  import { dirname as dirname6, resolve as resolve3 } from "path";
51263
51386
  import { fileURLToPath as fileURLToPath3 } from "url";
51264
51387
  var __dirname3 = dirname6(fileURLToPath3(import.meta.url));
@@ -51269,7 +51392,7 @@ function loadPackageJson() {
51269
51392
  resolve3(process.cwd(), "package.json")
51270
51393
  ];
51271
51394
  for (const candidate of candidates) {
51272
- if (existsSync7(candidate)) {
51395
+ if (existsSync8(candidate)) {
51273
51396
  try {
51274
51397
  const pkg = JSON.parse(readFileSync6(candidate, "utf-8"));
51275
51398
  if (pkg.name === "claude-threads") {
@@ -51614,7 +51737,7 @@ ${avoidCommands.map((c) => `- \`!${c.command}\` - ${c.reason}`).join(`
51614
51737
  }
51615
51738
  // src/session/lifecycle.ts
51616
51739
  import { randomUUID as randomUUID4 } from "crypto";
51617
- import { existsSync as existsSync10 } from "fs";
51740
+ import { existsSync as existsSync11 } from "fs";
51618
51741
 
51619
51742
  // src/utils/keep-alive.ts
51620
51743
  import { spawn as spawn3 } from "child_process";
@@ -56589,7 +56712,7 @@ class MessageManager {
56589
56712
  this.session.claude.sendMessage(content);
56590
56713
  if (skippedFiles.length > 0) {
56591
56714
  const feedback = this.formatSkippedFilesFeedback(skippedFiles);
56592
- await this.platform.createPost(this.threadId, feedback);
56715
+ await this.platform.createPost(feedback, this.threadId);
56593
56716
  }
56594
56717
  this.session.lastActivityAt = new Date;
56595
56718
  this.session.isProcessing = true;
@@ -56748,7 +56871,7 @@ function formatUptime(startedAt) {
56748
56871
  }
56749
56872
 
56750
56873
  // src/changelog.ts
56751
- import { readFileSync as readFileSync7, existsSync as existsSync8 } from "fs";
56874
+ import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
56752
56875
  import { dirname as dirname7, resolve as resolve4 } from "path";
56753
56876
  import { fileURLToPath as fileURLToPath4 } from "url";
56754
56877
  var __dirname4 = dirname7(fileURLToPath4(import.meta.url));
@@ -56759,7 +56882,7 @@ function getReleaseNotes(version) {
56759
56882
  ];
56760
56883
  let changelogPath = null;
56761
56884
  for (const p of possiblePaths) {
56762
- if (existsSync8(p)) {
56885
+ if (existsSync9(p)) {
56763
56886
  changelogPath = p;
56764
56887
  break;
56765
56888
  }
@@ -57106,7 +57229,7 @@ async function buildStatusBar(sessionCount, config, formatter, platformId) {
57106
57229
  items.push(formatter.formatCode(`\u23F8\uFE0F Update deferred`));
57107
57230
  }
57108
57231
  }
57109
- const claudeVersion = getClaudeCliVersion();
57232
+ const claudeVersion = getClaudeCliVersion().version;
57110
57233
  const versionStr = claudeVersion ? `v${VERSION} \xB7 CLI ${claudeVersion}` : `v${VERSION}`;
57111
57234
  items.push(formatter.formatCode(versionStr));
57112
57235
  items.push(formatter.formatCode(`${sessionCount}/${config.maxSessions} sessions`));
@@ -57799,7 +57922,7 @@ async function collectBugReportContext(session, errorContext) {
57799
57922
  const recentLogEntries = readRecentLogEntries(platformId, sessionId, BUG_REPORT_LOG_ENTRIES);
57800
57923
  return {
57801
57924
  version: VERSION,
57802
- claudeCliVersion: getClaudeCliVersion(),
57925
+ claudeCliVersion: getClaudeCliVersion().version ?? "unknown",
57803
57926
  platform: session.platform.displayName,
57804
57927
  platformType: session.platform.platformType,
57805
57928
  nodeVersion: process.version,
@@ -58096,7 +58219,7 @@ function formatBugPreview(title, description, context, imageUrls, imageErrors, f
58096
58219
  // src/operations/commands/handler.ts
58097
58220
  import { randomUUID as randomUUID2 } from "crypto";
58098
58221
  import { resolve as resolve5 } from "path";
58099
- import { existsSync as existsSync9, statSync as statSync3 } from "fs";
58222
+ import { existsSync as existsSync10, statSync as statSync3 } from "fs";
58100
58223
 
58101
58224
  // node_modules/update-notifier/update-notifier.js
58102
58225
  import process10 from "process";
@@ -61616,7 +61739,7 @@ async function changeDirectory(session, newDir, username, ctx) {
61616
61739
  const expandedDir = newDir.startsWith("~") ? newDir.replace("~", process.env.HOME || "") : newDir;
61617
61740
  const absoluteDir = resolve5(expandedDir);
61618
61741
  const formatter = session.platform.getFormatter();
61619
- if (!existsSync9(absoluteDir)) {
61742
+ if (!existsSync10(absoluteDir)) {
61620
61743
  await postError(session, `Directory does not exist: ${formatter.formatCode(newDir)}`);
61621
61744
  sessionLog2(session).warn(`\uD83D\uDCC2 Directory does not exist: ${newDir}`);
61622
61745
  return;
@@ -61771,7 +61894,7 @@ async function updateSessionHeader(session, ctx) {
61771
61894
  const permMode = isInteractive ? "\uD83D\uDD10 Interactive" : "\u26A1 Auto";
61772
61895
  const otherParticipants = [...session.sessionAllowedUsers].filter((u) => u !== session.startedBy).map((u) => formatter.formatUserMention(u)).join(", ");
61773
61896
  const statusItems = [];
61774
- const claudeVersion = getClaudeCliVersion();
61897
+ const claudeVersion = getClaudeCliVersion().version;
61775
61898
  const versionStr = claudeVersion ? `v${VERSION} \xB7 CLI ${claudeVersion}` : `v${VERSION}`;
61776
61899
  statusItems.push(formatter.formatCode(versionStr));
61777
61900
  if (session.usageStats) {
@@ -63472,7 +63595,7 @@ async function resumeSession(state, ctx) {
63472
63595
  log25.warn(`Max sessions reached, skipping resume for ${shortId}...`);
63473
63596
  return;
63474
63597
  }
63475
- if (!existsSync10(state.workingDir)) {
63598
+ if (!existsSync11(state.workingDir)) {
63476
63599
  log25.warn(`Working directory ${state.workingDir} no longer exists, skipping resume for ${shortId}...`);
63477
63600
  ctx.state.sessionStore.remove(`${state.platformId}:${state.threadId}`);
63478
63601
  const resumeFormatter = platform.getFormatter();
@@ -75927,7 +76050,7 @@ class UpdateScheduler extends EventEmitter8 {
75927
76050
 
75928
76051
  // src/auto-update/installer.ts
75929
76052
  import { spawn as spawn6 } from "child_process";
75930
- import { existsSync as existsSync12, readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4 } from "fs";
76053
+ import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4 } from "fs";
75931
76054
  import { dirname as dirname8, resolve as resolve6 } from "path";
75932
76055
  import { homedir as homedir5 } from "os";
75933
76056
  var log30 = createLogger("installer");
@@ -75935,7 +76058,7 @@ var STATE_PATH = resolve6(homedir5(), ".config", "claude-threads", UPDATE_STATE_
75935
76058
  var PACKAGE_NAME2 = "claude-threads";
75936
76059
  function loadUpdateState() {
75937
76060
  try {
75938
- if (existsSync12(STATE_PATH)) {
76061
+ if (existsSync13(STATE_PATH)) {
75939
76062
  const content = readFileSync9(STATE_PATH, "utf-8");
75940
76063
  return JSON.parse(content);
75941
76064
  }
@@ -75947,7 +76070,7 @@ function loadUpdateState() {
75947
76070
  function saveUpdateState(state) {
75948
76071
  try {
75949
76072
  const dir = dirname8(STATE_PATH);
75950
- if (!existsSync12(dir)) {
76073
+ if (!existsSync13(dir)) {
75951
76074
  mkdirSync4(dir, { recursive: true });
75952
76075
  }
75953
76076
  writeFileSync5(STATE_PATH, JSON.stringify(state, null, 2), "utf-8");
@@ -75958,7 +76081,7 @@ function saveUpdateState(state) {
75958
76081
  }
75959
76082
  function clearUpdateState() {
75960
76083
  try {
75961
- if (existsSync12(STATE_PATH)) {
76084
+ if (existsSync13(STATE_PATH)) {
75962
76085
  writeFileSync5(STATE_PATH, "{}", "utf-8");
75963
76086
  }
75964
76087
  } catch (err) {
@@ -41444,7 +41444,7 @@ class MessageManager {
41444
41444
  this.session.claude.sendMessage(content);
41445
41445
  if (skippedFiles.length > 0) {
41446
41446
  const feedback = this.formatSkippedFilesFeedback(skippedFiles);
41447
- await this.platform.createPost(this.threadId, feedback);
41447
+ await this.platform.createPost(feedback, this.threadId);
41448
41448
  }
41449
41449
  this.session.lastActivityAt = new Date;
41450
41450
  this.session.isProcessing = true;
@@ -41554,6 +41554,70 @@ var __dirname3 = dirname2(fileURLToPath2(import.meta.url));
41554
41554
 
41555
41555
  // src/claude/version-check.ts
41556
41556
  var import_semver = __toESM(require_semver2(), 1);
41557
+ import { execSync } from "child_process";
41558
+ import { existsSync as existsSync2 } from "fs";
41559
+ var COMMON_CLAUDE_PATHS = [
41560
+ "/usr/local/bin/claude",
41561
+ "/opt/homebrew/bin/claude",
41562
+ `${process.env.HOME}/.local/bin/claude`,
41563
+ `${process.env.HOME}/.npm-global/bin/claude`,
41564
+ `${process.env.HOME}/.bun/bin/claude`,
41565
+ "/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js"
41566
+ ];
41567
+ function tryClaudeVersion(claudePath) {
41568
+ try {
41569
+ const output = execSync(`"${claudePath}" --version`, {
41570
+ encoding: "utf8",
41571
+ timeout: 5000,
41572
+ stdio: ["pipe", "pipe", "pipe"]
41573
+ }).trim();
41574
+ const patterns = [
41575
+ /^([\d]+\.[\d]+\.[\d]+)/,
41576
+ /version\s+([\d]+\.[\d]+\.[\d]+)/i,
41577
+ /v?([\d]+\.[\d]+\.[\d]+)/
41578
+ ];
41579
+ for (const pattern of patterns) {
41580
+ const match = output.match(pattern);
41581
+ if (match) {
41582
+ return { version: match[1], rawOutput: output, error: null, foundAt: claudePath };
41583
+ }
41584
+ }
41585
+ return { version: null, rawOutput: output, error: null, foundAt: claudePath };
41586
+ } catch (err) {
41587
+ const errorMessage = err instanceof Error ? err.message : "Unknown error";
41588
+ return { version: null, rawOutput: null, error: errorMessage };
41589
+ }
41590
+ }
41591
+ function findClaudeInPath() {
41592
+ try {
41593
+ const result = execSync("which claude", {
41594
+ encoding: "utf8",
41595
+ timeout: 5000,
41596
+ stdio: ["pipe", "pipe", "pipe"]
41597
+ }).trim();
41598
+ return result || null;
41599
+ } catch {
41600
+ return null;
41601
+ }
41602
+ }
41603
+ function getClaudePath() {
41604
+ if (process.env.CLAUDE_PATH) {
41605
+ return process.env.CLAUDE_PATH;
41606
+ }
41607
+ const whichResult = findClaudeInPath();
41608
+ if (whichResult) {
41609
+ return whichResult;
41610
+ }
41611
+ for (const path of COMMON_CLAUDE_PATHS) {
41612
+ if (existsSync2(path)) {
41613
+ const result = tryClaudeVersion(path);
41614
+ if (!result.error) {
41615
+ return path;
41616
+ }
41617
+ }
41618
+ }
41619
+ return "claude";
41620
+ }
41557
41621
 
41558
41622
  // src/utils/keep-alive.ts
41559
41623
  import { spawn } from "child_process";
@@ -42007,7 +42071,7 @@ import { spawn as spawn2 } from "child_process";
42007
42071
  import { EventEmitter as EventEmitter2 } from "events";
42008
42072
  import { resolve as resolve3, dirname as dirname4 } from "path";
42009
42073
  import { fileURLToPath as fileURLToPath3 } from "url";
42010
- import { existsSync as existsSync2, readFileSync as readFileSync2, watchFile, unwatchFile, unlinkSync, statSync, readdirSync } from "fs";
42074
+ import { existsSync as existsSync3, readFileSync as readFileSync2, watchFile, unwatchFile, unlinkSync, statSync, readdirSync } from "fs";
42011
42075
  import { tmpdir } from "os";
42012
42076
  import { join as join2 } from "path";
42013
42077
  var log7 = createLogger("claude");
@@ -42053,7 +42117,7 @@ class ClaudeCli extends EventEmitter2 {
42053
42117
  if (!this.statusFilePath)
42054
42118
  return null;
42055
42119
  try {
42056
- if (existsSync2(this.statusFilePath)) {
42120
+ if (existsSync3(this.statusFilePath)) {
42057
42121
  const data = readFileSync2(this.statusFilePath, "utf8");
42058
42122
  this.lastStatusData = JSON.parse(data);
42059
42123
  }
@@ -42081,7 +42145,7 @@ class ClaudeCli extends EventEmitter2 {
42081
42145
  if (this.statusFilePath) {
42082
42146
  unwatchFile(this.statusFilePath);
42083
42147
  try {
42084
- if (existsSync2(this.statusFilePath)) {
42148
+ if (existsSync3(this.statusFilePath)) {
42085
42149
  unlinkSync(this.statusFilePath);
42086
42150
  }
42087
42151
  } catch {}
@@ -42092,7 +42156,7 @@ class ClaudeCli extends EventEmitter2 {
42092
42156
  throw new Error("Already running");
42093
42157
  this.stderrBuffer = "";
42094
42158
  cleanupBrowserBridgeSockets();
42095
- const claudePath = process.env.CLAUDE_PATH || "claude";
42159
+ const claudePath = getClaudePath();
42096
42160
  const args = [
42097
42161
  "--input-format",
42098
42162
  "stream-json",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-threads",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Share Claude Code sessions live in a Mattermost channel with interactive features",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",