claude-threads 1.7.1 → 1.8.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.
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.8.1] - 2026-04-21
9
+
10
+ ### Fixed
11
+ - **Interactive users silently demoted to headless when `autoUpdate` was enabled** — the auto-restart daemon runs the child as a bash background job (`&`), which leaves stdout piped and stdin detached. Ink can't render there, so the TUI dropped out without any error. Three prior patches (#287, #300, #317) each fixed the active crash mode inside the daemon path; none questioned whether interactive users should be routed through the daemon at all. The daemon is now skipped when `process.stdout.isTTY` and `--headless` isn't set. Unattended paths (explicit `--auto-restart`, `--headless`, or no TTY) still go through the daemon. (#333)
12
+
13
+ ## [1.8.0] - 2026-04-21
14
+
15
+ ### Added
16
+ - **Pass `MCP_CONNECTION_NONBLOCKING=true` to the Claude child** — caps `--mcp-config` connects at 5s so a slow MCP server never delays session startup. Requires Claude CLI 2.1.89+. Set it explicitly in the bot's own env to override.
17
+ - **Pass `ENABLE_PROMPT_CACHING_1H=true` to the Claude child** — opts into the 1-hour prompt cache TTL, meaningfully reducing re-caching cost on long-lived threads that idle past the default 5-minute window. Requires Claude CLI 2.1.108+. Set it explicitly in the bot's own env to override.
18
+ - **Documented `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1`** as an opt-in hardening flag. When set on the bot's env it passes through to Claude, which strips the specific credential env vars `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`, `AWS_BEARER_TOKEN_BEDROCK`, and `GOOGLE_APPLICATION_CREDENTIALS` from any Bash, hook, or stdio MCP subprocess it spawns (empirically verified on CLI 2.1.116). Bot-specific vars like `PLATFORM_TOKEN` / `MATTERMOST_TOKEN` / `SLACK_BOT_TOKEN` pass through untouched. **Side effect:** the flag also forces Claude's permission mode to `default` and rejects `--dangerously-skip-permissions`; the bot now warns at startup if the flag is set alongside any platform configured with `skipPermissions: true`. Requires Claude CLI 2.1.83+.
19
+
20
+ ### Fixed
21
+ - **Stale Claude CLI version range in `CLAUDE.md`** — the docs said `>=2.0.74 <=2.0.76`, but the actual pin in `version-check.ts` has been `>=2.0.74 <2.2.0` since v1.x. Also bumped the "install a compatible version" hint in the runtime error from `@2.1.1` to `@2.1.116`.
22
+
8
23
  ## [1.7.1] - 2026-04-21
9
24
 
10
25
  ### Fixed
package/dist/index.js CHANGED
@@ -50038,7 +50038,7 @@ function validateClaudeCli() {
50038
50038
  version: result.version,
50039
50039
  compatible: false,
50040
50040
  message: `Claude CLI version ${result.version} is not compatible. Required: ${CLAUDE_CLI_VERSION_RANGE}
50041
- ` + `Install a compatible version: npm install -g @anthropic-ai/claude-code@2.1.1`,
50041
+ ` + `Install a compatible version: npm install -g @anthropic-ai/claude-code@2.1.116`,
50042
50042
  rawOutput: result.rawOutput ?? undefined
50043
50043
  };
50044
50044
  }
@@ -54260,6 +54260,25 @@ function cleanupBrowserBridgeSockets() {
54260
54260
  log10.debug(`Browser bridge cleanup failed: ${err}`);
54261
54261
  }
54262
54262
  }
54263
+ function buildClaudeChildEnv(parentEnv, account) {
54264
+ const env = { ...parentEnv };
54265
+ if (env.MCP_CONNECTION_NONBLOCKING === undefined) {
54266
+ env.MCP_CONNECTION_NONBLOCKING = "true";
54267
+ }
54268
+ if (env.ENABLE_PROMPT_CACHING_1H === undefined) {
54269
+ env.ENABLE_PROMPT_CACHING_1H = "true";
54270
+ }
54271
+ if (account?.home) {
54272
+ env.HOME = account.home;
54273
+ env.USERPROFILE = account.home;
54274
+ delete env.ANTHROPIC_API_KEY;
54275
+ delete env.CLAUDE_CODE_OAUTH_TOKEN;
54276
+ } else if (account?.apiKey) {
54277
+ env.ANTHROPIC_API_KEY = account.apiKey;
54278
+ delete env.CLAUDE_CODE_OAUTH_TOKEN;
54279
+ }
54280
+ return env;
54281
+ }
54263
54282
  function isErrorResultEvent(event) {
54264
54283
  const ev = event;
54265
54284
  if (typeof ev.subtype === "string" && ev.subtype.startsWith("error"))
@@ -54561,20 +54580,7 @@ class ClaudeCli extends EventEmitter2 {
54561
54580
  return true;
54562
54581
  }
54563
54582
  buildChildEnv() {
54564
- const account = this.options.account;
54565
- if (!account)
54566
- return process.env;
54567
- const env = { ...process.env };
54568
- if (account.home) {
54569
- env.HOME = account.home;
54570
- env.USERPROFILE = account.home;
54571
- delete env.ANTHROPIC_API_KEY;
54572
- delete env.CLAUDE_CODE_OAUTH_TOKEN;
54573
- } else if (account.apiKey) {
54574
- env.ANTHROPIC_API_KEY = account.apiKey;
54575
- delete env.CLAUDE_CODE_OAUTH_TOKEN;
54576
- }
54577
- return env;
54583
+ return buildClaudeChildEnv(process.env, this.options.account);
54578
54584
  }
54579
54585
  getMcpServerPath() {
54580
54586
  const __filename2 = fileURLToPath3(import.meta.url);
@@ -79894,6 +79900,8 @@ async function main() {
79894
79900
  return false;
79895
79901
  if (opts.autoRestart === true)
79896
79902
  return true;
79903
+ if (!isHeadless && process.stdout.isTTY)
79904
+ return false;
79897
79905
  if (await configExists()) {
79898
79906
  try {
79899
79907
  const config = loadConfigWithMigration();
@@ -80005,6 +80013,15 @@ async function startWithoutDaemon() {
80005
80013
  console.error("");
80006
80014
  process.exit(1);
80007
80015
  }
80016
+ if (process.env.CLAUDE_CODE_SUBPROCESS_ENV_SCRUB === "1") {
80017
+ const hasSkipPermissionPlatform = config.platforms.some((p) => p.skipPermissions === true);
80018
+ if (hasSkipPermissionPlatform) {
80019
+ console.error(red(" ⚠️ CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1 is set but a platform has skipPermissions: true."));
80020
+ console.error(dim(" Claude CLI will force permissionMode: default and reject --dangerously-skip-permissions."));
80021
+ console.error(dim(" Either unset the env var or set skipPermissions: false on all platforms."));
80022
+ console.error("");
80023
+ }
80024
+ }
80008
80025
  let triggerShutdown = null;
80009
80026
  const updateState = loadUpdateState();
80010
80027
  const restoredSettings = updateState.justUpdated ? updateState.runtimeSettings : undefined;
@@ -53584,6 +53584,25 @@ function cleanupBrowserBridgeSockets() {
53584
53584
  log7.debug(`Browser bridge cleanup failed: ${err}`);
53585
53585
  }
53586
53586
  }
53587
+ function buildClaudeChildEnv(parentEnv, account) {
53588
+ const env = { ...parentEnv };
53589
+ if (env.MCP_CONNECTION_NONBLOCKING === undefined) {
53590
+ env.MCP_CONNECTION_NONBLOCKING = "true";
53591
+ }
53592
+ if (env.ENABLE_PROMPT_CACHING_1H === undefined) {
53593
+ env.ENABLE_PROMPT_CACHING_1H = "true";
53594
+ }
53595
+ if (account?.home) {
53596
+ env.HOME = account.home;
53597
+ env.USERPROFILE = account.home;
53598
+ delete env.ANTHROPIC_API_KEY;
53599
+ delete env.CLAUDE_CODE_OAUTH_TOKEN;
53600
+ } else if (account?.apiKey) {
53601
+ env.ANTHROPIC_API_KEY = account.apiKey;
53602
+ delete env.CLAUDE_CODE_OAUTH_TOKEN;
53603
+ }
53604
+ return env;
53605
+ }
53587
53606
  function isErrorResultEvent(event) {
53588
53607
  const ev = event;
53589
53608
  if (typeof ev.subtype === "string" && ev.subtype.startsWith("error"))
@@ -53885,20 +53904,7 @@ class ClaudeCli extends EventEmitter2 {
53885
53904
  return true;
53886
53905
  }
53887
53906
  buildChildEnv() {
53888
- const account = this.options.account;
53889
- if (!account)
53890
- return process.env;
53891
- const env = { ...process.env };
53892
- if (account.home) {
53893
- env.HOME = account.home;
53894
- env.USERPROFILE = account.home;
53895
- delete env.ANTHROPIC_API_KEY;
53896
- delete env.CLAUDE_CODE_OAUTH_TOKEN;
53897
- } else if (account.apiKey) {
53898
- env.ANTHROPIC_API_KEY = account.apiKey;
53899
- delete env.CLAUDE_CODE_OAUTH_TOKEN;
53900
- }
53901
- return env;
53907
+ return buildClaudeChildEnv(process.env, this.options.account);
53902
53908
  }
53903
53909
  getMcpServerPath() {
53904
53910
  const __filename2 = fileURLToPath3(import.meta.url);
@@ -107,6 +107,19 @@ Exactly one of `home` or `apiKey` should be set per account. Persisted sessions
107
107
  | `SESSION_TIMEOUT_MS` | Idle timeout in milliseconds | `1800000` (30 min) |
108
108
  | `NO_UPDATE_NOTIFIER` | Disable update checks | - |
109
109
  | `DEBUG` | Enable verbose logging | - |
110
+ | `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB` | Strip `ANTHROPIC_*` / `AWS_*_TOKEN` / `CLAUDE_CODE_OAUTH_TOKEN` / `GOOGLE_APPLICATION_CREDENTIALS` etc. from Bash, hook, and stdio-MCP subprocesses Claude spawns. Bot-specific vars like `PLATFORM_TOKEN` pass through. **Also forces permission mode to `default`** — `--dangerously-skip-permissions` will be rejected. Requires Claude CLI 2.1.83+. | - |
111
+
112
+ ### Forwarded to Claude CLI automatically
113
+
114
+ The bot sets two tuning flags on the Claude child process when they aren't
115
+ already present in the bot's environment:
116
+
117
+ | Variable | Effect | Requires |
118
+ |----------|--------|----------|
119
+ | `MCP_CONNECTION_NONBLOCKING=true` | Caps `--mcp-config` connects at 5s so a slow MCP server never delays startup | Claude CLI 2.1.89+ |
120
+ | `ENABLE_PROMPT_CACHING_1H=true` | Opts into 1-hour prompt cache TTL, cutting re-caching cost on long-lived threads | Claude CLI 2.1.108+ |
121
+
122
+ Export either with a different value in the bot's own env to disable.
110
123
 
111
124
  ## CLI Options
112
125
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-threads",
3
- "version": "1.7.1",
3
+ "version": "1.8.1",
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",