Skip to content

ThinkWatch Lite 2026.9.20

Choose a tag to compare

@github-actions github-actions released this 27 Sep 10:44
· 95 commits to main since this release
a526fc1

Upgrade notes: the bundled core stays at 0.52.1, so a remote server running 0.52.1 keeps working with this version and nothing on the server has to change.

Connecting and restoring clients:

  • A change is written only as it was shown. If a client rewrites its configuration while the confirmation dialog is open, nothing is written and the dialog shows the change worked out from the file as it is now, to confirm again. This applies to connecting and restoring a client, copying or removing an MCP server, and switching WSL to mirrored networking.
  • Restoring no longer deletes sections that connecting had created once something else was added to them: Claude Code's env in settings.json, the provider section of a new opencode configuration, and DeepSeek Harness's refs. Restoring DeepSeek Harness no longer fails with "refs is not a scalar", and its credentials file keeps its version when DeepSeek Harness has written its own entries into it.
  • A configuration file that contains an empty object written as { } no longer gets a stray comma when a setting is added to it. Claude Code and Claude Desktop rejected such a file.
  • In TOML files, a comment at the end of a changed line is kept, and an MCP server copied from a JSON client no longer gets empty strings where it had null.
  • When the record of an earlier connection next to a client's configuration is damaged or belongs to another client, connecting is refused, as restoring already was. Before, it recorded the gateway's address and key as the original values, and a later restore put them back.
  • Keys no longer appear in the change shown before writing: restoring showed the user's own key, and copying an MCP server showed the environment variables and headers of every server in the file. Messages about a configuration file that cannot be parsed no longer quote the line that failed, and a failed write no longer leaves a temporary copy with the gateway key next to the configuration.
  • Backups are readable by their owner only, and a configuration folder that is a symbolic link (for example into a dotfiles repository) is pointed out before writing.
  • Pointing Claude Desktop at a new address or key, after a key change or when switching to a remote core, updates its model list too.
  • On Windows, a running client is recognized by its program name, so a program such as TombRaider.exe is no longer taken for Aider.
  • Uninstalling keeps the data folder when a client could not be restored, since it holds that client's only full backup. It stops the core before deleting the data, and its confirmation also lists the clients inside WSL that will be restored.
  • The "Change path…" dialog no longer freezes the window while a network path that is offline takes its time to answer.
  • On a new installation, the data folder is created readable by its owner only, as intended. It holds config.yaml with the upstream keys, and on Windows its access rules are their only protection.

Figures:

  • When a statistic cannot be read, the Overview says it is unavailable and the Upstreams page shows "—" with a Retry button, instead of zeros or an empty chart.
  • Today's cost in the menu bar, and the costs on the Keys and Upstreams pages, keep measured, estimated and unpriced apart, as the Overview does. A cost is no longer shown as $0 when the requests could not be priced.
  • Very small amounts are shown as "<$0.0001" instead of "$0.0000". Numbers change unit after rounding, so they read "10k" and "1.0M" rather than "10.0k" and "1000k".
  • In live mode, requests whose price has not arrived yet make the total a lower bound, marked "≥", instead of counting as $0.
  • In a session, a turn is marked Unpriced only when a price would fix it. "Show unpriced only" on the Traffic page no longer lists failed requests and requests without usage.
  • Requests in progress when a remote connection dropped are corrected from the server's history instead of staying marked as failed.

Time ranges: "Today" in the menu bar starts at midnight on this computer, also when the core runs on a server in another time zone and on the days clocks change. A custom range such as "since 9/8" keeps its start day while the page stays open. Long custom ranges are drawn with daily or weekly points and always reach the present; ranges over about four months used to stop short of it.

Core and remote connections:

  • Switching to a remote core also stops a local core that was still starting or restarting. Before, it kept being started and held the gateway port.
  • A core in safe mode is shown as being in safe mode, not as running, and Restart works from there.
  • A remote connection that died without a sign, for example after the computer slept or the network changed, is noticed within 45 seconds, and a server that accepts the connection but never answers makes the connection test time out.
  • Quitting the app stops the local core instead of leaving it to notice a few seconds later.

Notifications:

  • A tool call blocked by the security rules, and something suspicious appearing in a client's configuration, are reported again each time they happen. Before, only the first one was ever reported, even after a restart. To keep a burst from flooding the screen, each shows at most once every five minutes (per upstream for blocked calls), and one notification then sums up the rest.
  • A notification that waits a minute before showing is dropped if the gateway went down meanwhile. The "N more" count no longer counts the same notice twice. The title of an upstream that keeps dropping out no longer grows longer with each request.
  • "Updated to …" follows the notification setting.
  • The notice list and the settings are saved in a way that survives the app being killed mid-save, and a setting this version does not recognize, such as one written by a newer version, resets only that setting.

Menu bar and tray: the color reflects the most severe quota window, not only the fullest one. On Windows and Linux, menu actions such as Check for Updates report their result in a notification, and messages from the core appear in the interface language. A click on a menu that has just been replaced no longer runs a different item. The menu bar no longer stops updating when the core stops answering.

MCP and the security scan:

  • The scan also covers MCP servers configured per project in ~/.claude.json, Claude Code settings that run commands without the model (statusLine, apiKeyHelper and similar), and Codex's notify. Helpers that print credentials are scanned but not listed, so their commands do not appear on screen.
  • Skills and folders created after the app started are watched as well, and so is opencode.jsonc.
  • A remote MCP server is no longer taken for a local one because its address contains "localhost". SKILL.md files with Windows line endings or a byte order mark are read correctly.
  • A file full of hidden characters no longer stalls the scan; findings are capped per file, with a note saying where the scan stopped. A special file, such as a link to /dev/zero, no longer blocks it.
  • Findings in a hook's command, including hidden characters, are shown on that hook's row.

Editing:

  • A config.yaml with Windows line endings no longer shows unsaved changes on opening, and is saved with its line endings as they were. "Show in config file" selects the right entry when a key and a route share a name.
  • Edit dialogs save against the configuration they were opened with. A change made elsewhere meanwhile is reported as a conflict instead of being overwritten. Switching several items on or off in quick succession no longer fails with "version mismatch".
  • Price fields and the dry run accept a decimal comma.
  • In the upstream dialog, the connection check result is cleared when the connection settings change.
  • In a key's model scope, model IDs typed by hand are shown and can be removed even when the model list is empty, and they are compared without regard to case, as the gateway does.
  • Saving a route applies its auxiliary request categories as they are after the edit: unticked or deleted conditions no longer keep them assigned to routing. max_tokens of 0 is refused instead of being dropped on save, and a copy of the fallback rule can be moved ahead of it.
  • A replayed request goes to the upstream it was priced for.
  • Several dialogs no longer act on stale state: the speed test waits for the new quote before it can start, deleting a price sheet from the upstream dialog also clears it from the form, checking for updates from About no longer overwrites settings changed meanwhile, dismissing one key-rotation banner no longer dismisses the others, and Z.ai sign-in accepts an existing upstream whose address ends in a slash.
  • A small payload cap in Retention no longer blocks saving that section.
  • Ctrl/⌘+B no longer toggles the sidebar while typing in a text field.
  • On Windows, choosing a connection at startup and opening the update window no longer risk freezing the app.

Speed: the update and connection windows load a fraction of the code they used to, and the configuration editor loads when it is opened. The change shown before writing a large ~/.claude.json appears at once. The Traffic page does less work per event, and the macOS menu bar updates its menu in place while it is open.

Downloads

Platform File
macOS, Apple silicon ThinkWatch-Lite-2026.9.20-arm64.dmg
Windows, x64 ThinkWatch-Lite-2026.9.20-x64-setup.exe
Windows, ARM64 ThinkWatch-Lite-2026.9.20-arm64-setup.exe
Linux, x86_64 ThinkWatch-Lite-2026.9.20-x86_64.AppImage
Linux, aarch64 ThinkWatch-Lite-2026.9.20-aarch64.AppImage

Each file is published with a .sha256 file beside it. latest.json is the manifest for in-app updates, and install.sh is the Linux install script.

On macOS, Homebrew installs the same disk image:

brew install --cask thinkwatchproject/tap/thinkwatch-lite

On Linux, the install script downloads the AppImage for the machine's architecture, checks its SHA-256 and installs it as ~/Applications/ThinkWatch-Lite.AppImage:

curl -fsSL https://github.com/ThinkWatchProject/ThinkWatch-Lite/releases/latest/download/install.sh | sh

Both commands install the latest release. First-launch steps for each platform, such as removing the quarantine attribute from a copy downloaded on macOS, are described in the README.

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 macOS:

shasum -a 256 -c ThinkWatch-Lite-2026.9.20-arm64.dmg.sha256

On Linux:

sha256sum -c ThinkWatch-Lite-2026.9.20-x86_64.AppImage.sha256

On Windows, in PowerShell, the following prints True when the installer matches:

(Get-FileHash .\ThinkWatch-Lite-2026.9.20-x64-setup.exe).Hash -eq (Get-Content .\ThinkWatch-Lite-2026.9.20-x64-setup.exe.sha256).Split()[0]

The Homebrew cask and the Linux install script check the SHA-256 themselves.

What's Changed

  • chore(deps): update sharp to 0.35.4 (libvips and libheif advisories) by @fylorn in #234
  • Fix the findings of a full code review: data safety, honest figures, local-time windows by @fylorn in #235
  • chore: 2026.9.20 by @fylorn in #236

Full Changelog: v2026.9.19...v2026.9.20