claude-threads 1.25.1 → 1.27.0

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,31 @@ 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.27.0] - 2026-08-20
9
+
10
+ ### Changed
11
+ - **Unit-test infrastructure hardening.** `handler.test.ts` no longer probes the real environment (git child processes, battery readouts are mocked, with a correct pre-mock value-snapshot restore — Bun module namespaces are live bindings, so restoring the namespace would restore the mocks; the same hazard is fixed in the plugin suite's `crossSpawn` restore). The per-test budget on all unit-test entry points is raised to 15s: the 5s default was routinely blown by event-loop contention when several processes compete for the machine, killing millisecond-fast tests at exactly the budget.
12
+
13
+ ### Added
14
+ - **Direct channel mode (DCM)** - Opt-in per platform via `directChannelMode: true`: the whole configured channel behaves as one session. Messages reach the bot without an `@mention`, and the bot replies with top-level channel posts instead of thread replies, so the channel reads like a plain conversation (#315). Internally the session is keyed by a synthetic thread id (`dcm:<platform id>`) that the platform clients resolve to a channel-root post, which keeps persistence, resume, reaction-based permission prompts, and `!commands` working unchanged. Messages posted inside any thread of the channel route to the same session; the thread-context prompt is skipped (there is no thread history behind the synthetic id). Default off — thread-per-session behavior is unchanged. The long form configures shared-channel behavior: `respondTo: all_messages | mention` (does the bot react to everything or only to @mentions; backed by the per-session quiet-mode flag so `!mentions` toggles it live). On Mattermost, a DM is just a private channel, so pointing a DCM platform entry at a DM channel id covers bot direct messages with no extra feature (#315); Slack is excluded — Socket Mode distributes envelopes across an app's connections, so a second entry on the same credentials could swallow the first one's events.
15
+ - **Platform-level `approvals` option** - `owner | all_users` controls who may answer tool-permission prompts and the other reaction gates (plan approvals, question answers, resume): the session participants (starter + `!invite`d), or everyone on the platform's `allowedUsers` list. Unset keeps the historical default per mode — `all_users` for thread sessions (unchanged upstream behavior), `owner` for direct channel mode — so the option is purely opt-in for existing setups; `approvals: owner` on a thread channel is an opt-in hardening.
16
+ - **DM auto-discovery (Mattermost)** - `directMessages: true` on a platform entry lets anyone on its `allowedUsers` start a bot DM "out of the cold": the first message spawns a derived direct-channel-mode instance for that DM channel (sticky hidden, scoped to the DM partner incl. tool-permission approvals), and persisted DM sessions are reconstructed after a restart. Mattermost only — Slack's Socket Mode envelope distribution makes per-DM connections unsafe there.
17
+
18
+ ### Fixed
19
+ - **Permission prompts show the full Bash command.** The approval prompt used to hard-truncate commands at 100 characters, so anything past the first pipe or `&&` was invisible at the exact moment the user was asked to approve it — the gate could only be rubber-stamped. The prompt now shows the command up to a generous 1500-character cap (a pathological command is still cut so it cannot blow up the prompt post). The 50-character display truncation in the streaming view is unchanged; only the permission prompt is affected.
20
+ - **Resuming a legacy persisted session no longer drops the owner from `sessionAllowedUsers`.** (#483) A session persisted before the collaboration list existed restored as an empty set, silently removing the owner from their own session — the one restore site without the defensive `[startedBy]` fallback its siblings already had.
21
+
22
+ ## [1.26.0] - 2026-08-20
23
+
24
+ ### Added
25
+ - **Routines — scheduled recurring work, Claude Tag-style.** `!routine every weekday at 9am, summarize the open review threads` creates a routine in natural language: one haiku pass parses the request into a structured schedule (presets hourly/daily/weekdays/weekly — hourly is the floor; timezone from the request or the bot host's zone, stated explicitly), the bot posts the parsed result, and **nothing is saved until someone reacts 👍**. Each run fires as a **bot-initiated session thread** in the channel — a completely normal session (platform permission mode, account-pool balancing, channel memory, end-of-session distillation) started as the routine's creator, with the creator re-authorized on every fire (a deauthorized creator disables the routine with a channel notice, mirroring Claude Tag).
26
+ - **Managing:** `!routines` lists numbered with schedule/creator/last-run; `!routines pause|resume|delete <n>` (owner-gated); `!routines run <n>` fires now without consuming the period's scheduled run (platform-allowed users only — a temporarily `!invite`d guest cannot spawn unattended sessions under the creator's identity).
27
+ - **Scheduling correctness:** due-ness is evaluated on the wall clock in the routine's own timezone (DST-safe, unit-tested across both switches), anchored to one fire per period; windows missed while the bot is down are skipped, not back-filled.
28
+ - **Guardrails:** per-platform cap (`limits.maxRoutines`, default 10); 3 consecutive failed runs auto-disable with a notice (manual `!routines run` outcomes never count toward — or reset — that streak); runs count against `MAX_SESSIONS` (retried within the window when at the limit); cost is stated in the confirmation and the listing (each run starts a full Claude session on your subscription). Per-platform `routines: false` disables the feature; storage at `~/.config/claude-threads/routines.yaml` (0600, per-platform scoped like memory; override `CLAUDE_THREADS_ROUTINES_PATH`).
29
+
30
+ ### Fixed
31
+ - **Ended sessions could come back from the dead.** The turn-end persistence write is deferred until the turn's message operations settle; when Claude exited immediately after its final turn (fast one-shot sessions), that deferred write could land *after* session teardown had soft-deleted the record — re-saving it as active. A later plain reply in the thread then resumed a session the bot had just ended. The deferred persist now no-ops once the session is unregistered. (Also the root cause of the flaky "should ignore side conversations" integration test.)
32
+
8
33
  ## [1.25.1] - 2026-08-20
9
34
 
10
35
  ### Fixed
package/README.md CHANGED
@@ -54,6 +54,7 @@
54
54
  - **A real chat citizen** - Nine MCP tools let Claude post files, follow permalinks, react, and DM, each behind its own guardrail (see [What Claude can do in your chat](#what-claude-can-do-in-your-chat))
55
55
  - **Git worktrees** - `!worktree feature/foo` isolates Claude's changes on a branch
56
56
  - **Memory** - Channels learn over time: `!remember` saves shared team notes every session sees, sessions distill durable facts when they end, and Claude's native auto-memory keeps per-repo project knowledge — all scoped per channel ([docs](https://github.com/anneschuth/claude-threads/blob/main/docs/CONFIGURATION.md#memory-memory-default-fully-enabled))
57
+ - **Routines** - `!routine every weekday at 9am, summarize open threads` schedules recurring work; runs post as new threads in the channel, confirmed before saving and managed with `!routines` ([docs](https://github.com/anneschuth/claude-threads/blob/main/docs/CONFIGURATION.md#routines-routines-default-enabled))
57
58
  - **Files both ways** - Drop any file into the chat for Claude to read, with full multimodal for images and PDFs; Claude posts screenshots, plots, or PDFs back with `send_file` (100 MB cap)
58
59
  - **Quiet mode and verbosity dials** - `!mentions on` makes a session respond only when mentioned; session headers and the channel sticky each have `full`/`minimal`/`hidden` modes
59
60
  - **Runs on macOS, Linux, and Windows** - Windows via Git Bash or WSL
@@ -121,6 +122,10 @@ Type `!help` in any session thread:
121
122
  | `!invite @user` | Invite a user to this session (added as `Co-Authored-By:` on commits) |
122
123
  | `!kick @user` | Remove an invited user |
123
124
  | `!github-email <email>` | Register your GitHub noreply email so `!invite` can attribute commits to you |
125
+ | `!remember <text>` | Save a note to the channel's shared memory |
126
+ | `!memory` | Show channel memory (`forget <n\|text>` removes entries) |
127
+ | `!routine <schedule, task>` | Schedule a recurring routine in natural language (confirmed with 👍) |
128
+ | `!routines` | List routines (`pause\|resume\|delete\|run <n>` to manage) |
124
129
  | `!update` | Show auto-update status (`!update now` / `!update defer`) |
125
130
  | `!bug <desc>` | Report a bug with context (creates a GitHub issue) |
126
131
  | `!approve` | Approve pending plan (alternative to 👍; also `!yes`) |