Releases: anneschuth/claude-threads
Releases · anneschuth/claude-threads
Release list
v1.17.3
Immutable
release. Only release title and notes can be modified.
Dependency maintenance release.
Dependencies
- Production:
@hono/node-server2.0.5 → 2.0.6,hono4.12.26 → 4.12.27,semver7.8.4 → 7.8.5. (#417) - Dev:
@types/node25 → 26,typescript-eslint8.61.1 → 8.62.1. (#416)
Changed
- Held
js-yamlon 4.x and added a dependabot ignore forjs-yaml >=5.0.0. Dependabot grouped ajs-yaml4.x → 5.x major into the production bump, but 5.x is ESM-only and dropped the CommonJSdefaultexport, breaking ourimport yaml from 'js-yaml'call sites withMissing 'default' export. The bump now stays on 4.x until the code migrates to named ESM imports. (#417) - CI:
actions/checkout6 → 7. (#413)
v1.17.2
Immutable
release. Only release title and notes can be modified.
Security
@hono/node-server2.0.4 → 2.0.5 to resolve GHSA-frvp-7c67-39w9: on Windows, prefix-mounted Serve Static middleware could be bypassed. Only affects Windows deployments using Serve Static. (#408)
Dependencies
v1.17.1
Immutable
release. Only release title and notes can be modified.
Fixed
- Quiet mode (
!mentions on) now survives an idle pause. A session with "respond only when mentioned" enabled would still resume on the first non-mention reply once it had been paused for inactivity, defeating the whole point of quiet mode. The active-session path honored the gate but the paused-session resume path did not check the persistedrespondOnlyWhenMentionedflag, so any plain message woke the session up. The resume path now applies the same gate: while quiet mode is on, a reply that doesn't @mention the bot no longer resumes a paused session. Commands (including!stop) still bypass the gate as before. (#410)
Security
hono4.12.23 → 4.12.25 to resolve CVE-2026-54290 (HIGH): the CORS middleware reflected anyOriginwith credentials whenorigindefaulted to*.- Pinned transitive
ws≥ 8.21.0 andshell-quote≥ 1.8.4 (both pulled in viaink) to clear GHSA-96hv-2xvq-fx4p (HIGH,wsmemory-exhaustion DoS) and GHSA-w7jw-789q-3m8p (CRITICAL,shell-quotenewline escaping). Added to the existingoverrides/resolutionsblocks; runtime behavior is unchanged.
v1.17.0
Immutable
release. Only release title and notes can be modified.
Added
!mentions quiet mode: respond only when @mentioned. A new per-session toggle for holding side conversations inside a bot thread without the bot replying to every message.
!mentions onmakes the bot ignore thread replies that don't explicitly @mention it;!mentions off(or a bare!mentionsto flip the current value) turns it back off.- Commands and pending worktree-branch-name prompts always bypass the gate, so
!mentions off(and answering a worktree prompt) works even while quiet mode is on. - When quiet mode is on, the session header shows a row noting it, so a returning user can see why the bot is staying quiet.
- The setting is owned by the session owner or a globally allowed user and persists across a bot restart.
- A global
respondOnlyWhenMentioned: trueinconfig.yaml(also offered in the onboarding wizard) seeds quiet mode on every new thread. Each session still keeps its own value and can override per-thread.
The default everywhere is unchanged (the bot treats every approved-user reply as input), so existing threads and configs are unaffected. (#402)
Dependencies
v1.16.3
Immutable
release. Only release title and notes can be modified.
Changed
- Fixed the flaky Mattermost integration suite (two independent root causes). These tests failed intermittently in CI, including on
main, so this was a pre-existing infra flake rather than a regression. (1) Channel contention: every pooled test bot posted into one shared channel, each maintaining its own sticky message; run together the suites flooded that channel and tripped the Mattermost threads write race (threads_pkey500s), surfacing as flaky task-list / context-prompt failures. Each suite now provisions a fresh channel viainitIsolatedTestContext, routes its bot there, and removes it inafterAll, which eliminated the 500 storms. (2) Leaked bot state across suites: the bot/session/sticky layer keeps module-level global state (stickyPostIds, the session registry, the pool cursor) and live WebSockets, and Bun runs all suite files in one process. A bot whose socket wasn't fully torn down kept processing events into the next suite (posting "Bot Offline" stickies, resuming stale sessions), which broke the sticky suite. CI now runs each suite file in its own process, so process exit clears all shared state by construction. A follow-up also corrected theshould show status indicatorsassertion. Test/CI-only; no runtime behavior changed. (#396, #398, #399)
Dependencies
- Production:
@hono/node-server2.0.3 → 2.0.4,hono4.12.21 → 4.12.23,semver7.8.0 → 7.8.1,ws8.20.1 → 8.21.0.commander14 → 15 was deliberately held back: v15 requires Node >= 22.12 (the runtime floor is Node 20) and changes the default behavior of paired--no-*options the CLI relies on. (#401) - Dev:
eslint10.4.0 → 10.4.1,lint-staged,typescript-eslint8.59.4 → 8.60.0. Lockfile-only. (#400)
Full Changelog: v1.16.2...v1.16.3
v1.16.2
Immutable
release. Only release title and notes can be modified.
Fixed
- Sturdier retry budget for the Mattermost post-save race. Under load Mattermost can return a burst of 500s on
POST /posts(the threads write race: duplicate key onthreads_pkey/app.post.save.app_error) when several posts stream to the same thread. The retry budget was 3 attempts with plain exponential backoff; a heavy burst exhausted it and dropped a post, which surfaced as flaky task-list / sticky / context-prompt behavior. The budget is now 6 attempts with a capped (2s), equal-jittered backoff. The cap keeps the total wait bounded so a long retry chain can't itself stall things, and the jitter decorrelates concurrent posts that would otherwise re-collide on the same row lock every round. (#394) - Two remaining memory leaks after #351. First,
MessageManager.dispose()cleared the post tracker but never calledthis.events.removeAllListeners()on the per-session emitter. Each session attaches a handful of listeners (question:complete,task:update,approval:complete, and the rest), and their closures kept session state reachable after the session ended, so the heap grew with every session.dispose()now removes the listeners before resetting. Second, React 19 enables user timing when bothconsole.timeStampandperformance.measureexist (the case on Node.js 25+), so every component re-render callsperformance.measure()with a structured-clone'd prop-diff detail that Node buffers indefinitely (~50-205 KB per entry, ~2 GB after a long uptime). Nothing in the bot reads those entries, so a guardedsetIntervalclears them every 60 seconds with.unref()so it never blocks a clean exit. (#394)
Full Changelog: v1.16.1...v1.16.2
v1.16.1
Immutable
release. Only release title and notes can be modified.
Security
- Fail-closed authorization on the user-driven paths that invoke Claude. A confirmed bypass let an unauthorized Slack user reach Claude. Authorization is now deny-by-default at every user-driven path that invokes Claude (
startSession,sendFollowUp,resumePausedSession, and resume-from-reaction), all routed through oneisAuthorizedForSessionhelper. The biggest gap was message-driven resume, which ran from persisted state with no identity check; it now verifies the username against the persisted session allowlist before resuming. (#388) - hono 4.12.18 → 4.12.21 picks up four upstream security fixes (GHSA-2gcr-mfcq-wcc3 mount-prefix routing, GHSA-xrhx-7g5j-rcj5 IPv6 IP-restriction bypass, GHSA-3hrh-pfw6-9m5x Set-Cookie injection, GHSA-f577-qrjj-4474 JWT scheme validation). The mount-prefix and Set-Cookie fixes are the relevant ones for the inbound webhook surface. (#386)
Changed
- Production deps bumped:
@hono/node-server2.0.2 → 2.0.3,express-rate-limit8.5.1 → 8.5.2. (#386) - Dev deps bumped:
@types/bun,@types/node,@types/react,eslint10.3.0 → 10.4.0,lint-staged17.0.4 → 17.0.5,typescript-eslint8.59.3 → 8.59.4. (#385)
Fixed
- Multiple pasted screenshots no longer silently vanish. Several clipboard images in one message arrive with the same name (
image.png); the second and later writes hitEEXISTand were dropped. Saves now dedupe within a message (image.png,image_1.png, ...), resolving the unique name before thewxwrite so symlink-race protection stays intact. (#387) - Inbound attachments are no longer capped at 100 MB. The cap is gone; an attachment of any reported size is downloaded and written to disk. (#387)
v1.16.0
Immutable
release. Only release title and notes can be modified.
What's Changed
- chore(deps): Bump fast-uri from 3.1.0 to 3.1.2 by @dependabot[bot] in #378
- chore(deps): Bump hono from 4.12.17 to 4.12.18 by @dependabot[bot] in #379
- chore(deps): Bump ip-address and express-rate-limit by @dependabot[bot] in #380
- Per-platform sessionHeader and stickyMessage visibility by @anneschuth in #384
- chore(deps-dev): Bump the dev-dependencies group with 3 updates by @dependabot[bot] in #381
- chore(deps): Bump the production-dependencies group with 5 updates by @dependabot[bot] in #382
Full Changelog: v1.15.2...v1.16.0
v1.15.2
Immutable
release. Only release title and notes can be modified.
What's Changed
- chore(deps): Bump the production-dependencies group with 4 updates by @dependabot[bot] in #377
- chore(deps-dev): Bump the dev-dependencies group with 2 updates by @dependabot[bot] in #376
Full Changelog: v1.15.1...v1.15.2
v1.15.1
Immutable
release. Only release title and notes can be modified.
Fixed
- Numeric tool args no longer fail at the MCP boundary when the runtime sends them as strings. Surfaced during live dogfooding of v1.15.0:
search_messageswithmax_results: 5returnedInvalid input: expected number, received stringfrom the MCP framework. Switched four schema fields toz.coerce.number().int()so either form parses. Affectsread_post.max_messages,list_thread.max_messages,read_channel_history.max_messages,search_messages.max_results. (#375)