claude-threads 1.36.1 → 1.37.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
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.37.1] - 2026-09-18
11
+
12
+ Dependency maintenance only. No source changes, so nothing about how the bot
13
+ behaves is different — but `bun build --target node` bundles dependencies into
14
+ `dist/`, so the versions below are the ones users actually run and they only
15
+ reach anyone through a release.
16
+
17
+ ### Changed
18
+ - **Bundled dependencies updated**: hono 4.13.5 → 4.13.7 (#592), react 19.2.8 → 19.3.0 and zod 4.5.4 → 4.6.5 (#596). Development dependencies moved too, including knip 6.34.0 → 6.35.1 and react-devtools-core 7 → 8 (#593); those do not ship.
19
+ - **`ink-scroll-view` is pinned below 0.4.0** (#595). 0.4.0 imports `useBoxMetrics` from ink, an export that only exists in ink 7, so the build failed outright. Taking it would mean moving to ink 7, which requires Node 22 while this project's floor is Node 20. One optional scroll pane is not a reason to strand users on a supported LTS line, so Dependabot now ignores it until the Node floor moves for an independent reason.
20
+
21
+ ### Added
22
+ - **Per-platform `lifecycle` visibility** (#505, thanks @kaza). Session status posts — the idle warning, the timeout notice, the pause notice, the resume notice and the shutdown notice a deploy leaves in every open thread — are the bulk of what a quiet channel contains when the bot is used as an assistant rather than a task runner. `lifecycle: minimal` drops the idle warning, which predicts a timeout the next message would undo anyway; `hidden` drops the status posts entirely. Defaults to `full`, so nothing changes unless you set it. Editing a post the thread already has is never suppressed: it adds no post and no notification, and leaving a stale "session idle" up across a restart would read worse than the edit. An abnormal exit survives every level, because a session that died must not look like one that finished. At `hidden` there is no post for a 🔄 reaction to resume from, so the channel sticky tells the reader to send a message instead.
23
+ - **Per-platform `turnMarker`: the daemon says when a turn is over** (#528, thanks @kaza). An end-of-turn signal an integration can wait for, instead of guessing from "it has been quiet for eight seconds". On Slack it rides as invisible message metadata on the turn's last reply; on Mattermost, which has no metadata channel, as a 🏁 reaction. Default `off`, so nothing appears unless you ask for it. The payload carries a version (`v`), and `docs/CONFIGURATION.md` states what is frozen: `event_type` does not change within a 1.x line and `event_payload` only ever gains fields, `session` is stable across restarts and respawns, and `turn` restarts at 1 after a bot restart, so it is an ordering hint within one run rather than a unique key. Each marked turn costs one extra API call.
24
+ - **`CLAUDE_THREADS_HOME` moves the state root** (#557, thanks @Jadefalkner). Everything the bot persists — config, sessions, thread logs, worktree metadata, memory, uploads — resolves from one root instead of `homedir()` directly, so a second bot can run as the same user by pointing at a different directory. Unset, every path resolves exactly as before: this is a refactor at the default, and an existing install upgrades with its sessions intact.
25
+
26
+ ### Changed
27
+ - **⚠️ Two bots sharing one `$HOME` will no longer both start** (#557). A one-process-per-root lock now refuses the second, naming the pid that holds it and the fix. This is a deliberate break of a setup that appeared to work: the two instances were writing the same `sessions.json` and quietly losing each other's sessions. If you run more than one bot as the same user, give each its own `CLAUDE_THREADS_HOME` before upgrading. A lock left behind by a killed process is taken over automatically.
28
+
29
+ ### Fixed
30
+ - **Verifying the `bugReports` gate no longer files a public issue** (#586). `createGitHubIssue` called `execSync` directly, so the one test that proves the gate is load-bearing reached the real `gh` CLI the moment the gate was removed. Anyone following the repo's own red-green rule therefore filed a public issue titled "T" from their test suite, three times in one afternoon (#581, #582, #583). The command is now injectable, the same way `checkGitHubCli` already was, and the test passes a stub and asserts directly that no subprocess runs. A second case covers the other direction, so a stub that was never wired up cannot make the first one pass for the wrong reason.
31
+
10
32
  ## [1.36.1] - 2026-09-10
11
33
 
12
34
  ### Fixed
@@ -7,6 +7,7 @@
7
7
  #
8
8
  # For other exit codes:
9
9
  # - 0: Clean exit, don't restart
10
+ # - 3: Refused to start (another instance holds the state directory), don't restart
10
11
  # - 1+: Error, optional restart based on flags
11
12
  #
12
13
  # PLATFORM SUPPORT:
@@ -32,6 +33,9 @@ set -e
32
33
 
33
34
  # Exit code that signals "restart for update"
34
35
  RESTART_EXIT_CODE=42
36
+ # Exit code that signals "refused to start" (another instance holds the state
37
+ # directory): never restart, a retry would only collide again.
38
+ LOCKED_EXIT_CODE=3
35
39
 
36
40
  # Configuration
37
41
  MAX_RESTARTS=${CLAUDE_THREADS_MAX_RESTARTS:-0} # 0 = unlimited
@@ -92,6 +96,7 @@ while [[ $# -gt 0 ]]; do
92
96
  echo ""
93
97
  echo "Exit codes:"
94
98
  echo " 0 Clean exit, no restart"
99
+ echo " 3 Refused to start (another instance holds the state directory), no restart"
95
100
  echo " 42 Update restart signal (always restarts)"
96
101
  echo " other Error (restarts only with --restart-on-error)"
97
102
  exit 0
@@ -162,6 +167,9 @@ while true; do
162
167
  # Clean exit
163
168
  log "Clean exit, not restarting"
164
169
  should_restart=false
170
+ elif [ $exit_code -eq $LOCKED_EXIT_CODE ]; then
171
+ log "Another instance holds the state directory, not restarting"
172
+ should_restart=false
165
173
  elif [ "$RESTART_ON_ERROR" = true ]; then
166
174
  # Error exit with restart-on-error enabled
167
175
  log "Error exit, restarting due to --restart-on-error"