claude-threads 1.19.4 → 1.20.1
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 +31 -0
- package/dist/index.js +72 -2
- package/dist/mcp/mcp-server.js +13 -2
- package/docs/CONFIGURATION.md +4 -0
- package/docs/MCP-TOOLS.md +4 -0
- package/package.json +3 -2
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.1] - 2026-08-06
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **"How it compares" section on the website and README** - A short, respectful comparison with the other ways to drive a coding agent from chat: Anthropic's own Claude Code in Slack / Claude Tag, OpenAI's Codex in Slack, Cursor in Slack, Cognition's Devin, and community Slack bots. The framing is a single axis — where the session runs (vendor cloud vs. your machine) — with claude-threads positioned as the local, self-hosted option that also speaks Mattermost. A closing note names the strongest differentiators beyond that: in-thread permission approvals, multiplayer sessions, the multi-account pool, and no GitHub assumption. The website's "Why I built this" note about Anthropic's integration was updated to match (it is no longer Enterprise-gated: Pro/Max plans have Claude Code in Slack, Team/Enterprise have Claude Tag).
|
|
12
|
+
|
|
13
|
+
## [1.20.0] - 2026-08-06
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- **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.
|
|
17
|
+
|
|
8
18
|
## [1.19.4] - 2026-08-05
|
|
9
19
|
|
|
10
20
|
### Changed
|
package/README.md
CHANGED
|
@@ -170,6 +170,27 @@ Restrict who can use the bot during setup, or reconfigure later with `claude-thr
|
|
|
170
170
|
|
|
171
171
|
Who may do what (start sessions, react to permission prompts, approve guest messages) is written down in the [authorization model](https://github.com/anneschuth/claude-threads/blob/main/SECURITY.md).
|
|
172
172
|
|
|
173
|
+
## How it compares
|
|
174
|
+
|
|
175
|
+
Driving a coding agent from chat is a busy space: Anthropic, OpenAI, Cursor, and Cognition each ship their own integration, and other open-source projects exist too — several of them excellent. The main difference is where the session actually runs.
|
|
176
|
+
|
|
177
|
+
| Product | Sessions run on | Chat platforms | Account |
|
|
178
|
+
| :----------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------- | :---------------------------------------------- | :-------------------------------------------- |
|
|
179
|
+
| **claude-threads** (open source, Apache-2.0) | Your machine — local checkout, your MCP servers and plugins | Slack + Mattermost, multiple workspaces at once | Any Claude subscription or API key |
|
|
180
|
+
| [Claude Code in Slack](https://code.claude.com/docs/en/slack) / [Claude Tag](https://claude.com/docs/claude-tag/overview) (Anthropic) | Anthropic's cloud, against GitHub repos | Slack | Claude Pro/Max; Claude Tag on Team/Enterprise |
|
|
181
|
+
| [Codex in Slack](https://slack.com/marketplace/A09F5C369E3-openai-codex) (OpenAI) | OpenAI's Codex cloud | Slack | ChatGPT plan |
|
|
182
|
+
| [Cursor in Slack](https://cursor.com/docs/integrations/slack) | Cursor's cloud agents | Slack | Cursor plan |
|
|
183
|
+
| [Devin](https://devin.ai/) (Cognition) | Cognition's cloud | Slack (also Linear and Jira tickets) | Devin plan |
|
|
184
|
+
| Community bots such as [claude-code-slack-bot](https://github.com/mpociot/claude-code-slack-bot) | Your machine | Slack | Claude subscription or API key |
|
|
185
|
+
|
|
186
|
+
The cloud products share a working style: you delegate from a thread, the work runs in a vendor-hosted sandbox, and progress updates and a pull request come back — Claude Tag additionally stays in the conversation as a shared teammate the whole channel can talk to. If your repositories live on GitHub and you want nothing to host, they are a good choice; Anthropic's own integration in particular runs the same Claude Code this bot does.
|
|
187
|
+
|
|
188
|
+
claude-threads makes the opposite choice: the whole session stays in the thread and on your hardware. Output streams live, permission prompts land as emoji reactions, invited teammates type into the same session, and Claude works against a local checkout with whatever MCP servers and plugins you already configured. That fit matters when chat is self-hosted Mattermost, when code cannot leave the building, or when you want a session in chat to behave exactly like the one at your desk. The trade-off: you run the bot yourself, on a machine that has the repository.
|
|
189
|
+
|
|
190
|
+
A few more things set it apart. The full Claude Code permission model lives in the thread: every tool use can prompt for 👍/✅/👎 approval, with three modes switchable mid-session. Sessions are multiplayer: `!invite` teammates while Claude works, messages from uninvited users are gated behind approval, and commits credit everyone involved as co-author. An optional [account pool](https://github.com/anneschuth/claude-threads/blob/main/docs/CONFIGURATION.md#claude-accounts-optional-multi-account-mode) routes each new session to the Claude subscription with the most headroom and cools down rate-limited ones. And nothing assumes GitHub — the session works against any local checkout, whatever its host.
|
|
191
|
+
|
|
192
|
+
This table is current as of August 2026. All of these products move quickly — if it has gone stale, [open an issue](https://github.com/anneschuth/claude-threads/issues).
|
|
193
|
+
|
|
173
194
|
## Documentation
|
|
174
195
|
|
|
175
196
|
- **[Setup Guide](https://github.com/anneschuth/claude-threads/blob/main/SETUP_GUIDE.md)** - Creating the bot account on Mattermost or Slack, step by step
|
|
@@ -186,6 +207,16 @@ npm install -g claude-threads
|
|
|
186
207
|
|
|
187
208
|
The bot checks npm for new versions on its own and offers the update in chat.
|
|
188
209
|
|
|
210
|
+
## Support the Project
|
|
211
|
+
|
|
212
|
+
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.
|
|
213
|
+
|
|
214
|
+
**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.
|
|
215
|
+
|
|
189
216
|
## License
|
|
190
217
|
|
|
191
218
|
Apache-2.0
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
_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)
|
|
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 = () => {
|
package/dist/mcp/mcp-server.js
CHANGED
|
@@ -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)
|
|
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
|
|
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.1",
|
|
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",
|