Command line (baz)
Sign in, manage gateways and Recipes, and make paid calls from a terminal or agent.
The Bazantic CLI manages your gateways and Recipes. It also makes paid calls to any gateway.
Management commands support --json. Paid calls also support --json.
npm i -g @bazantic/cliThat installs baz (with bazantic and bazantic-cli as aliases).
Sign in
baz login
baz whoami # account + scopesbaz login prints an approval URL and waits for you to approve it in a browser. It opens the
browser for you only when the terminal is interactive — under a pipe or in CI it prints the
URL and waits, which is what you want from a script.
Gateway and Recipe management need a session. Paid calls do not need one. A self-custody wallet works without a Bazantic account.
Register a gateway
You need an OpenAPI or OpenRPC document and your API's base URL.
baz gateway add \
--spec-url https://api.example.com/openapi.json \
--endpoint https://api.example.com \
--name "Example API" \
--status draft \
--jsonBazantic fetches and parses the spec server-side, then generates the listing and the x402
and MPP payment pathways. The result gives you the gateway's slug and an mcpUrl.
If your spec is not published, send it from a file. The CLI sends the document in the request, and the server parses it. No URL is fetched.
baz gateway add \
--spec-file ./openapi.json \
--endpoint https://api.example.comAn upstream that needs a key takes the key from stdin, and the delivery flags say where the gateway puts it on each call:
printf %s "$PROVIDER_KEY" | baz gateway add \
--spec-url https://api.example.com/openapi.json \
--endpoint https://api.example.com \
--auth-type api-key --auth-delivery header --auth-param x-api-key \
--token-stdinAn MCP server is generated only when the spec format and the protocol detected from it pair
up — OpenAPI with a REST service, or OpenRPC with a JSON-RPC one. mcpUrl comes back either
way, so confirm the server is really there with a tools/list call before handing the URL to
anyone.
| Option | Meaning |
|---|---|
--spec-url | OpenAPI or OpenRPC document. Must be reachable from Bazantic's servers and declare at least one operation. |
--spec-file | The same document, from a local file. The limit is 4 MB. Use one of --spec-url and --spec-file. |
--endpoint | Your API's base URL. https only — the gateway forwards a credential to it, so a plaintext hop is refused. |
--name | Listing name. Defaults to one derived from the spec. |
--auth-type | How the gateway authenticates to your API: api-key, basic, oauth2, or none. Defaults to none, the "needs no key" case. The CLI also accepts x402-mpp and jwt, but Bazantic retired both. x402-mpp forwards no credential. The dashboard does not offer jwt, and the gateway does not serve a listing of that type. For a bearer token, use api-key with --auth-delivery bearer. |
--auth-delivery | Where the credential goes on each upstream call: url, header, bearer, or query. Defaults to url. |
--auth-param | The header name for header delivery, or the query parameter for query delivery. Required for those two, and refused for the others. |
--token-stdin | Read the credential from stdin, so it stays out of argv, shell history and ps. The CLI reads a credential from nowhere else. The CLI refuses this flag with none and x402-mpp, which forward no credential. It also refuses it with oauth2, which takes --client-secret. |
--token-url | oauth2 only: the provider's token endpoint. Required with --auth-type oauth2. |
--client-id | oauth2 only: the client id. Required with --auth-type oauth2. |
--client-secret | oauth2 only: the client secret. Required with --auth-type oauth2. The gateway exchanges it for a token at request time. |
--scopes | oauth2 only: comma-separated scopes. Optional. |
--header | A header that your API requires on every call, as "<name>: <value>", for example "Accept-Version: v1". Repeat the flag for more headers. The gateway stores these as plain text. Put a key in the credential, not in a header. |
--status | draft or active. The default is active. A draft serves no traffic. |
--access | owner or public. The default is public. owner admits only a caller with an identity of your account. The webapp saves the mode with the draft, before activation, so the gateway never serves as public. See Set who may call a gateway. |
--json | Print one line: { ok, id, slug, mcpUrl }. |
gateway add refuses an option that it does not know, an option that you give twice, and an option with no value. It sends no request.
A spec Bazantic can't reach will fail here
--spec-url is fetched by the server, not by your machine. A spec on localhost, behind a
VPN, or behind auth returns spec rejected: could not fetch --spec-url even though the URL
works in your own browser.
Every method discovered in the spec starts at a default price. Set real per-method prices in the dashboard after registration.
Omit --status to create an active gateway. Use --status draft to review a gateway before it
serves traffic. Activate a ready draft after inspection:
baz gateway list --json
baz gateway activate example-api
# gateway example-api
# status activeUse baz gateway list --json again to verify the persistent state. Activation checks the saved
methods, specification, credential, and payout setup. A failed check keeps the gateway in draft
or paused, and prints the server error code with the corrective message.
If activation fails after gateway add creates the gateway, the gateway stays a draft. The CLI prints the reason code and how to fix it. gateway activate prints them in the same way.
A declarative alternative — one bazantic.yaml file, with plan and apply — is in
design review; see Gateway manifest.
Set the credential and the required headers
A gateway with --auth-type api-key, basic or oauth2 cannot activate without a
credential. You can create it first and add the key later:
baz gateway add --spec-file ./openapi.json --endpoint https://api.example.com \
--auth-type api-key --auth-delivery header --auth-param X-Api-Key \
--status draft
printf %s "$PROVIDER_KEY" | baz gateway credential set <slug>
baz gateway activate <slug>credential set replaces the stored credential. Use it again to rotate a key. The gateway
keeps its slug and its URL.
If the key on stdin matches the stored key, the command prints credential unchanged and writes nothing. Otherwise it prints credential updated. With --json, the credential field is rotated or unchanged.
- The credential comes only from stdin. The command takes no flag for it.
- An empty value or a terminal on stdin stops the command before it sends a request.
- For
basic, sendbase64(user:password). Foroauth2, send the client secret. - The command does not change the auth type or the delivery. The dashboard changes those.
headers set replaces the full set of required headers. --clear removes all of them.
baz gateway headers set <slug> --header "Accept-Version: v1"
baz gateway headers set <slug> --clearThe server refuses a header that the gateway sets itself, such as Authorization or Host.
It also refuses a header with the name of the credential header.
Both commands write configuration only. They do not test the connection. activate tests the
connection of a draft. An active gateway uses the new values on its next reload, with no test.
Make a call after a change to an active gateway.
A change from credential set or headers set does not change the listing name, description, category or tags.
Set who may call a gateway
A gateway has an access mode. public admits any caller, and charges the listed price. owner admits only a
caller with an identity of the account that owns the gateway. The gateway refuses every
other caller before payment and before your API: 401 with no identity, and 403 for
another account.
Use owner for an API that only your own services call. Set it when you create the
gateway, so that the gateway never serves as public. A gateway created with a credential
and no --access is public, and gateway add prints a note that names --access owner:
printf %s "$PROVIDER_KEY" | baz gateway add --spec-file ./openapi.json \
--endpoint https://api.example.com \
--auth-type api-key --auth-delivery bearer --token-stdin \
--access ownerChange the mode of an existing gateway with gateway access:
baz gateway access <slug> owner
# gateway <slug>
# access owner
baz gateway access <slug> public- The command writes through the same function as the Gateway access control in the dashboard, with the same checks.
- The change is material. It lapses the marketplace verification of the gateway, as the same change in the dashboard does. The command prints a line when this occurs.
- A change from
ownertopublicexposes your API to every caller at once, so the command asks for confirmation first. Without a terminal, or with--json, that change needs--yes. A change toowner, and the same mode again, do not ask. - The same mode again writes nothing and prints
(unchanged). - With
--json, the command prints{ ok, slug, accessMode, changed, verificationLapsed }. baz gateway list --jsonshowsaccessModefor each gateway.
Put a custom domain on a gateway
baz gateway domains drives the whole custom-domain lifecycle. Add the hostname, create
the two DNS records the CLI prints, then verify.
baz gateway domains add my-gateway api.acme.com
# hostname api.acme.com
# status pending_ownership
#
# Type Host Value
# TXT _baz-challenge.api.acme.com baz-verify=api.acme.com,<token>
# CNAME api.acme.com bazgateway.com
# create both records at your DNS provider, then:
baz gateway domains verify my-gateway| Command | What it does |
|---|---|
gateway domains add <slug> <hostname> | Claims the hostname and prints the TXT and CNAME records to create. |
gateway domains status <slug> | Prints the status, the state of each record, the failure reason, and the last check time. |
gateway domains verify <slug> | Runs the DNS and certificate checks now. Limited to six attempts each hour for each hostname. |
gateway domains rm <slug> [--yes] | Releases the hostname. It prompts first unless you pass --yes. |
The status moves through pending_ownership, pending_dns, and pending_cert to
active. A failed check prints one reason code, such as cname_proxied. Bazantic also
re-checks a pending domain for you every few minutes, so status is enough to follow
progress.
rm removes the Bazantic record only. Delete the CNAME at your DNS provider too — a
record that still points at Bazantic can be claimed by someone else.
The full walkthrough, the reason codes, and the certificate steps are in Custom domains.
Check the gateways you own
baz gateway list --jsonUse --json. The plain listing prints only slug, name and status — it does not
include the gateway's URL, so it can't tell you what to call. The JSON form returns full
rows: slug, name, status, category, endpointUrl, an mcp flag, and deployment
timestamps.
mcp is eligibility, not liveness: it says a server can be generated from this
gateway's spec, not that one is deployed and answering. Probe /mcp to learn the latter.
# slug, status and callable URL as a table
baz gateway list --json | jq -r '.listings[] | [.slug, .status, .endpointUrl] | @tsv'Activate or resume a ready gateway with baz gateway activate <slug> [--json]. The JSON result
is { "ok": true, "slug": "...", "status": "active" }.
Before it writes active, the server probes your upstream with the stored credential, the
same way the connection test in the dashboard does. If the probe does not pass, the command
fails with connection_test_failed, the probe verdict, and the HTTP status when there is
one. Correct the connection and retry. If your upstream refuses the probe's request but
serves real traffic, rerun with --acknowledge-connection-test to activate anyway. The
server records that override.
A gateway that authenticates to its upstream with OAuth 2.0 is not probed. The secret it stores is a client secret, which the gateway exchanges for a short-lived access token each time the token expires. No probe can present a client secret to your API, so the server skips the check and activates. Every other authentication method is probed.
Read the URL, never build it
Take endpointUrl from this listing (or from the Overview tab in the dashboard) rather
than assembling a URL by hand. Every upstream path hangs off it verbatim, and the MCP
server is always endpointUrl + /mcp.
Match the routes to the spec
baz gateway resync my-gatewayA gateway has two things derived from one spec, by two different paths. Its MCP tools are compiled from the spec itself. Its paid routes come from a table that changes only when a save sends one. So replacing the spec moves the tools and leaves the routes, and the new tools answer 404 — with no payment challenge, which reads as a broken gateway rather than a stale one.
resync prints the difference and applies it on one confirmation:
Adding (2)
GET /v1/quote $0.01
POST /v1/swap $0.01
Removing (1)
these routes stop serving and stop earning
GET /v1/legacy $0.02
Unchanged (1)
prices are unchanged
GET /v1/price $0.05
Apply these route changes to my-gateway? [y/N]| Flag | Meaning |
|---|---|
--yes | Apply without the prompt. |
--json | Print the change as JSON and write nothing. |
A route in both sets keeps the price you set; only a genuinely new route takes the default. The command applies every change or none — there is no per-route choice. Routes that already match the spec print one line and write nothing.
The dashboard shows you the same list
Replacing a spec in the dashboard stops the save and shows this difference before it writes, and a gateway whose routes already trail its spec says so on its own page. The two surfaces read the same rule, so it does not matter which one you use.
Replace the spec of a gateway
baz gateway spec set my-gateway --spec-file ./openapi.yaml
baz gateway spec set my-gateway --spec-url https://example.com/openapi.jsonspec set replaces the stored spec. Give one of --spec-file and --spec-url.
--spec-filesends a local OpenAPI or OpenRPC document. The limit is 4 MB.- The command refuses
--spec-file -. Stdin is reserved for the credential. - The server checks the document before it stores it. It answers
invalid_specfor a document that is not a spec, andspec_unreachablefor a URL that it cannot fetch. - The server refuses a spec of another protocol, for example an OpenRPC document for a REST gateway. It answers
protocol_changeand stores nothing. Register a new gateway for the other protocol.
After the write, the command prints the same route change as resync and applies it on one
confirmation. The MCP tools follow the new spec on the next reload of the gateway. The paid
routes change only when you apply the route change.
| Flag | Meaning |
|---|---|
--yes | Apply the route change without the prompt. |
--json | Print one line: { ok, slug, status, specType, diff, routes }. Without --yes, write no routes. |
A script or a CI job has no terminal for the prompt. Give --yes or --json there. Without
one of them, the command refuses before it sends a request.
routes is applied, unchanged or pending. If you refuse the prompt, the new spec stays
and the routes do not change. Run baz gateway resync <slug> to apply them later.
If a step after the spec write fails, the error says that the spec is replaced and names
baz gateway resync <slug>. With --json, the command prints
{ ok: false, slug, specReplaced: true, specType, error } and exits 1.
If the spec write gets no answer, for example after a timeout, the spec may be stored. The
error says so and names resync, which shows the routes against the stored spec. With
--json, specReplaced is "unknown".
Manage Recipes
Run baz login before a Recipe management command. A new session has recipe:read and recipe:write scopes.
Run baz login again if an old session does not have Recipe scopes.
| Command | Purpose |
|---|---|
baz recipe list [--json] | List Recipes that the selected account owns. |
baz recipe get <handle> [--json] | Get one Recipe that the selected account owns. |
baz recipe create <file> [--json] | Create a draft from a strict JSON file. |
baz recipe update <handle> <file> [--json] | Update a draft from a strict partial JSON file. |
baz recipe publish <handle> [--json] | Publish the current draft revision. |
baz recipe unpublish <handle> [--json] | Return a published Recipe to draft state. |
baz recipe delete <handle> [--yes] [--json] | Delete a never-published draft after confirmation. |
List and get require recipe:read. Create, update, publish, unpublish, and delete require recipe:write.
A create file contains these eight fields, and the optional block field:
name
description
input_schema
input_example
output_example
prompt_template
model
tool_bindingsAn update file contains a nonempty subset of the same fields. Unknown fields cause an error before a network request.
block holds a Creator Mode block manifest:
- Set
blockto an object to attach or replace the manifest. - Set
blocktonullto remove the manifest. - If an update file omits
block, the stored manifest does not change.
The compact UTF-8 JSON for a control definition cannot exceed 24 KiB. This limit includes the block manifest. Update applies this limit after it merges the patch.
Neither file accepts a handle, owner, account, status, timestamp, or generation field. Bazantic derives an immutable handle from name.
Each tool binding has gateway_slug and tool_name fields only. A Recipe can have from 1 through 64 unique tool bindings.
prompt_template contains exactly one {{inputs}} placeholder. input_schema uses JSON Schema Draft 2020-12 and local references.
Run baz recipe --help for the model values and a complete create file.
Create produces a draft. Update works only on a draft.
Publish reads bounded Recipe metadata for updated_at and validates live tool bindings. Unpublish returns the Recipe to draft state.
Delete works only on a never-published draft. Delete also refuses a draft that has a published revision. Interactive delete asks for confirmation. Noninteractive and --json delete require --yes.
The CLI has no Recipe transfer, compose, generate, test, or draft-run command.
Paid calls in an MCP client
baz mcp gives an agent three tools with no Recipe installed: search (the public catalog),
check (the offers in a 402, paid by nobody) and fetch (the request, with its 402 paid).
baz mcp install --client claude-code # or: codex, cursorfetch pays from this device's payer and never prompts. It refuses a payment above the
ceiling: --max-amount in the entry's arguments, else maxAmountUsd in the config, else
0.01. Its max_amount argument can lower the ceiling for one call, never raise it.
--budget <usdc> caps the total that the server pays while it runs.
--catalog pre|prd|<url> selects the catalog that search reads. The default is
BAZANTIC_CATALOG_URL, else prd.
The server never asks for a passphrase. A wallet with a passphrase needs
BAZANTIC_GATEWAY_PASSPHRASE in the environment of the server.
Recipe tools in an MCP client
Install one dynamic Recipe MCP server:
baz recipe install --client claude-code
baz recipe install --client codex
baz recipe install --client cursorRun only the command for your client. baz recipe mcp then joins public Recipe tools with authorized control tools.
The API hosts /control-mcp. The webapp issues its CLI sessions, and the API validates each session.
Current control tools are:
bazantic_recipe_list
bazantic_recipe_get
bazantic_recipe_create
bazantic_recipe_update
bazantic_recipe_delete
bazantic_recipe_publish
bazantic_recipe_unpublish
bazantic_marketplace_search
bazantic_gateway_list_owned
bazantic_gateway_list_toolsThe marketplace tool returns active, owner-published, Bazantic-verified services. The owned-gateway tool returns safe data for non-retired account gateways.
Both tools return at most four rows. Pass each next_offset value as offset until it is null.
Discovery rows omit descriptions, tags, URLs, timestamps, secrets, and raw specifications.
The live inventory tool reads one eligible gateway. It returns tool names, descriptions, input schemas, annotations, and an availability state.
The selected account must own that gateway, or the verified marketplace must expose it. All three gateway tools require gateway:read.
Control tools use the CLI session and do not use x402. Published Recipe calls still use the paid Recipe gateway.
Without a valid CLI session, the MCP server lists and calls public Recipes only. Published Recipe calls still require a payment source.
Make a paid call
Two payers, and only two: a grant (capped, revocable authority over your Bazantic-hosted balance) or a self-custody wallet you hold and fund. Prefer a grant.
baz grant create --name agent-1 --cap 5
baz curl https://<your-gateway>/<path> --account agent-1 --max-amount 0.02 --jsonEvery price, cap, and ceiling uses USD units. The CLI pays on three rails:
| Rail | Network and token | Testnet and token |
|---|---|---|
| Base | base, USDC | base-sepolia, USDC |
| Tempo (MPP) | tempo, USDC.e | tempo-moderato, AlphaUSD |
| Solana | solana, USDC | solana-devnet, USDC |
A grant pays on Base and Base Sepolia only. Tempo and Solana need the self-custody wallet
(--account wallet).
The wallet holds up to two keys: one EVM key and one Solana key. The 402 selects the key. A
Solana offer is paid by the Solana key. A Base or Tempo offer is paid by the EVM key.
--account <name>picks the grant that pays. Required once you have more than one.--network <name>selects the network:base,base-sepolia,tempo,tempo-moderato,solana, orsolana-devnet. With no--networkand nonetworkin the config, the CLI selects a default. On a production gateway, a grant or an EVM key pays on Base, and a Solana key pays on Solana. When the 402 offers both and the wallet holds both keys, the EVM key pays. A preview gateway uses the testnet of the same rail.--max-amountdefaults to0.01, which is also the common per-call price. The ceiling is inclusive, so a call priced at exactly0.01goes through — raise it only for a route you know costs more.--yesskips the payment confirmation. The ceiling is still enforced.- Use
--yesonly for a task that the user approved for unattended execution. - The per-call ceiling is not a task budget. The grant cap limits total authorized spend.
- A gateway in sandbox mode answers with a 402 that
offers Base Sepolia only, whatever its hostname is. With no
--network,baz curlthen pays on Base Sepolia. A testnet holds no real money, so the CLI asks for no confirmation. With an explicit--networkthat the 402 does not offer,baz curlstops and names the network the 402 offered. - A standard or broad grant supports Base and Base Sepolia with one shared cap. Use the same
--accountfor live and sandbox gateways. Fund the wallet with test USDC on Base Sepolia for sandbox calls. The gateway selects the payment network for these scopes. - A standard grant pays active Bazantic gateway recipients. Use
--any-servicefor a broad external grant. An HTTPS--servicevalue requires--name,--cap,--recipient,--network, and--max-per-request. --verboseprints up to two lines to stderr after a paid call. The first line gives the amount and the payer address. The second line gives the payment receipt when the payment has one.--jsonprints neither line.--verbosedoes not print the 402 challenge. Usebaz checkto read the offers in a 402.
--json returns one object — { ok, status, paid, body } — so the upstream payload is
.body, not the whole document, and paid already carries transaction, network and
explorerUrl without --verbose. Drop --json and stdout is the upstream body verbatim,
which is the form you want when redirecting to a file:
baz curl https://<your-gateway>/<path> --account agent-1 > response.jsonbaz curl reads the common curl flags the way curl reads them: -X, -H, -d,
--data-raw, --data-binary, --data-urlencode, --json <body>, -G, -A, -u,
--oauth2-bearer, -b, -e, -I, -o, -O, -i, -f, --fail-with-body and -w. Put
baz in front of a curl command and the command pays. --json followed by {, [ or @
is the curl JSON body. --json alone is the structured output above.
A curl flag that changes how curl runs, and not what it sends, has no effect, and
baz curl writes a note to stderr for it. These flags include -k, -L, --max-time,
--retry and --http2. baz always verifies TLS, never follows a redirect, and never
retries. -s stops the notes. A flag that changes the request in a way baz cannot do stops
the command before it sends anything or pays, with exit code 2. These flags include -F,
-T, --proxy, --cert and --digest, and any flag that curl does not know.
baz grant create needs a human: it prints an approval URL and waits while you approve it in
a browser, cross-checking the device fingerprint it shows. See
Spend grants for the full walkthrough — the approval flow, how a grant
connects to your Bazantic balance, and how to scope, list, and revoke one.
Check the response body
The gateway does not settle a provider HTTP error. Some APIs report application errors
with HTTP 200. Such a response can be chargeable. Check the body and the status.
Check your payment setup
baz grant list --json # this device's credentials: cap, network, scope, expiry, status
baz wallet balance --json # the USDC balance of each key in the self-custody walletbaz grant list asks the server for each credential's real status, so a grant revoked from
the dashboard shows up here. Offline, it falls back to local expiry data and marks the row
unverified. There is no spend total — track that as calls × price.
Inspect a gateway before a call
Find a gateway and read the price of a route. Neither command needs a wallet, a grant or a login:
baz search "air quality" # the public catalog
baz check https://<your-gateway>/<path> # the offers in the 402: amount, network, recipientWith no query, baz search lists the whole catalog. --limit <n> shows at most n results.
--catalog pre|prd|<url> selects the catalog. The default is BAZANTIC_CATALOG_URL, else prd.
baz check sends the request once, with no payment, and pays nothing. A free route answers
normally, so a check of a free POST runs that POST. baz curl <url> --dry-run is the same
command.
Use the declared machine resources before you call an upstream method:
- List the tools.
POST {endpointUrl}/mcpwith a JSON-RPCtools/listrequest returns each operation and its parameters. - Read the specification. The service page links its OpenAPI or OpenRPC document.
- Read the agent card. An MCP service page links its A2A agent card.
These reads are free. A tools/call request can invoke a free upstream method. Get approval
and inspect the price before a tool call.
Command summary
baz login | logout | whoami session (identity only, no money)
baz gateway add | list | activate your gateways (requires login)
baz gateway resync <slug> match routes to the stored spec
baz gateway credential set <slug> replace the upstream credential (stdin)
baz gateway headers set <slug> replace the required upstream headers
baz gateway spec set <slug> replace the spec, then apply the route change
baz gateway domains <cmd> <slug> a gateway's custom domain: add | status | verify | rm
baz recipe <cmd> Recipe lifecycle: list | get | create | update | publish | unpublish | delete
baz recipe install | mcp install or run the composite Recipe MCP server
baz mcp [install] install or run the pay MCP server: search, check, fetch
baz search [query] find gateways in the public catalog
baz check <url> list the offers in a 402; pay nothing
baz curl <url> [options] make a request; settle the 402 automatically
baz wallet new [--solana] add a key to the wallet: an EVM key, or a Solana key
baz wallet import [--key-file <f>] import an EVM key (a hidden prompt without --key-file)
baz wallet import --solana <file> import a solana-keygen JSON key file
baz wallet import --from-wallet <f> copy the keys of another baz wallet file, still encrypted
baz wallet address print the address of each key
baz wallet balance [--network <n>] print the USDC balance of each key
baz grant create | list create a grant, or list the grants of this device
baz grant revoke <name> [--yes] [--json] revoke a grant
baz update [--check] [--to <version>] [--json] update the CLI (alias: baz upgrade)wallet new and wallet import take --passphrase-stdin or --unprotected. A run with no
terminal must use one of these flags, or set BAZANTIC_GATEWAY_PASSPHRASE. One passphrase
protects the whole wallet, and the first key sets it.
wallet new and wallet import fill the slot of their kind and keep the other key. They
refuse to overwrite a key of the same kind. --replace overwrites it and deletes the old
key, so keep a copy of a funded key first. A key added beside a kept key uses the wallet
passphrase. The command asks for it, checks it against the kept key, and writes nothing when
it is wrong. A protection flag that does not match the wallet is refused. --from-wallet asks
for the passphrase of the source file, encrypts the keys with this wallet's passphrase, and
requires each key to own its stored address.
A wallet file from an earlier CLI version keeps working. A wallet with two keys keeps a copy of the EVM key in the earlier format, so CLI 0.11.0 and older see and pay with the EVM key only. Upgrade every CLI install to use the Solana key from all of them.
grant revoke asks for confirmation. A run with no terminal must pass --yes.
Configuration lives in ~/.bazantic/config.json (mode 0600). Its gateway block takes
account, network and maxAmountUsd, so everyday calls need fewer flags. account takes a
grant name, or wallet for the self-custody wallet. A flag always wins over the file.
For headless and CI use, inject secrets through the environment. Do not put private keys,
device keys, passphrases, or session tokens in prompts, logs, command arguments, or source
files. Do not print ~/.bazantic/config.json.
Environment variables
| Variable | What it does |
|---|---|
BAZANTIC_GATEWAY_PRIVATE_KEY | An EVM private key that pays in place of the EVM key of the wallet file. No Solana equivalent exists. |
BAZANTIC_GATEWAY_PASSPHRASE | The wallet passphrase. It unlocks the wallet with no prompt. wallet new and wallet import use it to set the passphrase of a new wallet, or to check the passphrase of an existing one. |
BAZANTIC_GATEWAY_DEVICE_KEY | The PEM private key of one grant. Use it to pay with one grant in a headless environment. |
BAZANTIC_GATEWAY_RPC_URL | The EVM RPC for wallet balance and for a Tempo payment. The default is a public RPC of the chain. |
SOLANA_RPC_URL | The Solana RPC for a Solana payment and for wallet balance. The default is the public RPC of the network: https://api.mainnet-beta.solana.com for solana, and https://api.devnet.solana.com for solana-devnet. |
BAZANTIC_CATALOG_URL | The catalog for baz search and baz mcp: pre, prd, or a URL. The default is prd. |
BAZANTIC_CONFIG_DIR | The directory for config.json, the wallet and the grant keys. The default is ~/.bazantic. |
BAZANTIC_NO_UPDATE_CHECK | Stops the update check. NO_UPDATE_NOTIFIER and GH_NO_UPDATE_NOTIFIER do the same. |
Update the CLI
baz update # install the latest version
baz update --check # print the current and the latest version; install nothing
baz update --to <version> # install an exact version, older or newerbaz upgrade is an alias of baz update. Use --to to return to an earlier version after a
bad release. --json prints a structured result.
baz update installs through the package manager that installed the CLI: npm, pnpm, yarn, or
bun. It never runs sudo. If a global install needs elevation, the command fails and prints the
command to run. baz update does not install under npx or in a source checkout. In both cases,
baz update --check still prints the latest version.
The CLI checks npm for a new version once in 24 hours, in a background process. No command waits
for the check. When a newer version exists, baz prints one line to stderr when the command ends.
The CLI skips the check in these conditions:
BAZANTIC_NO_UPDATE_CHECK,NO_UPDATE_NOTIFIER, orGH_NO_UPDATE_NOTIFIERis set.- The command has
--no-update-notifieror--json. - The
CIvariable is set. - stderr is not a terminal.