Skip to content
ThinkWatch
Start typing to search the docs.
ThinkWatch Lite · Features

Features#

A page-by-page reference to what ThinkWatch Lite shows and does. The Lite page gives the short version.

The main window has ten pages: Overview, Traffic, Clients, Keys, Upstreams, Routing, Security, MCP, Plugins and Settings.

Usage and cost#

The Overview page reports tokens, cost and requests for the last 24 hours, 7 days, 30 days or a custom range, each against the period before; a live view follows the last ten minutes. A trend chart stacks tokens or cost by model, and the model ranking beneath it opens the matching requests. Further sections cover the prompt cache (hit rate, the net savings it brought and the hit rate per model), latency (median and 95th-percentile time to first token, per model and per upstream), generation speed (median tokens per second, per model and per upstream) and what each protection found.

The cost figure states how much of it is estimated, for instance for a response that was cut off before it finished. Requests whose model has no price, and requests whose upstream reported no usage, are counted separately and never added in as zero. Prices come from price sheets: the default one follows LiteLLM’s public prices and is refreshed once a day, and a custom one applies a multiplier and its own prices for particular models, as needed for a relay whose prices differ from the official ones. A subscription account such as a ChatGPT sign-in is priced from the price sheet like any other upstream, and an upstream such as a local model can be set to free. Each request’s cost is fixed when the request finishes, and the request records the price sheet and the date of the prices it was costed with.

Until the first request has gone to an upstream, the Overview page shows a get-started checklist instead: add an upstream, connect a client, send a first request. Other pages show a hint for the next step where it applies, such as connecting a client once an upstream exists. A hint can be hidden, and Settings › General shows the hidden ones again.

Traffic and sessions#

The Traffic page lists requests as they arrive: status, key, model, upstream, time to first token and total time (with the generation speed on hover), tokens and cost, with marks for a converted API format, redacted keys, text deleted by the content filter and a blocked or suspicious tool call. The list can be searched (path, key, upstream, model and error message), filtered by key, upstream and model, or narrowed to failed or unpriced requests. It holds the latest 2,000 requests, and a search or filter also runs over the stored history, further back on request. With content search on, it also covers what each request newly sent (the last user turn, tool results included) and its answer (tool calls included), for as long as payloads are kept; a match shows its excerpt under the request. The Sessions view groups the requests of one conversation into turns, with the input tokens and the cost of each turn. A session’s Conversation tab replays it turn by turn: the messages each turn added and its answer, with text, folded thinking, tool calls beside their results, and images by type and size. Changes to the system prompt and restarts after compaction are marked, and a turn whose bodies are past retention, were too large to keep whole or cannot be read says so. Each turn opens its request.

A request opens into its timeline, its routing (the rule it matched, the group it went through and each attempt with its status and duration), the request and response bodies, and its usage and cost. A request from DeepSeek Harness also shows the size of the session log it carried, the whole conversation the client attaches to every request; the gateway removes it before a request goes to an upstream other than DeepSeek. A finished request can be sent again, unchanged, to another upstream after an estimate of its cost, and the two responses are shown side by side.

The attempts also show an upstream passed over at its concurrency limit (At its concurrency limit), the time spent waiting for a free slot, and a streamed answer given up because its start timed out (Start timed out), with the input tokens that upstream may have billed for it. A request refused by its key’s usage limit, or because every upstream stayed at its concurrency limit, shows Usage limit or At capacity in place of an upstream, and a connection in the Responses API’s WebSocket mode is listed one request per turn, each with its own usage and cost.

Client setup#

The Clients page points Claude Code, Claude Desktop, Codex, opencode, Pi, oh-my-pi, Grok Build, Qwen Code, Hermes Agent, Zed, Aider and DeepSeek Harness at the gateway. Before anything is written, it lists the fields that change and what else the change affects (the ChatGPT desktop app, for instance, reads the same configuration file as Codex), shows the full diff and backs up the original file. Only the settings that point the client at the gateway change, and each client receives a key of its own. Claude Desktop is connected through its official third-party inference mode, and the page lists each of the files that change for it; a Claude Desktop managed by an organization is left as it is. Claude Desktop accepts only Claude model names; when no upstream offers a Claude model, the takeover asks which model it should use and adds a routing rule for its key, which cancelling the takeover removes. A connected client can be restored at any time, on its own or together with all the others; a restored Codex keeps a plain OpenAI entry in place of the gateway’s, so sessions started while it was connected can still be opened. opencode (v1 and v2), Pi, oh-my-pi, Grok Build and Qwen Code also get the list of models their key can use on the gateway; when that list changes, the page offers to update it, through the same diff. DeepSeek Harness is covered in its web app, its desktop app and headless runs, which all read the same configuration; models used through a DeepSeek account signed in to the desktop app still go to DeepSeek directly. Cursor, Continue and Antigravity CLI come with step-by-step instructions and a key created for them. For every client the page shows whether it is in use, waiting for its first request or not in effect, and its requests over the last 24 hours.

On Windows, Claude Code and Codex installed inside WSL appear in a group of their own for each distribution, next to the clients on the computer itself. They are pointed at the gateway on Windows, restored and diagnosed the same way, each with a key separate from the Windows copy, and their files are edited through \\wsl.localhost. They are given 127.0.0.1, the same address as the clients on Windows, which WSL reaches in two setups:

  • WSL 1, which shares the network with Windows.
  • WSL 2 with mirrored networking: networkingMode=mirrored under [wsl2] (or the older [experimental]) in %USERPROFILE%\.wslconfig. It needs Windows 11 22H2 or later and WSL 2.0.5 or later.

WSL 2 uses NAT networking by default, and the gateway on Windows cannot be reached from inside WSL that way; the gateway does not listen on the WSL virtual adapter for it. The WSL group then explains this instead of offering to connect, and offers to switch to mirrored networking: networkingMode in .wslconfig is added or changed, and nothing else in the file is touched, through the same diff, confirmation and full backup as a client. The switch takes effect once WSL restarts, which the page also offers (wsl --shutdown, which stops every running distribution). A full uninstall leaves .wslconfig as it is, and its backup is kept. On Windows 10 and Windows 11 21H2, which have no mirrored networking, and with a WSL older than 2.0.5, the group says so. When connected to a remote core, clients in WSL are pointed at the server like those on Windows, whatever the networking.

Keys#

Clients reach the gateway with a key, on the local machine as well. The Keys page lists the default key, used by clients that were not given one of their own, and a key for each connected client, labelled with the client it belongs to so that its requests can be told apart in Traffic. Each key has a route, the models it may use (all, none, or chosen models and patterns such as gpt-5*), an optional limit on concurrent requests, optional usage limits, and its requests and cost over the last 24 hours. A key can be disabled, which rejects every request made with it, or rotated; rotating writes the new key into the configuration of the client that uses it.

Usage limits keep one client from using up a budget: each caps the key at a number of requests, tokens or a cost in USD per minute, hour, day, week or month, and once one is used up the key’s requests are refused until it resets, with the key marked Limit reached. Token limits can count cache reads, models without a price count as zero toward a cost limit and are listed in the key dialog, and a daily, weekly or monthly limit raises a notification at 80% and when it is reached.

Upstreams#

Upstreams are the services requests are forwarded to: API keys for Anthropic, OpenAI, Google Gemini, DeepSeek or any compatible endpoint, Amazon Bedrock (with an API key, access keys or an AWS profile), a ChatGPT account or a Z.ai / BigModel account signed in from the app, relays such as OpenRouter, and local models such as Ollama. A ChatGPT account shows its usage limits and reset times. So does an upstream on a GLM Coding Plan, that is, one whose address is on api.z.ai or open.bigmodel.cn, whether it was signed in from the app or added with a key: its 5-hour and weekly limits and, on a plan billed in credits, the credits left (“1,976 / 2,000 credits left”). When a client and an upstream use different API formats, requests are converted between Anthropic Messages, OpenAI Chat Completions, OpenAI Responses and Gemini, and the fields that cannot be carried over are listed on the request. Upstreams can be reached through an outbound proxy and priced with a price sheet of their own; aliases, proxies and price sheets have tabs on the same page. An optional Concurrency limit suits relays and accounts that allow only so many requests at once: when the upstream is full, a conversation that stays on it waits for a free slot, other requests go to the next upstream, and when every upstream is full a request waits and then receives a busy error. Specs… in an upstream’s model list sets a model’s context window and maximum output by hand, for a model the price table lacks or gets wrong, and the values set there are used in place of the price table’s. A connection test times the DNS lookup and the TCP, TLS and proxy handshakes without incurring any cost; an inference test measures the time to first token and estimates its cost before it runs.

The Aliases tab gives a model the name clients use for it. An alias lists the names the same model has on different upstreams, such as claude-sonnet-5 on Anthropic and us.anthropic.claude-sonnet-5-v1:0 on Bedrock; every upstream that offers one of them serves the alias under its own name, and they back each other up. Clients see aliases in their model lists, and answers carry the name the client asked for, while the request log shows the model each upstream was sent. When the same Claude model has different names on the official API, Bedrock, Vertex or OpenRouter, the tab and the new-alias dialog suggest grouping them. An alias can also be created from an upstream’s model list. The dialog shows which upstream receives which name and warns when the name would take over another upstream’s model of the same name. A key whose model scope allows an upstream model can also use the aliases that list it.

Each upstream is also compared over the last 7 days with the others serving the same model, and a deviation is marked next to its name in the list: Model name differs when answers name a model other than the one sent, Input reported high or Input reported low when the input tokens it reports, as a multiple of the gateway’s own estimate, are well off the other upstreams’, and Low cache reads when follow-up turns read a smaller share of their input from the prompt cache. Hovering over a mark shows the evidence and the sample sizes, and a deviation is marked only when both sides have enough samples.

API keys and header values can be written as ${NAME} to read a system environment variable. On macOS these come from the login shell, so variables exported in ~/.zshrc and similar files apply, and the same holds on Linux (~/.bashrc, ~/.profile and so on); on Windows they are the environment variables configured in system settings. After a variable changes, reopening the app picks it up. Proxy variables such as HTTPS_PROXY, and PATH, are not read.

A relay or vendor can hand out an import link, thinkwatch://import?… or its web form https://thinkwat.ch/import#…, that pre-fills a new upstream with a name, base URL, protocol, API key and model list. The app shows the settings and the host that will receive requests and the key in a confirmation dialog, and writes nothing and contacts nothing before Create is chosen. A link only ever adds one upstream: it cannot change existing ones, headers, proxies, pricing or routing, and a key that refers to an environment variable is rejected. The parameters and a link builder are in Import links.

Routing and failover#

Each key follows a route, and keys without one follow the default route. A route is a list of rules evaluated in order. A rule matches on the model, the key, the client’s API format, input tokens, max_tokens, the number of tools, images, extended thinking, streaming, prompt caching or the kind of auxiliary request; it then forwards the request to an upstream, a group or specified models, or refuses it, and can rewrite the model, max_tokens or extended thinking. Specified models name an upstream and one of its models, with backups tried in order, and send the model as written; to have one client use one model under another model’s name, a rule on that client’s key does it without changing what the name means for other clients. A model condition written for an upstream model also matches the aliases that list it. Setting max_tokens caps the length of answers: the upstream stops at that point by itself, without an error. A group puts several upstreams behind one name and decides the order in which they are tried: as listed, manually selected, in turn, lowest latency first or lowest cost first. In a round-robin group each member has a weight from 1 to 100, its long-run share of requests, and Distribute by can multiply the weights by each upstream’s speed (time to first token), its reliability (recent success rate) or both; conversations in progress stay on their upstream. When an attempt fails, the request moves on to the next upstream, and by default a session stays on one upstream so that its prompt cache keeps hitting. With Move to the next upstream when the start times out on in Settings › Failover, a streamed answer that has sent nothing within the wait also moves on, when another upstream can take it; the last upstream always waits. A map at the top of the page traces every key through its route and groups to the upstreams.

Auxiliary requests that clients send on their own (health checks, warm-ups, titles, topic detection and input suggestions) can be answered locally at no cost, or forwarded. Forwarded ones go through the routing rules like any other request, and a rule can send a given kind to a lower-cost upstream.

Every request records the rule it matched, the group it went through and each attempt with its status and duration. A dry run evaluates the rules for a given request and shows where it would go and why, without sending anything and without incurring any cost.

Security#

The Security page holds three protections: outbound redaction, tool-call inspection and the content filter. They apply to every upstream and every key alike, and each runs in one of three modes: Off, Observe (detect and record, change nothing) and a third mode named for what it does: Replace for outbound redaction, Cut off for tool-call inspection and Enforce for the content filter. All three start in Observe, so out of the box no request is changed or refused.

  • Outbound redaction searches the whole request before it leaves, including the system prompt, earlier turns and tool calls, for credentials and personal information: API keys and tokens for Anthropic, OpenAI, GitHub, Slack, AWS, Google, GitLab, Stripe, npm, DigitalOcean and SendGrid, private keys, JWTs and passwords in connection strings, as well as Chinese resident ID numbers and bank card numbers, which count only when their structure and check digit are valid. In Replace mode they are replaced with placeholders such as <<TW_SECRET_1>> and restored where the response repeats them. Rules for email addresses, Chinese mainland mobile numbers, internal IP addresses and internal domains are included and start off, and a custom rule can name its own placeholder: PROJECT gives <<TW_PROJECT_1>>.
  • Tool-call inspection checks the tool calls a model returns for commands that download or decode code and run it, send out environment variables or credential files, send a credential to a host that is neither local nor the credential’s own provider, read private keys or cloud credentials, read or change ThinkWatch’s own data directory, or install startup items and scheduled jobs. A path that only appears in text being written, such as a document that mentions the directory, does not count. In Cut off mode such a call cuts the response off, so the client never receives a complete call to run. Deleting the home or root directory, making files world-writable and uploading a local file to an outside host are only recorded by default.
  • Content filter checks the user messages and tool results in each request, context compaction included. A rule matches a keyword, a regular expression or code points such as U+E0000–U+E007F, and in Enforce mode it refuses the request, deletes the matched text and sends the rest, or only records. Built-in rules delete Unicode tag characters and bidirectional controls, which can hide instructions from people but not from a model, and refuse explicit “ignore previous instructions” phrasing. Rules for zero-width and private-use characters, which emoji, Persian text and icon fonts also use, and for jailbreaks, persona manipulation, prompt extraction and their Chinese counterparts start off and can be switched on.

The page lists every rule, the built-in ones grouped by kind. Built-in rules can be switched on or off one at a time; a built-in tool-call rule can be set to cut off or only record, and a built-in content rule to refuse, delete or only record. Custom rules are regular expressions, or for the content filter also keywords or code points. Any rule can be tried on a sample text first; for redaction and the content filter, the test also shows the text as it would be sent. Everything the protections find is kept in the log on the first tab, together with the request it came from; when hidden characters spell out text, the log shows that text.

The protections act on requests and answers passing through the gateway, not on files on disk. The configuration file holds keys in plain text and only its owner can read it, which keeps out other users but not programs running as the same user; outbound redaction protects what leaves the machine, not the file.

MCP#

The MCP page covers what clients load from their own configuration files, which does not pass through the gateway.

  • Servers: the MCP servers configured in Claude Code, Claude Desktop, Cursor, Codex, opencode, Antigravity CLI, Zed, Pi, oh-my-pi, Grok Build, Qwen Code, Hermes Agent and DeepSeek Harness, side by side. A server can be copied from one client to another or removed from a client; the change is shown before anything is written, and the original file is backed up. Copying and removing work for Claude Code, Claude Desktop, Cursor and Codex; the other clients are listed but not written to. A remote server on another host is marked as third party, since using it sends the surrounding context to that host, and a server configured differently in different clients is marked as well and can be compared side by side.
  • Skills and hooks: the installed skills and configured hooks, with the client each belongs to; skills in the shared ~/.agents/skills folder are listed as such.
  • Findings: client configuration, skills, hooks, slash commands, subagents and project instruction files are scanned for hidden characters, prompt injection, dangerous commands and overly broad permissions, and each finding is graded high, medium or low. The scan only reports; it never changes a file.

The app watches these files while it runs, and a new finding raises a system notification.

Plugins#

Plugins are short JavaScript files that change requests before they go to an upstream and answers before they reach the client, such as asking for answers in a chosen language or converting file paths in tool calls between WSL and Windows. They run after routing, in a sandbox inside core with no network, files or memory between requests, see placeholders instead of the keys in a request, and pass through the same protections afterwards. Two plugins ship with the app, both off until turned on. Each plugin is one file that also holds its scope, its behavior on errors and its settings. It is edited in one editor with a Settings tab, whose changes are written into the file, and a Code tab; adding a plugin opens the same editor. Routine changes are saved directly; for a plugin that may change tool calls, installing it, turning it on, changing its code and approving a changed file are confirmed in a system dialog. A plugin whose file changes outside the app stops running until the new version is approved. The page lists each plugin with its status, permissions, scope and statistics, and offers a trial run on a recent request and its log; requests changed by plugins are marked in Traffic. The API, permissions, limits and security model are described in Plugins.

Settings#

Settings has seven sections. Connection lists the local core and the saved remote cores, described in Connecting to a remote core. General sets the language, the appearance, what the menu bar item shows on macOS, launch at login, whether notices arrive as system notifications, in the app only or not at all, and shows hidden guidance hints again. Listening sets who can reach the gateway (this machine only, the local network of a chosen interface, or every interface), its port and the allowed address ranges. Failover sets how long a failing upstream is paused before requests go to the next one: after how many consecutive failures, for how long, and separate pauses for an insufficient balance, a used-up quota and rate limits. It also sets how long to wait for a streamed answer to start, whether a stream that has not started by then moves to the next upstream (off by default), and how long in total a request may wait for a free slot on a full upstream or for a key’s per-minute or per-hour limit, 30 seconds by default. Log retention sets how long request payloads and request records are kept, and a size cap for payloads. About shows the version, checks for updates and produces a diagnostics bundle with keys and addresses masked. Uninstall restores every connected client and removes the autostart entry, and is meant to be run before the app is deleted.

On macOS the menu bar shows today’s tokens above today’s cost; the numbers turn orange when a subscription quota is nearly used up and red when it is, and Settings can reduce the item to the icon or to the numbers.

Clicking it opens a native menu with the gateway’s address, its generation speed over the last minute and its state, unread notices, today’s requests, tokens and cost, the quotas and reset times of each subscription account and GLM Coding Plan upstream (with the credits left under the bar on a plan billed in credits), and the requests in progress, followed by actions: choosing the upstream of a manually selected group, copying the gateway address or the default key, switching connections and checking for updates, all without opening the main window.

On Windows the icon sits in the notification area. Hovering over it shows the gateway’s state and today’s tokens and cost; a left click opens the main window, and a right click opens the same menu, with quota bars written out as text.

On Linux the icon sits in the system tray. Clicking it opens the same menu, with Open ThinkWatch Lite as its first item and quota bars written out as text.

System notifications, native on macOS and Windows and sent through the desktop’s notification service on Linux, report when the gateway stops forwarding or keeps restarting, the connection to a remote core drops, a subscription quota runs out, a sign-in expires or an upstream rejects its credential, a proxy cannot be reached, the configuration file fails validation, a tool call matches a rule that cuts the response off, a key nears or reaches a daily, weekly or monthly usage limit, or suspicious content appears in a client’s configuration. A new version found by the automatic check is announced the same way (see Updates). An unreachable upstream, which a fallback usually covers, is only listed in the app. Notices as a whole can be set to system notifications, in-app only, or off. Marking a notice as read stops the bell from counting it; the notice stays in the list until the problem behind it clears or the list is cleared.

Last updated 2026-10-05 Edit on GitHub