claude-threads 1.11.0 → 1.13.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 +32 -0
- package/dist/index.js +10689 -10123
- package/dist/mcp/{permission-server.js → mcp-server.js} +823 -47
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,38 @@ 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
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.13.0] - 2026-05-05
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Claude can follow chat permalinks via the new `read_post` MCP tool.** When the user shares a Mattermost or Slack permalink in the thread, Claude can call `read_post(url, include_thread?, max_messages?)` to resolve it to the post body (and optional thread context) instead of asking the user to copy-paste. Auto-approved like `send_file`: the URL host check (Mattermost) or workspace `*.slack.com` + channel-id match (Slack) inside the handler are the real gate, since the bot's token is already scoped to what it can see. Defaults: 20 thread messages per call (hard cap 50), 2000-char body truncation per message, returned content marked as untrusted user input in the tool description (prompt-injection note). (#366)
|
|
14
|
+
- **Session collaborators surface as `Co-Authored-By:` trailers on commits Claude makes.** When the session owner runs `!invite @user`, that user's name + email is added to the system-prompt attribution block; the owner is the implicit author and is excluded, and the bot account plus AI assistants are excluded explicitly. Mid-session updates work without restart: `!invite` and `!kick` post a "Collaborators updated" notice in the thread, and Claude reads the current list from there on its next turn. Solo sessions still get a one-line standby instruction so a later `!invite` is honored without a respawn. All four Claude (re)spawn sites — `startSession`, `resumeSession`, `!cd`, worktree create/join — now compose the system prompt through one helper so the attribution rule cannot silently drop on respawn. Collaborators without a resolvable email are skipped silently rather than producing a malformed trailer. (#367)
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- **MCP package renamed `claude-threads-permissions` → `claude-threads-mcp`** to match the broader MCP-server scope (permission prompts, file uploads, post reads — no longer permission-only). Tool names exposed to Claude follow: `mcp__claude-threads-permissions__send_file` → `mcp__claude-threads-mcp__send_file`, etc. **Breaking for in-flight sessions across upgrade**: a Claude run that started under the old name will see the new tool names after restart, so any auto-approve rules tied to the old prefix need updating. The bot itself rewires automatically. (#366)
|
|
18
|
+
- **`src/mcp/permission-server.ts` renamed to `src/mcp/mcp-server.ts`.** Same content, accurate name. The npm `bin` entry `claude-threads-mcp` already pointed at the dist artifact, so no change for downstream installs apart from the bundled-file path inside the dist tarball. (#366)
|
|
19
|
+
|
|
20
|
+
### Internals
|
|
21
|
+
- **`PermissionApi` interface renamed to `McpPlatformApi`.** The interface now covers permission prompts, file uploads, and post reads, so the old name no longer fits. Includes file renames (`src/platform/permission-api*.ts` → `src/platform/mcp-platform-api*.ts`) and the matching impl files under `src/platform/{mattermost,slack}/`. (#366)
|
|
22
|
+
- **Shared permalink utilities at `src/platform/permalink-shared.ts`.** Caps (`DEFAULT_THREAD_LIMIT`, `MAX_THREAD_LIMIT`, `MAX_MESSAGE_BODY_CHARS`) and helpers (`clampThreadLimit`, `truncateBody`, `quoteBlock`) used by both Mattermost and Slack permalink modules — prevents drift on rendering rules. (#366)
|
|
23
|
+
- **Shared `fetch` test harness at `src/platform/test-helpers/fetch-harness.ts`.** Consolidates the recorder + responder pattern that lived in three platform-API test files. (#366)
|
|
24
|
+
- **`buildAppendSystemPrompt` helper in `src/commands/system-prompt-generator.ts`.** Single composition point for the four Claude (re)spawn sites; covers solo-standby and full-collaborator forms with shared exclusion guidance for owner / bot / AI. (#367)
|
|
25
|
+
- **`GitHubEmailsStore` (`src/persistence/github-emails-store.ts`).** Persists collaborator email lookups so the attribution block can be rebuilt after a restart without re-querying the platform. (#367)
|
|
26
|
+
|
|
27
|
+
## [1.12.0] - 2026-05-05
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
- **Claude can send files inline via the new `send_file` MCP tool.** Closes #360. When Claude produces an artifact during a session — Playwright screenshot, generated TTS MP3, plot, document — it can now post the file directly into the chat thread by calling `send_file(path, caption?)` instead of asking the user to fetch it from a URL. The tool runs inside the per-session `claude-threads-permissions` MCP child (no second MCP server needed), validates the path against the session working directory and per-session upload directory, then drives the Mattermost two-step `/api/v4/files` + `/api/v4/posts file_ids` flow or Slack's three-step v2 flow (`files.getUploadURLExternal` + presigned PUT + `files.completeUploadExternal`). Returns `{ ok: true, postId }` on success or `{ ok: false, reason }` on failure so Claude can retry or apologize to the user. Auto-approved by the permission gate (path validator is the real gate; making the user 👍 every screenshot would defeat the feature). Available in all three permission modes (`default`, `auto`, `bypass`) — bypass-mode now spawns the MCP server too so the tool stays available in the build-anything-on-demand setups that motivated the issue. Optional `outboundFiles: { enabled?, maxBytes? }` block on each platform config — defaults to enabled with a 100 MB cap. Reuses the per-thread upload directory and `MAX_UPLOAD_SIZE` ceiling already established by inbound attachments (PR #359). The system prompt now leads with "You are RIGHT NOW running inside a chat thread" and explicitly tells the model not to claim the tool is unavailable, after a manual test caught the model improvising an apology even though the tool was wired up. (#361)
|
|
31
|
+
|
|
32
|
+
### Security
|
|
33
|
+
- **Path validator hardens `send_file` against traversal and tricks.** New `src/mcp/path-validator.ts`. Rejects: non-absolute paths, anything that resolves (via `realpath`) outside the session working directory or per-session upload directory (path-prefix containment, so `/srv/sessions-evil` does not match `/srv/sessions`), non-regular files (FIFOs, sockets, devices, directories), SUID/SGID files, oversize files, zero-byte files (which Slack's upload endpoint rejects anyway), and dangerously wide allowed roots like `/`, `/home`, `/etc`, `/var`, `/tmp` (so a misconfigured `SESSION_WORKING_DIR` fails loudly instead of widening the trust boundary). The uploader receives the realpath-resolved path so it can't be re-pointed by a symlink between validation and read. Every reject branch has a unit test verified RED-GREEN against the live function. Follow-ups for TOCTOU between validate and read, per-session rate-limiting, and caption-length truncation tracked in #362-#365. (#361)
|
|
34
|
+
|
|
35
|
+
### Internals
|
|
36
|
+
- **`buildRestartCliOptions` helper.** Five places in the codebase construct a `ClaudeCli` (start, resume, `!cd`, `!permissions interactive`, `!worktree create`/`switch`). Each must thread `uploadDir` and `outboundFiles` through, or `send_file` silently breaks for that path. Two of the five (worktree paths) were skipped in the original PR and only caught by manual testing. Extracted to `src/claude/restart-options.ts` so all sites share one source of truth. (#361)
|
|
37
|
+
- **Env-var contract test pins names across the bot↔MCP-child boundary.** `OUTBOUND_ENV` constants in `src/mcp/outbound-env.ts` are referenced by both `buildPermissionArgs` (emit side) and `permission-server.ts` (consume side); a contract test asserts the names match and no bare string literal is used on either side. Caught a class of silent rename-drift bugs that would otherwise type-check and unit-test green while breaking the feature at runtime. (#361)
|
|
38
|
+
- **Portable chmod helper for tests.** Bun 1.3.x masks the SUID/SGID/sticky bits in `fs.chmod` and `chmodSync` (verified against 1.3.3); the SUID-rejection branch of the path validator was untestable without a workaround. New `src/test-utils/chmod-portable.ts` `setMode()` tries the runtime's chmod, verifies via `stat`, and falls back to `/bin/chmod` if the high bits didn't land. Works on Node (fast path) and Bun (shell fallback). (#361)
|
|
39
|
+
|
|
8
40
|
## [1.11.0] - 2026-05-03
|
|
9
41
|
|
|
10
42
|
### Changed
|