Repository navigation
ThinkWatch Core 0.65.0
This release makes the gateway do much less work per request, keeps large requests from holding up other streams, fixes two ways stored request bodies and sessions could go missing, and stops forwarded bodies from having their keys reordered. On macOS, watching configuration files no longer wakes the process for every file change in the home folder.
Upgrade notes
- The control-plane protocol version (
CONTROL_API_VERSION) goes from 40 to 41. ThinkWatch Lite connects only to a core with the same protocol version: ThinkWatch Lite 2026.10.8 includes 0.64.1 (protocol 40) and does not connect to 0.65.0. A server used with it stays on 0.64.1 until the app is updated to a release that includes 0.65.0;sudo twcore upgrade --version 0.64.1 --restartswitches a server back. - The request store's schema is unchanged: upgrading from 0.64.1 keeps the request history. The first start on an existing store adds three indexes, which takes about a second for a store of 270,000 requests and grows the file by about 15%.
- The configuration format is unchanged.
- Changed in the protocol:
GET /sessions/{id}/transcripttakesTranscriptQuery(from_turn, optional: only the turns from that index on). A client written for protocol 40 that sendsnullis refused.Transcriptgainstotal_turnsandsettled_turns, the number of leading turns that will not change any more; asking fromsettled_turnsnext time returns only what is new.DryRunCandidategainsshare: the part of a load-balance group's requests the candidate gets with the current weights and factors. It is null outside load-balance groups and for members sitting the round out.
- Message codes are unchanged from 0.64.1.
Less work per request. With the default settings, a 2 MiB request from Claude Code used to cost about 45 ms of processing before its first byte went upstream, and an 8 MiB one about 180 ms; they now cost about 11 and 46 ms. The body is parsed once instead of three times, the checks for known client requests and for keys in the text search bytes directly, the content filter skips plain ASCII, and the scan that finds keys to redact no longer copies the body just to note what it found. Bodies of 1 MiB or more are analysed on a thread of their own, so answers streaming on the same worker no longer pause: the longest gap between relayed chunks while 8 MiB requests arrived fell from about half a second to under 40 ms.
Forwarded bodies keep the client's bytes. Taking out metadata.user_id (sent by Claude Code on every request) and applying a routing rule or alias that changes the model, output limit or thinking used to rewrite the whole body with every object's keys in alphabetical order, tool schemas and tool inputs included. Only the changed fields are now edited; everything else reaches the upstream as the client sent it.
Stored bodies and sessions.
- Body clean-up no longer deletes the current day. When one day held more than
body_max_bytesof bodies, the hourly clean-up emptied that day's folder, including the session being looked at. Older days are still removed whole; the current day loses its oldest requests until it fits. - A session older than the newest 500 opens again; it used to be reported as not found.
- The session list, the last-seen time of each client and the routing page's counts use indexes instead of reading every request: the session list went from about 180 ms to about 14 ms on a store of 270,000 requests.
- A session's conversation is built once and then extended with new requests, instead of rereading every stored body each time: 830 ms → 6 ms for a 300-turn session.
- Requests are recorded on a thread of their own with a queue separate from the app's live updates, so a slow app window can no longer cause requests to go unrecorded.
File watching on macOS. Watching a folder used to deliver every change anywhere below it, so watching the home folder for ~/.claude.json woke the process several times a second. Folders are now watched with kqueue and only their own entries count, with the files of interest watched directly for changes in place. Idle over 30 seconds, the watch plan ThinkWatch Lite uses went from 105 wake-ups to 4. Linux and Windows are unchanged.
Downloads
| Platform | Binary | Archive for server installation |
|---|---|---|
| Linux, x86_64 | twcore-x86_64-unknown-linux-gnu |
twcore-x86_64-unknown-linux-gnu.tar.gz |
| Linux, aarch64 | twcore-aarch64-unknown-linux-gnu |
twcore-aarch64-unknown-linux-gnu.tar.gz |
| macOS, Apple silicon | twcore-aarch64-apple-darwin |
— |
| Windows, x64 | twcore-x86_64-pc-windows-msvc.exe |
— |
| Windows, ARM64 | twcore-aarch64-pc-windows-msvc.exe |
— |
Each file is published with a .sha256 file beside it. A Linux archive contains twcore, the systemd unit twcore.service and LICENSE. ThinkWatch Lite includes its own copy of twcore; the files here are for running core separately, such as on a server.
Server installation
On Linux (x86_64 or aarch64), the install script sets up twcore as a systemd service. This installs 0.65.0:
curl -fsSL https://raw.githubusercontent.com/ThinkWatchProject/ThinkWatch-Core/main/scripts/install.sh | sudo sh -s -- --version 0.65.0An installation made with the script switches to 0.65.0 with:
sudo twcore upgrade --version 0.65.0 --restartConfiguration, the remote control port and connecting ThinkWatch Lite are described in docs/server.md.
Verifying a download
A .sha256 file holds the SHA-256 of the file followed by its name. With both files in the current directory, on Linux:
sha256sum -c twcore-x86_64-unknown-linux-gnu.tar.gz.sha256On macOS:
shasum -a 256 -c twcore-aarch64-apple-darwin.sha256On Windows, in PowerShell, the following prints True when the binary matches:
(Get-FileHash .\twcore-x86_64-pc-windows-msvc.exe).Hash -eq (Get-Content .\twcore-x86_64-pc-windows-msvc.exe.sha256).Split()[0]The install script and twcore upgrade check the SHA-256 themselves.
What's Changed
- CI: caches only on main, smoke on debug builds; releases save no cache, Windows builds each architecture on its own runner by @fylorn in #297
- Faster request path, history and macOS file watching; incremental transcripts and dry-run shares, protocol 41 by @fylorn in #298
- chore: v0.65.0 by @fylorn in #299
Full Changelog: v0.64.1...v0.65.0