claude-threads 1.19.3 → 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,16 @@ 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
+
13
+ ## [1.19.4] - 2026-08-05
14
+
15
+ ### Changed
16
+ - **Dependency updates.** Production: `js-yaml` 4.3.0 → 4.3.1 (#457). Dev: `@types/react` 19.2.17 → 19.2.18, `knip` 6.29.0 → 6.31.0, `lint-staged` 17.2.0 → 17.3.0 (#456). The js-yaml bump additionally needed a manual `bun.lock` sync: the lockfile-sync workflow's `bun install` no-ops when the locked version still satisfies the manifest range (`^4.3.0` covers 4.3.0), so `bun.lock` — the lockfile CI actually installs from — had kept 4.3.0. Both manifests now pin `^4.3.1` and both lockfiles lock 4.3.1.
17
+
8
18
  ## [1.19.3] - 2026-08-04
9
19
 
10
20
  ### 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
@@ -48960,7 +48960,7 @@ function requireOmap() {
48960
48960
  function resolveYamlOmap(data) {
48961
48961
  if (data === null)
48962
48962
  return true;
48963
- const objectKeys = [];
48963
+ const objectKeys = {};
48964
48964
  const object = data;
48965
48965
  for (let index = 0, length = object.length;index < length; index += 1) {
48966
48966
  const pair = object[index];
@@ -48978,10 +48978,9 @@ function requireOmap() {
48978
48978
  }
48979
48979
  if (!pairHasKey)
48980
48980
  return false;
48981
- if (objectKeys.indexOf(pairKey) === -1)
48982
- objectKeys.push(pairKey);
48983
- else
48981
+ if (_hasOwnProperty.call(objectKeys, pairKey))
48984
48982
  return false;
48983
+ Object.defineProperty(objectKeys, pairKey, { value: true });
48985
48984
  }
48986
48985
  return true;
48987
48986
  }
@@ -55474,6 +55473,29 @@ init_logger();
55474
55473
  import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync, chmodSync as chmodSync2 } from "fs";
55475
55474
  import { homedir as homedir2 } from "os";
55476
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
55477
55499
  var log6 = createLogger("persist");
55478
55500
  var STORE_VERSION = 2;
55479
55501
  var DEFAULT_CONFIG_DIR = join3(homedir2(), ".config", "claude-threads");
@@ -55685,6 +55707,22 @@ class SessionStore {
55685
55707
  }
55686
55708
  return;
55687
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
+ }
55688
55726
  loadRaw() {
55689
55727
  if (!existsSync5(this.sessionsFile)) {
55690
55728
  return { version: STORE_VERSION, sessions: {} };
@@ -57500,7 +57538,9 @@ function generateHelpMessage(formatter) {
57500
57538
 
57501
57539
  ${formatter.formatBold("Reactions:")}
57502
57540
  ` + `${formatter.formatListItem(approvalReactions)}
57503
- ` + `${formatter.formatListItem(sessionReactions)}`;
57541
+ ` + `${formatter.formatListItem(sessionReactions)}
57542
+
57543
+ ` + formatSponsorFooter(formatter);
57504
57544
  }
57505
57545
 
57506
57546
  // src/changelog.ts
@@ -57635,7 +57675,9 @@ var handleHelp = async (ctx) => {
57635
57675
  var handleReleaseNotes = async (ctx) => {
57636
57676
  const notes = getReleaseNotes(VERSION);
57637
57677
  if (notes) {
57638
- 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);
57639
57681
  } else {
57640
57682
  await ctx.client.createPost(`\uD83D\uDCCB ${ctx.formatter.formatBold(`claude-threads v${VERSION}`)}
57641
57683
 
@@ -67147,6 +67189,13 @@ function appendFooter(lines, config) {
67147
67189
  lines.push(config.footer);
67148
67190
  }
67149
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
+ }
67150
67199
  async function buildStickyMessage(sessions, platformId, config, formatter, getThreadLink) {
67151
67200
  if (isShuttingDown) {
67152
67201
  const lines2 = [
@@ -67210,6 +67259,7 @@ async function buildStickyMessage(sessions, platformId, config, formatter, getTh
67210
67259
  lines2.push("");
67211
67260
  lines2.push(`✨ ${formatter.formatBold("What's new:")} ${whatsNew2}`);
67212
67261
  }
67262
+ appendMilestoneCelebration(lines2, formatter);
67213
67263
  appendFooter(lines2, config);
67214
67264
  lines2.push("");
67215
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/")}`);
@@ -67274,6 +67324,7 @@ async function buildStickyMessage(sessions, platformId, config, formatter, getTh
67274
67324
  lines.push("");
67275
67325
  lines.push(`✨ ${formatter.formatBold("What's new:")} ${whatsNew}`);
67276
67326
  }
67327
+ appendMilestoneCelebration(lines, formatter);
67277
67328
  appendFooter(lines, config);
67278
67329
  lines.push("");
67279
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/")}`);
@@ -70007,6 +70058,7 @@ async function startSession(options, username, displayName, replyToPostId, platf
70007
70058
  ctx.ops.registerPost(startPost.id, actualThreadId);
70008
70059
  }
70009
70060
  ctx.ops.emitSessionAdd(session);
70061
+ ctx.ops.recordSessionStarted();
70010
70062
  sessionLog6(session).info(`▶ Session started by @${username}`);
70011
70063
  fireMetadataSuggestions(session, options.prompt, ctx);
70012
70064
  keepAlive.sessionStarted();
@@ -71024,6 +71076,7 @@ class SessionManager extends EventEmitter4 {
71024
71076
  buildMessageContent: (t, p, uploadDir, f) => buildMessageContent(t, p, uploadDir, f, this.debug),
71025
71077
  persistSession: (s) => this.persistSession(s),
71026
71078
  unpersistSession: (sid) => this.unpersistSession(sid),
71079
+ recordSessionStarted: () => this.sessionStore.recordSessionStarted(),
71027
71080
  updateSessionHeader: (s) => this.updateSessionHeader(s),
71028
71081
  updateStickyMessage: () => this.updateStickyMessage(),
71029
71082
  handleEvent: (sid, e) => this.handleEvent(sid, e),
@@ -76860,6 +76913,18 @@ function Header({ version, workingDir, claudeVersion }) {
76860
76913
  /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
76861
76914
  dimColor: true,
76862
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"
76863
76928
  }, undefined, false, undefined, this)
76864
76929
  ]
76865
76930
  }, undefined, true, undefined, this),
@@ -82944,6 +83009,10 @@ async function startWithoutDaemon() {
82944
83009
  if (!isHeadless) {
82945
83010
  process.stdout.write("\x1B[2J\x1B[H");
82946
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
+ `);
82947
83016
  }
82948
83017
  };
82949
83018
  triggerShutdown = () => {
@@ -52774,7 +52774,7 @@ function requireOmap() {
52774
52774
  function resolveYamlOmap(data) {
52775
52775
  if (data === null)
52776
52776
  return true;
52777
- const objectKeys = [];
52777
+ const objectKeys = {};
52778
52778
  const object5 = data;
52779
52779
  for (let index = 0, length = object5.length;index < length; index += 1) {
52780
52780
  const pair = object5[index];
@@ -52792,10 +52792,9 @@ function requireOmap() {
52792
52792
  }
52793
52793
  if (!pairHasKey)
52794
52794
  return false;
52795
- if (objectKeys.indexOf(pairKey) === -1)
52796
- objectKeys.push(pairKey);
52797
- else
52795
+ if (_hasOwnProperty.call(objectKeys, pairKey))
52798
52796
  return false;
52797
+ Object.defineProperty(objectKeys, pairKey, { value: true });
52799
52798
  }
52800
52799
  return true;
52801
52800
  }
@@ -55271,6 +55270,13 @@ class KeepAliveManager {
55271
55270
  }
55272
55271
  var keepAlive = new KeepAliveManager;
55273
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
+
55274
55280
  // src/operations/sticky-message/handler.ts
55275
55281
  var log6 = createLogger("sticky");
55276
55282
  var botStartedAt = new Date;
@@ -56303,7 +56309,9 @@ function generateHelpMessage(formatter) {
56303
56309
 
56304
56310
  ${formatter.formatBold("Reactions:")}
56305
56311
  ` + `${formatter.formatListItem(approvalReactions)}
56306
- ` + `${formatter.formatListItem(sessionReactions)}`;
56312
+ ` + `${formatter.formatListItem(sessionReactions)}
56313
+
56314
+ ` + formatSponsorFooter(formatter);
56307
56315
  }
56308
56316
 
56309
56317
  // src/commands/executor.ts
@@ -56323,7 +56331,9 @@ var handleHelp = async (ctx) => {
56323
56331
  var handleReleaseNotes = async (ctx) => {
56324
56332
  const notes = getReleaseNotes(VERSION);
56325
56333
  if (notes) {
56326
- 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);
56327
56337
  } else {
56328
56338
  await ctx.client.createPost(`\uD83D\uDCCB ${ctx.formatter.formatBold(`claude-threads v${VERSION}`)}
56329
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.3",
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",
@@ -78,7 +79,7 @@
78
79
  "hono": "4.13.0",
79
80
  "ink": "^6.6.0",
80
81
  "ink-scroll-view": "^0.3.5",
81
- "js-yaml": "^4.3.0",
82
+ "js-yaml": "^4.3.1",
82
83
  "prompts": "^2.4.2",
83
84
  "react": "^19.2.3",
84
85
  "semver": "7.8.5",
@@ -98,7 +99,7 @@
98
99
  "@types/ws": "^8.18.0",
99
100
  "eslint": "^10.7.0",
100
101
  "husky": "^9.1.7",
101
- "knip": "6.29.0",
102
+ "knip": "6.31.0",
102
103
  "lint-staged": "^17.0.4",
103
104
  "prettier": "^3.9.5",
104
105
  "typescript": "^6.0.2",