SDKs & CLI

CLI

The wity command asks Wity questions from your terminal. It prints a probability for every answer, and its exit codes let shell scripts and CI jobs act on the answer.

Use it to:

  • Try a question on some text, without writing any code.
  • Make a decision inside a shell script or a CI job, like "does this change need a billing reviewer?".
  • Give AI agents, like Claude Code or Cursor, Wity as a set of tools.

Install#

npm install -g wity-cli

Needs Node.js 22.13 or newer. -g installs it for your whole computer, so the wity command works in any folder. Run wity --version to check that it's installed.

API key#

Every question is sent to the Wity API, which needs an API key. Create one on the keys page, then save it in the CLI:

wity api-key set # paste your key at a hidden prompt
wity doctor # check that the key, storage and connection all work

The key stays hidden while you paste it. The CLI checks the key with a free call, then saves it, so you only do this once. Other ways to set the key:

wity api-key set wity_…
in the command
Saves the key in one step. Your shell history keeps a copy of the command.
wity api-key set --stdin
for scripts and CI
Reads the key from a pipe instead of a prompt: echo "$KEY" | wity api-key set --stdin.
WITY_API_KEY
environment variable
Skips saving a key at all. When it's set, it wins over the saved key.

To look after the key later:

wity api-key show
check
Shows the start of the key in use, where it comes from, and whether it works.
wity api-key set
replace
Running it again replaces the saved key.
wity api-key remove
remove
Removes the key from this computer only. The key itself keeps working, because it may be in use somewhere else. To stop it working, revoke it on the keys page.

Where the key is kept

  • In your system's keychain: macOS Keychain, Windows Credential Manager, or the Secret Service on Linux.
  • Without a keychain, in ~/.config/wity/credentials.json, which only your user can read. Set WITY_CREDENTIAL_STORE to keychain or file to choose.
  • The key is saved for one API address, and never sent to another.

Your first question#

wity noul "Is this urgent?" --text "Server is down for all customers"

The command has three parts:

  • noul is the type of question: yes or no.
  • "Is this urgent?" is the question. Write it the way you'd ask a colleague.
  • --text is the text Wity judges.

In a terminal, the answer looks like this:

  • A bar for each option, with its probability. The most likely option is marked.
  • confidence: how concentrated the probabilities are, from 0 (spread evenly) to 1 (all on one option).
  • A note if Wity thought before answering, and what it said before thinking.
  • The time taken, the tokens sent and the cost.

Probabilities

Probabilities add up to 1, and a higher number means Wity is more sure. They aren't exact odds. See Probabilities & confidence.

The three question types#

# noul: a yes-or-no question. Prints the probability of yes.
wity noul "Is this a phishing message?" --file email.txt
# choice: pick one option. Add -o id="description" once for each option.
wity choice "Which team handles this?" \
-o billing="Payments and refunds" \
-o technical="Bugs and outages" \
-o other="Anything else" \
--file ticket.txt
# score: a level on a scale. Add -l once for each level, lowest first.
wity score "How upset is the customer?" -l Calm -l Annoyed -l Angry --text "Where is my order?!"
noul
yes or no
Answers with the probability of yes. Add --if-yes and --if-no to say what yes and no mean in your case, which helps when the question alone is vague.
choice
pick one
Each -o adds one option, written id="description". Wity reads the description to understand the option, and answers with the id.
score
a scale
Each -l adds one level, lowest first, 2 to 10 in all. The levels are numbered from 0. The answer is the expected level, so it can fall between two levels, like 1.4.

See Writing good questions for tips.

Where the text comes from

wity noul "Is this spam?" --text "You won a free cruise!" # text in the command
wity noul "Is this spam?" --file email.txt # text from a file
cat email.txt | wity noul "Is this spam?" # text from a pipe
wity noul "Is this spam?" --file - # text from stdin

The text can be up to 32,000 characters.

Options for every question

-r, --reasoning
off | auto | always
When Wity may think before answering. auto, the default, thinks only when the question is hard. off is the fastest. See Reasoning.
--max-latency <ms>
200 to 120000
Caps how long the request may take. When time runs out, Wity stops thinking and answers.
--json
flag
Prints the full response as JSON. This is the default when the output goes to a pipe or a file.
--field <path>
string
Prints one value from the answer (see below).
--fail-under <n>
number
Exits with code 10 if the answer is under n (see below).
--expect <id>
choice only
Exits with code 10 unless this option wins.
--dry-run
flag
Prints the request without sending it. Needs no key.
--code [ts|curl]
flag
Prints the request as TypeScript code (using the SDK) and as a curl command, instead of sending it. Needs no key.

Using answers in scripts#

In a script you usually want one number, or a simple pass or fail. Three options give you that.

wity noul "Is this spam?" --file email.txt --field noul
# prints only the probability of yes, like 0.97
wity choice "Which team?" -o billing="Payments" -o technical="Bugs" --file ticket.txt --field choice
# prints only the winning option's id, like billing
wity choice "Which team?" -o billing="Payments" -o technical="Bugs" --file ticket.txt --field probabilities.billing
# prints only the probability of billing

Without --field, piped output is the full JSON response. A single question's answer is under answers.answer in it.

Pass or fail with --fail-under

--fail-under <n> makes wity exit with code 10 when the answer is under n. Shell if statements and CI jobs treat any code other than 0 as a failure. What's compared:

  • for noul, the probability of yes
  • for choice, the probability of the winning option, or of the --expect option if you gave one
  • for score, the score itself, on the level scale (0 is the lowest level)
# Ask whether a code change touches billing code.
# --fail-under 0.5 makes wity exit with code 10 if the probability of yes is under 0.5.
# >/dev/null hides the output, because only the exit code matters here.
if wity noul "Does this diff touch billing code?" --file change.diff --fail-under 0.5 >/dev/null; then
echo "Needs a billing reviewer"
fi

Check the winner with --expect

# Exit with code 10 unless "billing" wins, and with at least 0.8 probability.
wity choice "Which team handles this?" -o billing="Payments" -o technical="Bugs" \
--file ticket.txt --expect billing --fail-under 0.8

Several questions at once#

wity ask reads questions from a YAML or JSON file and sends them all in one request. It costs less than asking them one by one, because the text is sent and billed once.

# questions.yaml
state: My card was charged twice, and I need one refund before Friday. # optional: or use --text, --file, a pipe
reasoning: auto # optional
questions:
team: # a name you choose for this question
type: choice
instructions: Which team should handle this ticket?
criteria: # the options: id, then description
billing: Payments, charges and refunds
technical: Bugs, errors and outages
other: Anything else
urgent:
type: noul
instructions: Does the customer need this soon?
upset:
type: score
instructions: How upset is the customer?
criteria: [Calm, Annoyed, Angry] # the levels, lowest first

The file uses the same format as the API. Each question has a type, the question in instructions, and for choice and score, the options or levels in criteria. Then run it:

wity ask questions.yaml # print every answer
wity ask questions.yaml --field team.choice # print only the team
  • To ask the same questions about different texts, leave state out of the file. Then pass the text the usual way: wity ask questions.yaml --file ticket.txt. A file that has a state can't take --text or --file as well.
  • state can also be an object, which Wity reads as JSON.
  • Every problem in the file is listed before anything is sent.
  • --reasoning and --max-latency on the command line override the file.

Generate#

Questions pick from options you wrote. wity generate writes new text instead, like a short reply or a value read off a document, up to 512 tokens. A token is a word or a piece of a word.

# free text
wity generate "The one-sentence reply to send" --file ticket.txt
# JSON that matches a JSON Schema in ticket.schema.json
wity generate "Origin city and seat" --text "LISBOA (LIS) -> BER, seat 23C" --shape ticket.schema.json
  • --shape takes a JSON Schema file, which describes the JSON you want: its fields, and what each one holds.
  • In a terminal it prints the text, then the time and cost.
  • In a pipe it prints only the text, or with --shape only the JSON. Add --json for the whole response.
  • --max-tokens caps the length (default 128). If Wity hits it, the CLI says so. With --shape, it also exits with code 1, because the JSON is incomplete.

Heads up

Check generated text before you act on it. It can say things that aren't in the input.

From the CLI to code#

Once a question works, --code prints it as code you can paste into your app. It uses the TypeScript SDK and curl. Nothing is sent, and no key is needed.

wity noul "Is this urgent?" --text "Server is down" --code ts

Playground#

Run wity with no arguments to open an interactive screen in your terminal, where you can change the text and the question and ask again. wity playground --file ticket.txt opens it with text from a file.

  • Type or paste the text, pick a question type, and press Enter to ask.
  • Tab moves between fields. ← and → change the question type and the reasoning mode.
  • Ctrl+T shows the request as code. Esc quits.
  • Every Enter is a real, billed call. The header shows what you've spent so far.

AI agents (MCP)#

MCP (Model Context Protocol) is a standard way for AI apps to use outside tools. wity mcp serve gives an AI app five Wity tools: wity_noul, wity_choice, wity_score, wity_ask and wity_generate. The agent can then ask Wity a typed question whenever it needs a decision.

First save a key with wity api-key set, or set WITY_API_KEY. Then add the server to your AI app. For Claude Code:

claude mcp add wity -- wity mcp serve --max-spend 1

For Claude Desktop, Cursor and other apps, add this to their MCP settings:

{
"mcpServers": {
"wity": { "command": "wity", "args": ["mcp", "serve", "--max-spend", "1"] }
}
}
  • --max-spend 1 stops paid calls after $1 in one session, in case an agent gets stuck in a loop.
  • The server talks to the app over stdin and stdout only. It opens no network port.
  • No tool can read, set or remove the key, and the key never appears in tool output.

Exit codes#

Every command ends with an exit code. Scripts can read it from $?, and if treats 0 as success:

0
ok
It worked.
1
failed
The API or the network failed.
2
bad input
Wrong flags or input. Nothing was billed.
3
key
No API key, or the key was refused.
10
check failed
Wity answered, but the answer failed --fail-under or --expect.
130
cancelled
You pressed Ctrl+C.

Settings#

Environment variables the CLI reads:

WITY_API_KEY
env
Use this key instead of the saved one.
WITY_CREDENTIAL_STORE
env
Where to save the key: auto (default), keychain or file.
WITY_LOG_LEVEL
env
How much to log: debug, info, warn (default), error or off. Logs go to stderr, and never include the key or your text.
WITY_BASE_URL
env
Another API address, for testing. https only, except localhost.
NO_COLOR, FORCE_COLOR
env
Turn colours off or on.

Questions, bugs and security problems: info@alphanimble.com. The CLI is licensed Apache-2.0.