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 +10 -0
- package/README.md +10 -0
- package/dist/index.js +75 -6
- package/dist/mcp/mcp-server.js +16 -6
- package/docs/CONFIGURATION.md +4 -0
- package/docs/MCP-TOOLS.md +4 -0
- package/package.json +5 -4
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 (
|
|
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)
|
|
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 = () => {
|
package/dist/mcp/mcp-server.js
CHANGED
|
@@ -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 (
|
|
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)
|
|
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
|
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
102
|
+
"knip": "6.31.0",
|
|
102
103
|
"lint-staged": "^17.0.4",
|
|
103
104
|
"prettier": "^3.9.5",
|
|
104
105
|
"typescript": "^6.0.2",
|