CLI Overview
The ThinkWork CLI (thinkwork-cli) is the primary way to deploy and manage ThinkWork and to operate a running stack. It wraps Terraform for provisioning, authenticates to the deployed Cognito pool for day-two ops, and exposes every admin-site capability as scriptable + interactive commands.
Installation
Section titled “Installation”npm install -g thinkwork-cliOr run one-off without installing globally:
npx thinkwork-cli --helpVerify the installation:
thinkwork --versionthinkwork --helpRequirements
Section titled “Requirements”- Node.js 20+
- Terraform 1.6+ on your
$PATH(for deploy/plan/destroy) - AWS credentials (via
~/.aws/credentials, environment variables, or EC2/ECS instance role) - A browser (for
thinkwork login --stage <s>— optional;--api-keyskips it)
Two kinds of sign-in
Section titled “Two kinds of sign-in”The CLI has two separate login flows — they do different things and are stored separately in ~/.thinkwork/config.json.
thinkwork login — AWS credentials
Section titled “thinkwork login — AWS credentials”Configures the AWS credentials the CLI uses to shell out to terraform and the aws CLI. Arrow-key picker over your existing ~/.aws/ profiles, with fall-through to access-key entry or aws sso login.
thinkwork login # interactive profile pickerthinkwork login --sso --profile work-ssothinkwork login --keys --profile thinkworkThe chosen profile is saved as defaultProfile and used by plan, deploy, destroy, bootstrap, doctor, outputs, status, init, etc.
thinkwork login --stage <s> — Cognito session
Section titled “thinkwork login --stage <s> — Cognito session”Signs in to the deployed stack’s Cognito user pool via OAuth2 authorization-code flow over a local loopback listener (port 42010). Supports Google OAuth through Cognito’s hosted UI. The resulting id/refresh tokens plus the caller’s default tenant are cached on sessions["<stage>"].
# Interactive — opens browserthinkwork login --stage dev
# Non-interactive — CI / servicethinkwork login --stage prod --api-key "$THINKWORK_API_KEY" --tenant acmeAPI-backed commands (thinkwork thread list, thinkwork agent create, thinkwork me, …) consume this session. Cognito id-tokens are refreshed transparently from the refresh token.
Where state lives
Section titled “Where state lives”~/.thinkwork/config.json:
{ "defaultProfile": "thinkwork", "defaultStage": "dev", "sessions": { "dev": { "kind": "cognito", "idToken": "...", "refreshToken": "...", "expiresAt": 1234, "tenantSlug": "acme", ... }, "prod": { "kind": "api-key", "authSecret": "...", "tenantSlug": "acme", "tenantId": "..." } }}~/.thinkwork/environments/<stage>/config.json:
{ "stage": "dev", "region": "us-east-1", "accountId": "123456789012", "terraformDir": "/Users/alice/thinkwork-deploy", "databaseEngine": "aurora-serverless", "enableHindsight": false, "createdAt": "2026-04-16T10:00:00Z", "updatedAt": "2026-04-16T10:00:00Z"}The environment registry is populated by thinkwork init and lets any command resolve the terraform working directory without needing a cd or a --dir flag.
Stage resolution
Section titled “Stage resolution”Every API-backed command needs a stage. Resolution order:
-s / --stage <name>flagTHINKWORK_STAGEenv vardefaultStagein~/.thinkwork/config.json(set by a successfulthinkwork login --stage <s>)- The sole deployed stage in the configured AWS region, if there’s only one
- Interactive picker (TTY only; errors in CI)
Tenant resolution
Section titled “Tenant resolution”API-backed commands also need a tenant (workspace). Resolution order:
-t / --tenant <slug>flagTHINKWORK_TENANTenv vartenantSlugcached on the current stage’s session (set at login time viabootstrapUser)- Interactive picker of the caller’s tenant memberships (TTY only)
Flag-driven and interactive modes
Section titled “Flag-driven and interactive modes”Every command works two ways:
- Flag-driven for agents and CI: pass every field as a flag. Missing required flags in a non-TTY context print a clear error and exit 1.
- Interactive walkthrough for humans: missing fields are prompted with arrow-key pickers or text input.
Ctrl+Ccancels cleanly.
# Fully interactivethinkwork user invite
# Fully scriptedthinkwork user invite alice@example.com --tenant acme -s dev --role admin
# Mix — pass the positional, prompt for everything elsethinkwork user invite alice@example.comMachine-readable output
Section titled “Machine-readable output”Every API-backed command accepts --json:
thinkwork me --json | jq .tenantSlugthinkwork thread list --status IN_PROGRESS --json | jq '.[] | .id'thinkwork cost summary --json | jq .totalUsd--json routes structured output to stdout; warnings, spinners, and errors always go to stderr so pipelines stay clean.
Using the CLI in CI
Section titled “Using the CLI in CI”# 1. AWS side (deploy / destroy / status) — credentials from env or IAM role.export AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}export AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}export AWS_REGION=us-east-1thinkwork deploy -s prod --auto-approve
# 2. API side (thread / agent / inbox / …) — api-key session, no browser.thinkwork login --stage prod --api-key "${{ secrets.THINKWORK_API_KEY }}" --tenant acmethinkwork thread list --status IN_PROGRESS --json | jq '.[].id'The api-key path stores authSecret + tenant on the session. resolveAuth(stage) sends Authorization: Bearer <secret> + x-tenant-id: <id> for every subsequent call.
See Commands Reference for the full syntax and options for every command — flags, positional args, examples for both interactive and scripted invocations, and the full Phase 1–5 roadmap of scaffolded commands.