claude-threads 1.28.0 → 1.29.3

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.
@@ -409,6 +409,95 @@ confirmation says so.
409
409
  bot-process-credentials caveat as memory distillation applies in OAuth
410
410
  account pools.
411
411
 
412
+ ### Watches (`watches`, default: enabled)
413
+
414
+ Event triggers, Claude Tag-style proactiveness: a watch fires when a
415
+ **matching message appears in the channel** — the bot starts a session **in
416
+ the triggering message's own thread** (as the watch's creator) and works the
417
+ task right where the event happened. Other thread participants reach the
418
+ session through the normal message-approval flow.
419
+
420
+ ```yaml
421
+ platforms:
422
+ - id: mattermost-main
423
+ type: mattermost
424
+ # ... credentials ...
425
+ watches: true # default; `false` disables evaluation + commands
426
+
427
+ limits:
428
+ maxWatches: 10 # per-platform cap (default 10)
429
+ watchCooldownMinutes: 5 # min minutes between fires of one watch (default 5)
430
+ watchDailyCap: 20 # max fires per watch per day (default 20)
431
+ ```
432
+
433
+ **Creating** (natural language, confirmed before saving):
434
+
435
+ ```
436
+ !watch when someone reports a production incident, triage it and post a checklist
437
+ ```
438
+
439
+ A haiku pass splits the request into a matching **condition**, a **task**,
440
+ and a set of lowercase **prefilter keywords** (with synonyms and — for
441
+ non-English requests — terms in both languages). The confirmation card shows
442
+ all three, and **nothing is saved until someone reacts 👍**.
443
+
444
+ **Matching is two-stage** to keep chatty channels free:
445
+
446
+ 1. Every channel message the bot would otherwise ignore is screened against
447
+ the keywords locally (zero cost). No keyword hit → nothing happens.
448
+ 2. A keyword hit gets **one haiku call** that semantically confirms the
449
+ message against the condition ("a link to last year's incident postmortem"
450
+ does not fire an incident watch). A keyword hit alone never fires;
451
+ a failed or ambiguous confirmation never fires (fail-closed).
452
+
453
+ **Managing:**
454
+
455
+ - `!watches` — numbered list with condition, creator, and last-fire status
456
+ - `!watches pause|resume|delete <n>` — owner-gated
457
+ - (No manual `run` — watches are event-driven; use `!routines run` for
458
+ on-demand work.)
459
+
460
+ **Semantics & guardrails:**
461
+
462
+ - Fires run **as their creator** and are re-authorized on every fire — a
463
+ creator who loses platform authorization disables the watch (with a
464
+ channel notice).
465
+ - Per-watch cooldown (default 5 min) and daily cap (default 20 fires/day);
466
+ at most one watch fires per message; fires count against `MAX_SESSIONS`.
467
+ - 3 consecutive failed fires auto-disable the watch with a channel notice;
468
+ `!watches resume <n>` re-arms it.
469
+ - Messages inside active or paused session threads never trigger watches
470
+ (loop prevention), and the bot's own posts are filtered before evaluation.
471
+ - Platform note: on **Mattermost**, messages from *other* bots (CI alerts,
472
+ webhook integrations) can trigger watches — useful for "watch the CI bot".
473
+ On **Slack**, the client filters all bot events, so only human messages
474
+ trigger.
475
+ - The fired session auto-includes the triggering thread's recent messages as
476
+ context (it is the event being responded to) — no interactive context
477
+ prompt to stall on.
478
+ - **Each fire starts a full Claude session on your subscription** — the
479
+ confirmation and `!watches` listing both say so.
480
+ - Watches are scoped per platform instance (same privacy boundary as memory)
481
+ and stored at `~/.config/claude-threads/watches.yaml` (0600; override with
482
+ `CLAUDE_THREADS_WATCHES_PATH`).
483
+ - The parse and each match confirmation use one haiku `claude -p` call — the
484
+ same bot-process-credentials caveat as memory distillation applies in
485
+ OAuth account pools.
486
+ - Watches are not available in **direct channel mode** — a DCM channel routes
487
+ every message to the one channel session, so there is no "otherwise
488
+ ignored" traffic to evaluate; `!watch` refuses with an explanation.
489
+
490
+ **Security note — who can trigger a fire:** the *creator* must be authorized,
491
+ but the *triggering message* can come from **any channel member** (that is the
492
+ point: incident reporters and CI bots are usually not on `allowedUsers`). The
493
+ channel membership is the trust boundary. The triggering content is framed as
494
+ data — the confirm prompt classifies it without following instructions inside
495
+ it, and the fired session's prompt marks the thread as context, not
496
+ instructions — but framing is a mitigation, not authorization. Treat a watch
497
+ in a channel with untrusted members accordingly, and be especially deliberate
498
+ about combining watches with `skipPermissions: true`, which lets the fired
499
+ session act without human tool approval.
500
+
412
501
  ## Claude Accounts (optional, multi-account mode)
413
502
 
414
503
  By default every session spawns `claude` with the bot's own `process.env`, so they all share one subscription's token budget. Add a `claudeAccounts` block to spread load across multiple accounts. Omit the block entirely to stay in single-account mode (unchanged behavior).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-threads",
3
- "version": "1.28.0",
3
+ "version": "1.29.3",
4
4
  "description": "Run Claude Code from Slack or Mattermost. Sessions stream live into threads where your whole team can watch and steer.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",