Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/components/LiteDownload.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
// takes one click instead of home → Lite page → install section → button.
//
// The download URLs and sizes come from the latest release's asset list at
// build time (the file names carry the version). Without script, or for a machine there is
// build time (the file names carry the version). Files are matched by the end of
// their names (ThinkWatch-Lite-<version>-windows-x64-setup.exe ends in
// -x64-setup.exe), which releases from before the <os>-<arch> names share. The
// Windows button stays on the installer; the portable zip is on the Lite page. Without script, or for a machine there is
// no build for (a phone, an Intel Mac), the button leads to the install
// section instead, which lists every option. So does a Linux machine while the
// latest release has no AppImage for it.
Expand Down
17 changes: 16 additions & 1 deletion src/components/pages/LitePage.astro
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ const latestPage = `${releases}/latest`;
// The installers of the latest release. The file names carry the version, so
// they come from the release's asset list, looked up at build time, along with
// their sizes; without it, the buttons lead to the latest release page instead
// and no size is shown.
// and no size is shown. Names are ThinkWatch-Lite-<version>-<os>-<arch>…
// (darwin, windows, linux); the installers, disk image and AppImages are matched
// by the end of the name, which releases before the rename share.
const liteRelease = await getLatestLiteRelease();
const assetName = (suffix: string) => Object.keys(liteRelease?.assets ?? {}).find((n) => n.endsWith(suffix));
const assetUrl = (suffix: string) => {
Expand All @@ -54,6 +56,10 @@ const win = Object.fromEntries(
},
]),
) as Record<(typeof winArchs)[number], { url: string; sha: string | null; size: string | null }>;
/** The Windows portable zips, linked from one line under the installer; the release page until a release has them */
const winZip = Object.fromEntries(
winArchs.map((arch) => [arch, assetUrl(`-windows-${arch}-portable.zip`) ?? latestPage]),
) as Record<(typeof winArchs)[number], string>;
const linuxArchs = ["x86_64", "aarch64"] as const;
const linux = Object.fromEntries(
linuxArchs.map((arch) => [
Expand Down Expand Up @@ -528,6 +534,14 @@ const archLabel = { x64: "x64", arm64: "ARM64" } as const;
)}
</p>
)}
{/* The portable zips as one line under the installer, this machine's architecture first */}
{winArchs.map((arch) => (
<p class="install-meta" data-winzip-arch={arch} hidden={arch !== "x64"}>
{c.install.windows.portable}<span>{[arch, ...winArchs.filter((a) => a !== arch)].map((a, i) => (
<Fragment>{i > 0 && " · "}<a href={winZip[a]}>{archLabel[a]}</a></Fragment>
))}</span>
</p>
))}
</div>
<p class="install-note">{c.install.windows.note}</p>
</div>
Expand Down Expand Up @@ -786,6 +800,7 @@ const archLabel = { x64: "x64", arm64: "ARM64" } as const;
};
const apply = (arm) => {
show("win", arm && windows ? "arm64" : "x64");
show("winzip", arm && windows ? "arm64" : "x64");
show("linux", arm && linux ? "aarch64" : "x86_64");
};
const guess = linux && /aarch64|arm64/.test(s);
Expand Down
28 changes: 22 additions & 6 deletions src/content/docs-lite/en/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The cask lives in [thinkwatchproject/tap](https://github.com/ThinkWatchProject/h

## macOS: disk image

Download `ThinkWatch-Lite-<version>-arm64.dmg` from the [latest release](https://github.com/ThinkWatchProject/ThinkWatch-Lite/releases/latest), check it against the sha256 published beside it, open it, and drag ThinkWatch Lite into Applications.
Download `ThinkWatch-Lite-<version>-darwin-arm64.dmg` from the [latest release](https://github.com/ThinkWatchProject/ThinkWatch-Lite/releases/latest), check it against the sha256 published beside it, open it, and drag ThinkWatch Lite into Applications.

The app is **not signed by a registered Apple developer**, so macOS quarantines a downloaded copy and refuses to open it until the attribute is removed:

Expand All @@ -22,12 +22,12 @@ xattr -dr com.apple.quarantine "/Applications/ThinkWatch Lite.app"

Without a terminal, the same takes one click after the first refused launch: System Settings › Privacy & Security › Open Anyway.

## Windows
## Windows: installer

Download the installer for the machine's architecture from the [latest release](https://github.com/ThinkWatchProject/ThinkWatch-Lite/releases/latest): `ThinkWatch-Lite-<version>-x64-setup.exe` for most PCs, or `ThinkWatch-Lite-<version>-arm64-setup.exe` for a PC with an ARM processor. The [Lite page](/lite#install) links to both installers of the latest release. Check the download against the sha256 published beside it:
Download the installer for the machine's architecture from the [latest release](https://github.com/ThinkWatchProject/ThinkWatch-Lite/releases/latest): `ThinkWatch-Lite-<version>-windows-x64-setup.exe` for most PCs, or `ThinkWatch-Lite-<version>-windows-arm64-setup.exe` for a PC with an ARM processor. The [Lite page](/lite#install) links to both installers of the latest release. Check the download against the sha256 published beside it:

```powershell
Get-FileHash .\ThinkWatch-Lite-<version>-x64-setup.exe
Get-FileHash .\ThinkWatch-Lite-<version>-windows-x64-setup.exe
```

The installer sets the app up for all users in Program Files, so Windows asks for administrator permission. It requires Windows 10 21H2 or later; WebView2, which Windows 11 already includes, is downloaded during installation if it is missing.
Expand All @@ -36,6 +36,20 @@ The installer is **not code-signed**, and no certificate will be bought. Running

Once installed, the app's icon sits in the notification area: a left click opens the main window, a right click opens the menu. Data is kept in `%APPDATA%\ThinkWatch`.

Uninstalling through the system first closes ThinkWatch Lite, restores the connected clients and removes the `thinkwatch://` link, launch-at-login entry and notification registration that point to it. With "Also delete data (configuration, API keys, request history)" ticked it deletes `%APPDATA%\ThinkWatch` as well, except when a client could not be restored, in which case the data directory, with that client's backup, is kept. The uninstaller runs as an administrator: when a standard account uninstalls with an administrator's password, it restores the administrator's clients and deletes the administrator's data instead, so use Settings › Full uninstall first in that case.

## Windows: portable

The portable copy runs from the folder it is extracted to, with no installation and no administrator rights. Download `ThinkWatch-Lite-<version>-windows-x64-portable.zip` (or `ThinkWatch-Lite-<version>-windows-arm64-portable.zip` for a PC with an ARM processor) from the [latest release](https://github.com/ThinkWatchProject/ThinkWatch-Lite/releases/latest), check it against the sha256 published beside it, extract it to any folder the user can write to and run `ThinkWatch Lite.exe`. The zip holds two files: `ThinkWatch Lite.exe` and the gateway, `twcore.exe`.

Configuration, keys and request history stay in the `data\` folder next to the program, apart from the installed copy's `%APPDATA%\ThinkWatch`, so the two keep separate settings. In a folder that cannot be written to, the app says so and quits.

The portable copy is not code-signed either, and SmartScreen is handled the same way as for the installer. It does not bring WebView2, which Windows 11 already includes; when it is missing, the app says so and can open Microsoft's download page.

Only one of the installed and portable copies runs at a time. Opening one while the other is running offers to stop the running one: it exits once the requests in flight have finished, and the one just opened starts. `thinkwatch://` links and launch at login always point to the copy that is running, and the launch-at-login switch is shared by both.

To remove it, use Settings › Full uninstall first, which restores the connected clients and removes launch at login and the other registry entries, then delete the whole folder.

## Linux

```bash
Expand All @@ -44,7 +58,7 @@ curl -fsSL https://github.com/ThinkWatchProject/ThinkWatch-Lite/releases/latest/

The script downloads the AppImage for the machine's architecture, checks it against the sha256 published beside it, installs it as `~/Applications/ThinkWatch-Lite.AppImage` and starts it. Running it again installs the latest version over the old one.

To install by hand, download `ThinkWatch-Lite-<version>-x86_64.AppImage` or `ThinkWatch-Lite-<version>-aarch64.AppImage` from the [latest release](https://github.com/ThinkWatchProject/ThinkWatch-Lite/releases/latest), check it with `sha256sum -c`, allow it to run (`chmod +x`, or Properties › "Allow executing file as program" in the file manager) and open it. Keep it in a folder the user can write to, such as `~/Applications`, so that it can update itself. The first launch adds ThinkWatch Lite to the application menu, together with its icon and the `thinkwatch://` link handler. Only the AppImage is published; there are no deb, rpm, Flatpak or Snap packages.
To install by hand, download `ThinkWatch-Lite-<version>-linux-x86_64.AppImage` or `ThinkWatch-Lite-<version>-linux-aarch64.AppImage` from the [latest release](https://github.com/ThinkWatchProject/ThinkWatch-Lite/releases/latest), check it with `sha256sum -c`, allow it to run (`chmod +x`, or Properties › "Allow executing file as program" in the file manager) and open it. Keep it in a folder the user can write to, such as `~/Applications`, so that it can update itself. The first launch adds ThinkWatch Lite to the application menu, together with its icon and the `thinkwatch://` link handler. Only the AppImage is published; there are no deb, rpm, Flatpak or Snap packages.

It requires Ubuntu 22.04, Debian 12, Fedora 36 or a later distribution of the same generation. An AppImage mounts itself with FUSE and needs `fusermount3` from the fuse3 package (libfuse2 is not needed). Most desktops already include it; otherwise:

Expand All @@ -69,7 +83,9 @@ When the automatic check finds a new version, the app posts a system notificatio

**Downloaded from the releases page on macOS:** one press on the install button does the rest. The app downloads the update, verifies it against a key compiled into itself, waits for the requests the gateway is serving to finish — up to three minutes — then replaces itself and restarts. A task in the middle of a response is not cut off to make room for the update.

**On Windows:** the same single press. The app downloads the new installer, verifies it against the key compiled into itself, waits for the requests in flight to finish in the same way, then runs the installer, and the new version starts once it is done. The app is installed for all users, so Windows asks for administrator permission at every update; declining leaves the current version running.
**With the Windows installer:** the same single press. The app downloads the new installer, verifies it against the key compiled into itself, waits for the requests in flight to finish in the same way, then runs the installer, and the new version starts once it is done. The app is installed for all users, so Windows asks for administrator permission at every update; declining leaves the current version running.

**The Windows portable copy:** the same single press, and no administrator permission is needed. The app downloads the new zip, verifies it against the key compiled into itself, waits for the requests in flight to finish, then replaces the two program files in its folder and restarts. If replacing them fails, the old files are put back and the current version keeps running.

**On Linux:** the same single press, and no password is asked for. The app downloads the new AppImage, verifies it against the key compiled into itself, waits for the requests in flight to finish, then replaces its own file and restarts. The AppImage has to be in a folder the user can write to.

Expand Down
2 changes: 1 addition & 1 deletion src/content/docs-lite/en/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

ThinkWatch Lite is a local gateway for Claude Code, Codex and other AI clients, on macOS, Windows and Linux. Each client is connected once; after that, upstreams and models change in the gateway without touching the client. Every request is recorded with its cost and route, and the API keys in it can be replaced before it leaves the machine.

> It runs on macOS 12 or later on Apple silicon, on Windows 10 21H2 or later on x64 or ARM64 and on Linux on x86_64 or aarch64, is [installed](/docs/lite/install) with Homebrew, a disk image, the Windows installer or an AppImage, and updates itself.
> It runs on macOS 12 or later on Apple silicon, on Windows 10 21H2 or later on x64 or ARM64 and on Linux on x86_64 or aarch64, is [installed](/docs/lite/install) with Homebrew, a disk image, the Windows installer or portable zip, or an AppImage, and updates itself.

## Highlights

Expand Down
Loading
Loading