claude-threads 1.19.4 → 1.20.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,11 @@ 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.20.0] - 2026-08-06
9
+
10
+ ### Added
11
+ - **GitHub Sponsors support ♥** - The project now accepts voluntary support via [GitHub Sponsors](https://github.com/sponsors/axolotl-systems): a `.github/FUNDING.yml` enables the Sponsor button on the repository, the `funding` field in `package.json` surfaces the link in npm's post-install funding notice, and the README gained a "Support the Project" section aimed at both individual users and organizations. The sponsor link appears only at moments of delivered value or explicit pull: a dim note in the CLI startup header, a one-line farewell after interactive shutdown, a footer on the on-demand `!help` and `!release-notes` replies, and a 24-hour celebration line in the sticky message when an instance crosses a session-count milestone (#100, #250, #500, ...). The milestone counter persists in `sessions.json` (`stats` block, backward compatible). `release.yml` appends a sponsor footer to each release's generated notes, and the GitHub new-issue chooser links to the sponsor page. Sponsorship is branded under [Axolotl Systems](https://axolotl.systems), credited on the website, README, and docs.
12
+
8
13
  ## [1.19.4] - 2026-08-05
9
14
 
10
15
  ### Changed
package/README.md CHANGED
@@ -186,6 +186,16 @@ npm install -g claude-threads
186
186
 
187
187
  The bot checks npm for new versions on its own and offers the update in chat.
188
188
 
189
+ ## Support the Project
190
+
191
+ claude-threads is free and open source, and will stay that way. It is developed and maintained by [Axolotl Systems](https://axolotl.systems). If the bot is useful to you, consider [sponsoring on GitHub](https://github.com/sponsors/axolotl-systems) — even a small amount helps keep development going.
192
+
193
+ **Using claude-threads at work?** If your team relies on this bot day-to-day, ask whether your organization can sponsor it. Many organizations (especially in the public sector) have policies that encourage supporting the open source they depend on, and a single organizational sponsorship goes a long way. Need an invoice or a different payment route? [Open an issue](https://github.com/anneschuth/claude-threads/issues) or reach out.
194
+
189
195
  ## License
190
196
 
191
197
  Apache-2.0
198
+
199
+ ---
200
+
201
+ _claude-threads is an [Axolotl Systems](https://axolotl.systems) project._
package/dist/index.js CHANGED
@@ -55473,6 +55473,29 @@ init_logger();
55473
55473
  import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync, chmodSync as chmodSync2 } from "fs";
55474
55474
  import { homedir as homedir2 } from "os";
55475
55475
  import { join as join3 } from "path";
55476
+
55477
+ // src/sponsor.ts
55478
+ var SPONSOR_URL = "https://github.com/sponsors/axolotl-systems";
55479
+ var SESSION_MILESTONES = [100, 250, 500, 1000, 2500, 5000, 1e4];
55480
+ var MILESTONE_VISIBLE_MS = 24 * 60 * 60 * 1000;
55481
+ function milestoneReached(totalSessions) {
55482
+ return SESSION_MILESTONES.includes(totalSessions) ? totalSessions : null;
55483
+ }
55484
+ function milestoneStillFresh(reachedAtIso, nowMs) {
55485
+ const reachedAt = Date.parse(reachedAtIso);
55486
+ if (Number.isNaN(reachedAt))
55487
+ return false;
55488
+ const age = nowMs - reachedAt;
55489
+ return age >= 0 && age < MILESTONE_VISIBLE_MS;
55490
+ }
55491
+ function formatSponsorFooter(formatter) {
55492
+ return formatter.formatItalic(`♥ Support claude-threads: ${formatter.formatLink("github.com/sponsors/axolotl-systems", SPONSOR_URL)}`);
55493
+ }
55494
+ function formatMilestoneLine(formatter, milestone) {
55495
+ return `\uD83C\uDF89 ${formatter.formatBold(`Session #${milestone}`)} on this instance — claude-threads is free & open source ${formatter.formatLink("♥ sponsor", SPONSOR_URL)}`;
55496
+ }
55497
+
55498
+ // src/persistence/session-store.ts
55476
55499
  var log6 = createLogger("persist");
55477
55500
  var STORE_VERSION = 2;
55478
55501
  var DEFAULT_CONFIG_DIR = join3(homedir2(), ".config", "claude-threads");
@@ -55684,6 +55707,22 @@ class SessionStore {
55684
55707
  }
55685
55708
  return;
55686
55709
  }
55710
+ getStats() {
55711
+ const data = this.loadRaw();
55712
+ return data.stats ?? { totalSessionsStarted: 0 };
55713
+ }
55714
+ recordSessionStarted() {
55715
+ const data = this.loadRaw();
55716
+ const stats = data.stats ?? { totalSessionsStarted: 0 };
55717
+ stats.totalSessionsStarted = (stats.totalSessionsStarted ?? 0) + 1;
55718
+ const milestone = milestoneReached(stats.totalSessionsStarted);
55719
+ if (milestone) {
55720
+ stats.milestone = { n: milestone, reachedAt: new Date().toISOString() };
55721
+ }
55722
+ data.stats = stats;
55723
+ this.writeAtomic(data);
55724
+ return stats.totalSessionsStarted;
55725
+ }
55687
55726
  loadRaw() {
55688
55727
  if (!existsSync5(this.sessionsFile)) {
55689
55728
  return { version: STORE_VERSION, sessions: {} };
@@ -57499,7 +57538,9 @@ function generateHelpMessage(formatter) {
57499
57538
 
57500
57539
  ${formatter.formatBold("Reactions:")}
57501
57540
  ` + `${formatter.formatListItem(approvalReactions)}
57502
- ` + `${formatter.formatListItem(sessionReactions)}`;
57541
+ ` + `${formatter.formatListItem(sessionReactions)}
57542
+
57543
+ ` + formatSponsorFooter(formatter);
57503
57544
  }
57504
57545
 
57505
57546
  // src/changelog.ts
@@ -57634,7 +57675,9 @@ var handleHelp = async (ctx) => {
57634
57675
  var handleReleaseNotes = async (ctx) => {
57635
57676
  const notes = getReleaseNotes(VERSION);
57636
57677
  if (notes) {
57637
- await ctx.client.createPost(formatReleaseNotes(notes, ctx.formatter), ctx.threadId);
57678
+ await ctx.client.createPost(`${formatReleaseNotes(notes, ctx.formatter)}
57679
+
57680
+ ${formatSponsorFooter(ctx.formatter)}`, ctx.threadId);
57638
57681
  } else {
57639
57682
  await ctx.client.createPost(`\uD83D\uDCCB ${ctx.formatter.formatBold(`claude-threads v${VERSION}`)}
57640
57683
 
@@ -67146,6 +67189,13 @@ function appendFooter(lines, config) {
67146
67189
  lines.push(config.footer);
67147
67190
  }
67148
67191
  }
67192
+ function appendMilestoneCelebration(lines, formatter) {
67193
+ const milestone = sessionStore?.getStats().milestone;
67194
+ if (milestone && milestoneStillFresh(milestone.reachedAt, Date.now())) {
67195
+ lines.push("");
67196
+ lines.push(formatMilestoneLine(formatter, milestone.n));
67197
+ }
67198
+ }
67149
67199
  async function buildStickyMessage(sessions, platformId, config, formatter, getThreadLink) {
67150
67200
  if (isShuttingDown) {
67151
67201
  const lines2 = [
@@ -67209,6 +67259,7 @@ async function buildStickyMessage(sessions, platformId, config, formatter, getTh
67209
67259
  lines2.push("");
67210
67260
  lines2.push(`✨ ${formatter.formatBold("What's new:")} ${whatsNew2}`);
67211
67261
  }
67262
+ appendMilestoneCelebration(lines2, formatter);
67212
67263
  appendFooter(lines2, config);
67213
67264
  lines2.push("");
67214
67265
  lines2.push(`${formatter.formatItalic("Mention me to start a session")} · ${formatter.formatCode("bun install -g claude-threads")} · ${formatter.formatLink("claude-threads.run", "https://claude-threads.run/")}`);
@@ -67273,6 +67324,7 @@ async function buildStickyMessage(sessions, platformId, config, formatter, getTh
67273
67324
  lines.push("");
67274
67325
  lines.push(`✨ ${formatter.formatBold("What's new:")} ${whatsNew}`);
67275
67326
  }
67327
+ appendMilestoneCelebration(lines, formatter);
67276
67328
  appendFooter(lines, config);
67277
67329
  lines.push("");
67278
67330
  lines.push(`${formatter.formatItalic("Mention me to start a session")} · ${formatter.formatCode("bun install -g claude-threads")} · ${formatter.formatLink("claude-threads.run", "https://claude-threads.run/")}`);
@@ -70006,6 +70058,7 @@ async function startSession(options, username, displayName, replyToPostId, platf
70006
70058
  ctx.ops.registerPost(startPost.id, actualThreadId);
70007
70059
  }
70008
70060
  ctx.ops.emitSessionAdd(session);
70061
+ ctx.ops.recordSessionStarted();
70009
70062
  sessionLog6(session).info(`▶ Session started by @${username}`);
70010
70063
  fireMetadataSuggestions(session, options.prompt, ctx);
70011
70064
  keepAlive.sessionStarted();
@@ -71023,6 +71076,7 @@ class SessionManager extends EventEmitter4 {
71023
71076
  buildMessageContent: (t, p, uploadDir, f) => buildMessageContent(t, p, uploadDir, f, this.debug),
71024
71077
  persistSession: (s) => this.persistSession(s),
71025
71078
  unpersistSession: (sid) => this.unpersistSession(sid),
71079
+ recordSessionStarted: () => this.sessionStore.recordSessionStarted(),
71026
71080
  updateSessionHeader: (s) => this.updateSessionHeader(s),
71027
71081
  updateStickyMessage: () => this.updateStickyMessage(),
71028
71082
  handleEvent: (sid, e) => this.handleEvent(sid, e),
@@ -76859,6 +76913,18 @@ function Header({ version, workingDir, claudeVersion }) {
76859
76913
  /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
76860
76914
  dimColor: true,
76861
76915
  children: "Chat × Claude Code"
76916
+ }, undefined, false, undefined, this),
76917
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
76918
+ dimColor: true,
76919
+ children: " · "
76920
+ }, undefined, false, undefined, this),
76921
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
76922
+ color: "red",
76923
+ children: "♥"
76924
+ }, undefined, false, undefined, this),
76925
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
76926
+ dimColor: true,
76927
+ children: " github.com/sponsors/axolotl-systems"
76862
76928
  }, undefined, false, undefined, this)
76863
76929
  ]
76864
76930
  }, undefined, true, undefined, this),
@@ -82943,6 +83009,10 @@ async function startWithoutDaemon() {
82943
83009
  if (!isHeadless) {
82944
83010
  process.stdout.write("\x1B[2J\x1B[H");
82945
83011
  process.stdout.write("\x1B[?25h");
83012
+ process.stdout.write(`
83013
+ Thanks for using claude-threads! ${dim("♥ Support the project: https://github.com/sponsors/axolotl-systems")}
83014
+
83015
+ `);
82946
83016
  }
82947
83017
  };
82948
83018
  triggerShutdown = () => {
@@ -55270,6 +55270,13 @@ class KeepAliveManager {
55270
55270
  }
55271
55271
  var keepAlive = new KeepAliveManager;
55272
55272
 
55273
+ // src/sponsor.ts
55274
+ var SPONSOR_URL = "https://github.com/sponsors/axolotl-systems";
55275
+ var MILESTONE_VISIBLE_MS = 24 * 60 * 60 * 1000;
55276
+ function formatSponsorFooter(formatter) {
55277
+ return formatter.formatItalic(`♥ Support claude-threads: ${formatter.formatLink("github.com/sponsors/axolotl-systems", SPONSOR_URL)}`);
55278
+ }
55279
+
55273
55280
  // src/operations/sticky-message/handler.ts
55274
55281
  var log6 = createLogger("sticky");
55275
55282
  var botStartedAt = new Date;
@@ -56302,7 +56309,9 @@ function generateHelpMessage(formatter) {
56302
56309
 
56303
56310
  ${formatter.formatBold("Reactions:")}
56304
56311
  ` + `${formatter.formatListItem(approvalReactions)}
56305
- ` + `${formatter.formatListItem(sessionReactions)}`;
56312
+ ` + `${formatter.formatListItem(sessionReactions)}
56313
+
56314
+ ` + formatSponsorFooter(formatter);
56306
56315
  }
56307
56316
 
56308
56317
  // src/commands/executor.ts
@@ -56322,7 +56331,9 @@ var handleHelp = async (ctx) => {
56322
56331
  var handleReleaseNotes = async (ctx) => {
56323
56332
  const notes = getReleaseNotes(VERSION);
56324
56333
  if (notes) {
56325
- await ctx.client.createPost(formatReleaseNotes(notes, ctx.formatter), ctx.threadId);
56334
+ await ctx.client.createPost(`${formatReleaseNotes(notes, ctx.formatter)}
56335
+
56336
+ ${formatSponsorFooter(ctx.formatter)}`, ctx.threadId);
56326
56337
  } else {
56327
56338
  await ctx.client.createPost(`\uD83D\uDCCB ${ctx.formatter.formatBold(`claude-threads v${VERSION}`)}
56328
56339
 
@@ -262,3 +262,7 @@ Active sessions are saved to `~/.config/claude-threads/sessions.json` and automa
262
262
  ## Keep-Alive
263
263
 
264
264
  The bot prevents system sleep while sessions are active (uses `caffeinate` on macOS, `systemd-inhibit` on Linux). Disable with `--no-keep-alive` or `keepAlive: false` in config.
265
+
266
+ ---
267
+
268
+ _claude-threads is maintained by [Axolotl Systems](https://axolotl.systems). If it makes your team faster, consider [sponsoring the project](https://github.com/sponsors/axolotl-systems)._
package/docs/MCP-TOOLS.md CHANGED
@@ -105,3 +105,7 @@ Sends a direct message to a member of the bot's channel. Use it when the user as
105
105
  | `message` | string | Message body. The bot prepends an attribution prefix. |
106
106
 
107
107
  **Guardrail:** The recipient must be a current member of the bot channel. The first DM to each recipient in a session triggers a permission prompt in the bot channel; a ✅ allow-all promotes that specific recipient to no-prompt for the rest of the session. A hard limit of 3 DMs per recipient per session applies.
108
+
109
+ ---
110
+
111
+ _claude-threads is maintained by [Axolotl Systems](https://axolotl.systems). If it makes your team faster, consider [sponsoring the project](https://github.com/sponsors/axolotl-systems)._
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-threads",
3
- "version": "1.19.4",
3
+ "version": "1.20.0",
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",
@@ -47,7 +47,7 @@
47
47
  "collaboration",
48
48
  "bun"
49
49
  ],
50
- "author": "Anne Schuth",
50
+ "author": "Anne Schuth (Axolotl Systems)",
51
51
  "license": "Apache-2.0",
52
52
  "repository": {
53
53
  "type": "git",
@@ -57,6 +57,7 @@
57
57
  "url": "https://github.com/anneschuth/claude-threads/issues"
58
58
  },
59
59
  "homepage": "https://claude-threads.run",
60
+ "funding": "https://github.com/sponsors/axolotl-systems",
60
61
  "files": [
61
62
  "dist",
62
63
  "bin",