Skip to content

Repository files navigation

Rust License: MIT macOS: arm64 Windows: x64, arm64 Linux: x86_64, aarch64

ThinkWatch Core

English | 中文

ThinkWatch Core is the gateway engine behind ThinkWatch: a set of Rust crates and the twcore binary built from them. Claude Code, Codex and other clients of the Anthropic, OpenAI and Gemini APIs point at twcore once. From then on, credentials can be kept out of outgoing requests, the tool calls that come back are checked, and every request is recorded with where it went and what it cost. twcore runs inside the desktop app ThinkWatch Lite or on its own on a Linux server, and ThinkWatch Enterprise builds on four of its crates.

Documentation: configuration reference · running core on a server · thinkwat.ch/core

Highlights

  • Connect once, switch freely. Clients keep one address and one key; changing upstreams or models happens in the gateway, with no client change or restart. Anthropic Messages, OpenAI Chat Completions, OpenAI Responses and Gemini are converted in both directions, streams included.
  • Outbound redaction. Outbound redaction can replace API keys, private keys and connection-string passwords with placeholders before a request leaves, and restore them where the answer repeats them, so a relay never sees the real values.
  • Malicious tool calls are cut off. A relay can rewrite an answer and slip in a tool call for the client to run. Tool-call inspection can cut off an answer whose tool call downloads and runs code, sends out environment variables or credential files, reads private keys, or installs a startup item or scheduled job, before the client receives it whole; hidden-character detection, a content filter and an output limit complete the five protections. All start in observe mode (the output limit starts off) and change nothing until set to enforce.
  • Every request is traceable. Each request is stored with the rule that chose its upstream, every attempt, any format conversion, usage, cost and where its price came from, time to first token and generation speed. A dry run shows where a request would go without sending it, and a stored request can be replayed against another upstream for comparison.
  • Routing and failover. Rules match on model, key, format, size, tools, images, thinking and more, and send requests to an upstream or a group (in order, manual, rotation, lowest latency, lowest cost). Until the first byte of the response reaches the client, a failing upstream is replaced by the next candidate and set aside for a time that depends on the reason it gives.
  • Many kinds of upstream. Provider API keys, any compatible endpoint, relays such as OpenRouter, local models, Amazon Bedrock, and ChatGPT or Z.ai accounts. Health checks and warm-ups are answered locally by default, at no cost.
  • Honest cost. Usage, cache reads and writes included, is priced from a daily-refreshed public price table or a custom price sheet. Estimated costs are marked as such, and usage that cannot be priced is counted separately, never as zero.
  • One file, applied live. All settings live in config.yaml; a change from an editor, the CLI or the control plane applies within a second once it validates, and the last fifty versions can be restored.

Install

Desktop. ThinkWatch Lite includes twcore and updates it with the app; nothing else to download.

Linux server (x86_64 or aarch64, glibc 2.35+: Ubuntu 22.04, Debian 12 or later). One command installs twcore as a systemd service with its own user:

curl -fsSL https://raw.githubusercontent.com/ThinkWatchProject/ThinkWatch-Core/main/scripts/install.sh | sudo sh

The script does not start the service. Then, as the service user:

alias twc='sudo -u thinkwatch THINKWATCH_HOME=/var/lib/thinkwatch twcore'

twc remote enable --allow 192.168.1.0/24   # open the remote control port to this network
twc check                                  # validate config.yaml
sudo systemctl enable --now twcore         # start the service, now and at boot
twc control-key                            # the key for ThinkWatch Lite on stdout; address and port on stderr

In ThinkWatch Lite, Settings → Connection → Add remote connection takes the address, control port and key. The app connects only to the core version it includes; sudo twcore upgrade --version <version> --restart switches the server to it. Neither port uses TLS, so keep both on trusted networks. Running core on a server covers secrets, network exposure, upgrades and uninstalling.

Prebuilt binaries for macOS (Apple silicon), Windows (x64, ARM64) and Linux (x86_64, aarch64) are attached to every release, each with a .sha256 checksum; the Linux .tar.gz includes the systemd unit.

twcore keeps its configuration and data in ~/.thinkwatch (%APPDATA%\ThinkWatch on Windows), or in THINKWATCH_HOME. Every field is in the configuration reference.

Control plane

The control plane is an HTTP API inside an encrypted channel: a unix socket (a loopback port on Windows), plus the optional remote port. Every connection starts with a Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s handshake keyed by listen.control.key; there are no certificates. curl cannot reach it; twcore call can:

twcore call /status
twcore call -X POST -d '{"model":"claude-sonnet-4-5","route":"default"}' /dryrun
twcore control-key --rotate     # replace the key; connections made with the old key are closed

The remote port admits only sources in allow_from, at most 32 connections at a time, and cannot stop core, take the diagnostic bundle or change listen.control.

Crates

Crate Role
tw-dialect Conversion between the four API formats; usage parsing
tw-guard The five protections: redaction, tool-call inspection, hidden characters, content filter, output limit
tw-breaker Circuit-breaker state machine
tw-bedrock Amazon Bedrock on the wire: SigV4 signing, eventstream, addresses, model catalog
tw-types Messages for people: stable code, arguments, English sentence
tw-engine Routing rules and groups
tw-pricing Price table, price sheets, measured / estimated / unpriced cost
tw-yaml Minimal edits to the original YAML text
tw-secret Environment and command-sourced credentials, masking
tw-watch Debounced directory watching
tw-api Control-plane contract: types and client
tw-link Control-channel handshake and encryption
tw-config Configuration schema, loading and validation
tw-store Request history and runtime state on SQLite
tw-observe Event bus
tw-gateway Data plane: the life of a request
tw-control Control-plane server

ThinkWatch Enterprise depends only on the first four, which depend only on one another; CI checks that Enterprise compiles against every change to them. ThinkWatch Lite pins tw-api, tw-types, tw-yaml, tw-guard, tw-watch and tw-link to a release tag and bundles the twcore of the same release. Setting up AI clients and scanning their configuration happen in Lite, on the machine it runs on; twcore issues each client its own gateway key. The binary lives in bin/twcore.

Build and test

Requires a recent stable Rust toolchain (1.94.1 or later).

cargo build --release -p twcore     # target/release/twcore
cargo run -p twcore -- init         # write an initial config.yaml
cargo run -p twcore -- serve        # start the gateway and the control plane
cargo test --workspace              # unit and integration tests
scripts/smoke.sh                    # every path on the real binary, in a temporary HOME

CONTRIBUTING.md lists the checks a pull request has to pass and describes the configuration reference, the price list and releases.

License

MIT

About

Gateway engine for Claude Code, Codex and other AI clients, inside ThinkWatch Lite or on a Linux server: credential redaction, tool-call inspection, rule-based routing, per-request cost. Rust, MIT.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages