scaledthought
v0.3.7
Published
OpenAI-compatible inference for open-weight models, set up by your coding agent. Prepaid, pay per token, no subscription. US live; Canada coming soon.
Maintainers
Readme
scaledthought
The CLI for ScaledThought: headless, OpenAI-compatible inference for open-weight models. The US region is live; Canada is coming soon. It's built for coding agents: it never prompts, prints JSON when stdout isn't a terminal, and every error is one JSON line on stderr with a non-zero exit.
Agents: the full setup protocol is at https://scaledthought.com/llms.txt.
npx -y [email protected] init --region us --source org-npm # US only for now; Canada is coming sooninit creates an account, writes ST_API_KEY and ST_BASE_URL to ./.env (mode 0600), adds .env to
.gitignore, and prints the account, its credit balance (balance_usd, needs_credits), the models live in your
region, next_command and next_steps.
Running it again is safe. If a key already exists it returns "already_initialized": true and the
account status instead of creating a second account.
Before init, ask your human one question: "What email should own this account?" and pass it as
--email <address>. We email that address one confirmation link; once they click it they own the account and sign in
to its dashboard (billing, credits, keys). We send it account email, such as the confirmation, sign-in links and security
notices, and product emails they can unsubscribe from any time. init then prints email_confirmation and a message_for_human to relay. If they'd
rather not, leave the flag out: init prints "missing": ["owner_email"], and
npx -y [email protected] account email set <address> names them later.
If you arrived through a scaledthought.com/go/<code> link, its instructions add --source <code> (a campaign code
such as a-rd, stored on the new account so we know which campaign worked; the command above carries org-npm, the
code for this page). Directory listings link to their own /go/<code>, and a listing's MCP URL can end in
?source=<code>: connecting without a key then answers with the init command carrying that code. It's optional, and a value that isn't a
code is dropped with a warning rather than failing init. On some US campaigns the human can copy an opt-in prompt
ending in (ad click <token>); the /go instructions then tell the agent to add --ad-click <token> (the token is
in the prompt, never in the link). A malformed token is dropped with a warning, and the flag is ignored outside us.
Turn ad measurement off at any time with account ad-measurement off (nothing about the account is then sent to any
ad platform). account and account ad-measurement print ad_measurement (true only when something about the
account could be sent: a us account that signed up with an ad click and hasn't opted out; always false in ca) and
ad_measurement_opt_out (the stored preference). Neither flag is a secret.
Inference is prepaid, and a new account has no credits: until your human pays, completions return
402 insufficient_credits. (Only when init prints "trial": "after_email_confirmation": the account should get
limited usage to try it once your human confirms their email, in the US region while that offer lasts; its next_steps
say what to do. Otherwise, or once that is used, top up as below.) So the first thing after init is usually a top-up your human approves:
npx -y [email protected] billing topup --amount-usd 20 # prints approval_url and topup_id
# show your human the approval_url, exactly as printed; they pay by card
npx -y [email protected] billing wait # returns once they've paid; on topup_pending run it againbilling wait returns within about 90 seconds (--timeout-s to change it), under Claude Code's default 2-minute
shell timeout. Prefer it to billing topup --wait: an agent's shell tool usually shows a command's output only when it
ends, so the link would reach the human only after the payment it is waiting for.
npx -y [email protected] models --live # models serving in your region now
npx -y [email protected] chat -m <id> "Reply with OK" # one real completion (an id from models --live)
npx -y [email protected] mcp # `claude mcp add …` command + JSON config
npx -y [email protected] account # plan, region, spend, owner_email
npx -y [email protected] account email set <address> # your human's email owns the account once they confirm
npx -y [email protected] account rename "<name>" # the account's name on the dashboard ("" = the default)
npx -y [email protected] account ad-measurement off # opt out of ad measurementOther commands: keys list|create|rotate|revoke|revoke-self (keys create --expires-in 30d --scopes inference --child, keys rotate <id> --grace 24h), usage, billing status|topup|wait|auto-reload|transactions, batches …,
fine-tune …, benchmarks <id>, status (with your account's notices when a key is set), doctor (setup check),
webhooks add <url> [--events …]|list|remove <id> (signed callbacks), transcribe <file> (speech to text, --translate for English,
--format srt|vtt|text|verbose_json) and speak -o out.mp3 "text" (text to speech, streamed to the file; US
only for now) and realtime --model <id> --input question.wav --output reply.wav (one spoken turn over the realtime
WebSocket; mono 16-bit 24 kHz WAV; paid from prepaid credits). Add --help to any of them.
Keys for other places (the key goes to the platform's own CLI on stdin; it is never printed or put in argv):
npx -y [email protected] keys put github --repo acme/app --budget-usd 2 # also vercel, fly, cloudflare, gcp, aws, k8s, doppler
npx -y [email protected] keys rotate --all --push --grace 1h # re-put every replacement where the old key lived
npx -y [email protected] connect opencode # or aider; cursor and continue print stepsUse the key from any OpenAI SDK: base_url = $ST_BASE_URL, api_key = $ST_API_KEY.
- Keys are read from
ST_API_KEYor./.env, never from flags. - The key's prefix (
st_us_…/st_ca_…) picks the region's hosts. Requests never cross regions. - Errors look like
{"error":{"code":"…","message":"…","hint":"…"}}. Exit code 2 means bad usage, 1 anything else.
Before the first credit purchase an account has lower limits: 60 requests/min per key and up to 5 keys.
