CLI (mrl)
mrl is the ModelRelay command-line client. Use it to make model requests, sign in and create API keys, and manage customers, tiers, and usage.
Quick start
brew install tensor-systems/tap/mrl
mrl auth login --web # or --device on a machine without a browser
mrl keys create --name laptop # creates a key and saves it to the profile
mrl config set --model claude-sonnet-5-5 # default model
mrl "What is the capital of France?"
Installation
Homebrew (macOS/Linux)
brew install tensor-systems/tap/mrl
To upgrade:
brew upgrade mrl
Manual download
Download a release for macOS or Linux (arm64 or amd64) from releases.modelrelay.ai/mrl and add it to your PATH.
Check the installed version with mrl version or mrl --version.
Sign in and create API keys
Most commands use a secret API key (mr_sk_*). Creating keys and tiers uses an account token instead, which mrl auth login stores in the active profile.
mrl auth login --web # browser OAuth on this machine (GitHub by default)
mrl auth login --web --provider google # browser OAuth with Google
mrl auth login --device # approve a link from any device
mrl auth logout # clear the stored account token
Password accounts can log in with --email and --password-stdin:
printf '%s' "$PASS" | mrl auth login --email you@example.com --password-stdin
An expired login is refreshed automatically. If refreshing fails, run mrl auth login again.
Device sign-in
--web needs a browser on the machine running mrl. On a server, or a machine an agent drives while you are away from it, use device sign-in:
mrl auth login --device
The first line of stdout is the link and code to relay:
Open https://modelrelay.ai/device?code=WDJB-MJHT and approve code WDJB-MJHT
Open the link on any device, sign in with GitHub or Google (or create an account; new accounts get the signup credit), and tap Approve. The code is already filled in. mrl waits, saves the account token, and exits. The code expires after 10 minutes.
For agents, --json prints one JSON line before waiting and one after:
mrl auth login --device --json
# {"expires_in":600,"interval":5,"status":"pending","user_code":"WDJB-MJHT","verification_uri":"https://modelrelay.ai/device","verification_uri_complete":"https://modelrelay.ai/device?code=WDJB-MJHT"}
# {"profile":"default","status":"logged_in"}
Device sign-in uses the OAuth 2.0 Device Authorization Grant (RFC 8628); see Device sign-in for the endpoints.
API keys
# Create a key, print it once, and save it as the active profile's api_key
mrl keys create --name laptop
# Print only the secret (newline-terminated) and save nothing, for scripts
KEY=$(mrl keys create --name my-app --print)
# A key with a hard lifetime spend limit, in cents ($5.00 here)
KEY=$(mrl keys create --name app-review --spend-limit 500 --print)
# List keys (redacted), with each limited key's spend so far
mrl keys list
# Revoke a key by its ID (from `mrl keys list`)
mrl keys revoke 3f2a...
| Flag | Description |
|---|---|
--name |
Label for the key (required) |
--print |
Print only the secret to stdout; do not save it to the profile |
--spend-limit |
Hard lifetime spend limit in cents |
A spend-limited key is refused with 402 API_KEY_SPEND_LIMIT_REACHED on every billable endpoint once its settled spend reaches the limit. The check runs before each request, so requests already in flight when the limit is reached can take spend slightly past it. The limit cannot be raised: revoke the key and create another. A spend-limited key cannot mint customer tokens.
The key is created in --project (or MODELRELAY_PROJECT_ID / the profile’s project_id); otherwise in your account’s default project. If the account has several projects and no default, mrl lists them and asks for --project.
Configuration
Environment variables
export MODELRELAY_API_KEY=mr_sk_... # secret API key (MODELRELAY_SECRET_KEY also works)
export MODELRELAY_TOKEN=... # account token (overrides the stored login)
export MODELRELAY_PROJECT_ID=... # project UUID
export MODELRELAY_API_BASE_URL=... # defaults to https://api.modelrelay.ai/api/v1
export MODELRELAY_MODEL=claude-sonnet-5-5 # default model
Flags override environment variables, which override the config file.
Config file
~/.config/mrl/config.toml (or $XDG_CONFIG_HOME/mrl/config.toml):
current_profile = "default"
[profiles.default]
api_key = "mr_sk_..."
base_url = "https://api.modelrelay.ai/api/v1"
project_id = "<uuid>"
model = "claude-sonnet-5-5"
output = "table" # or "json"
# Defaults for `mrl do`
allow_all = false
allow = ["git ", "npm "]
trace = true
mrl auth login and mrl keys create write token and api_key into the active profile for you.
Profiles
mrl config set --profile dev --api-key mr_sk_... --model claude-sonnet-5-5
mrl config use dev # make dev the current profile
mrl config show # show the current profile
mrl --profile dev "Hi" # use a profile for one command
mrl config set accepts --profile, --api-key, --base-url, --project, --model, --output (json or table), and the mrl do defaults --allow-all, --allow, and --trace.
Make a request
Pass a prompt to send it to a model through the Responses API:
mrl "What is 2 + 2?"
mrl "Write a haiku" --stream
mrl "Explain recursion" --model claude-sonnet-5-5 --usage
A model is required: pass --model, set MODELRELAY_MODEL, or run mrl config set --model.
Piped text is prepended to the prompt:
git diff | mrl "Explain these changes"
cat README.md | mrl "Summarize this"
Attach files with -a:
mrl "Describe this screenshot" -a ./screenshot.png
| Flag | Description |
|---|---|
--model |
Model ID (overrides the profile default) |
--system |
System prompt |
--stream |
Stream output as it is generated |
--usage |
Show token usage after the response |
-a, --attachment |
Attach a local file; repeatable; - reads stdin |
--attachment-type |
Override the attachment MIME type (useful for stdin) |
--attach-stdin |
Attach piped stdin as a file instead of prepending it as text |
Quick tasks with do
mrl do runs a local tool loop: the model can run shell commands on your machine to complete a task.
mrl do "show git status" --allow "git "
mrl do "run tests and fix any failures" --allow-all
No commands are allowed by default. Use --allow to permit command prefixes, or --allow-all to permit any command. Set defaults with mrl config set --allow "git " --trace.
The loop calls the Responses API, executes the returned tool calls locally, sends the results back, and stops when the model replies without tool calls. Tool execution happens only on your machine.
sequenceDiagram
participant CLI as mrl CLI
participant API as /responses API
participant Local as Local Shell
CLI->>API: POST /responses [system, user]
API-->>CLI: tool_call: bash "git status"
CLI->>Local: git status
Local-->>CLI: output
CLI->>API: POST /responses [... + tool_result]
API-->>CLI: text, no tool calls
Note over CLI: No tool calls → exit loop
| Flag | Description |
|---|---|
--model |
Model ID (overrides the profile default) |
--system |
System prompt |
--allow |
Allow a bash command prefix; repeatable |
--allow-all |
Allow all bash commands |
--max-turns |
Maximum tool loop turns (default 50) |
--trace |
Print tool calls as they execute |
Models
# List text-generation models in the catalog
mrl model list
# Filter by provider and capability
mrl model list --provider openai --capability text_generation
# Include deprecated models
mrl model list --include-deprecated --json
--capability defaults to text_generation.
Resolve a route
Inspect the concrete model, selected provider, and pricing provenance for a Responses request without making a model call:
mrl response resolve --model claude-sonnet-5-5 --json
--model is required; --provider pins a provider. The command creates no usage or settlement record.
Customers, tiers, and usage
Customers
mrl customer list
mrl customer get <customer-id>
mrl customer create --external-id user_123 --email user@example.com
Tiers
mrl tier list
mrl tier get <tier-id>
mrl tier create uses an account token (run mrl auth login first) and needs a project:
# A $10/month Pro subscription billed through Stripe
mrl tier create --code pro --name "Pro" --billing-mode subscription \
--provider stripe --price 1000 --interval month \
--model grok-4.7 --default-model grok-4.7
# A pay-as-you-go tier seeded with $1 of promo credit
mrl tier create --code paygo --name "Pay as you go" --billing-mode paygo \
--promo-credits 100 --model grok-4.7 --default-model grok-4.7
| Flag | Description |
|---|---|
--code |
Tier code (required) |
--name |
Display name |
--billing-mode |
subscription or paygo (required) |
--provider |
Billing provider for subscription tiers, such as stripe |
--price |
Subscription price in cents |
--interval |
month or year |
--trial-days |
Free-trial length in days |
--promo-credits |
Promo credit granted on a customer’s first token, in cents |
--spend-limit |
Spend ceiling in cents for subscription tiers; omit for none, 0 permits no spend |
--model |
Model available on the tier; repeatable |
--default-model |
Which --model is the default |
--token-ttl |
Maximum customer-token TTL in seconds |
See Tiers and margins for how tiers price and limit usage.
Usage
mrl usage account
JSON schema lint
Check a JSON schema for provider compatibility before using it for structured output or tool parameters:
mrl schema lint ./schema.json
mrl schema lint ./schema.json --provider openai
mrl schema lint ./tool-schema.json --provider openai --tool-schema
cat schema.json | mrl schema lint -
--provider accepts openai, anthropic, googleai, or xai. --tool-schema validates the schema as tool parameters (OpenAI only).
Output formats
Table output is the default. Use --json for machine-readable output, or set output = "json" in the profile:
mrl customer list --json
mrl model list --json
Global flags
These flags work with every command:
| Flag | Description |
|---|---|
--profile |
Config profile |
--api-key |
Secret API key (mr_sk_*) |
--token |
Account token (from mrl auth login) |
--project |
Project UUID |
--base-url |
API base URL |
--json |
Output JSON |
--timeout |
Request timeout (default 30s) |