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/cli

That installs baz (with bazantic and bazantic-cli as aliases).

Sign in

baz login
baz whoami        # account + scopes

baz 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 \
  --json

Bazantic 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.com

An 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-stdin

An 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.

OptionMeaning
--spec-urlOpenAPI or OpenRPC document. Must be reachable from Bazantic's servers and declare at least one operation.
--spec-fileThe same document, from a local file. The limit is 4 MB. Use one of --spec-url and --spec-file.
--endpointYour API's base URL. https only — the gateway forwards a credential to it, so a plaintext hop is refused.
--nameListing name. Defaults to one derived from the spec.
--auth-typeHow 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-deliveryWhere the credential goes on each upstream call: url, header, bearer, or query. Defaults to url.
--auth-paramThe header name for header delivery, or the query parameter for query delivery. Required for those two, and refused for the others.
--token-stdinRead 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-urloauth2 only: the provider's token endpoint. Required with --auth-type oauth2.
--client-idoauth2 only: the client id. Required with --auth-type oauth2.
--client-secretoauth2 only: the client secret. Required with --auth-type oauth2. The gateway exchanges it for a token at request time.
--scopesoauth2 only: comma-separated scopes. Optional.
--headerA 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.
--statusdraft or active. The default is active. A draft serves no traffic.
--accessowner 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.
--jsonPrint 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 active

Use 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, send base64(user:password). For oauth2, 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> --clear

The 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 owner

Change 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 owner to public exposes 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 to owner, 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 --json shows accessMode for 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
CommandWhat 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 --json

Use --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-gateway

A 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]
FlagMeaning
--yesApply without the prompt.
--jsonPrint 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.json

spec set replaces the stored spec. Give one of --spec-file and --spec-url.

  • --spec-file sends 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_spec for a document that is not a spec, and spec_unreachable for 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_change and 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.

FlagMeaning
--yesApply the route change without the prompt.
--jsonPrint 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.

CommandPurpose
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_bindings

An 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 block to an object to attach or replace the manifest.
  • Set block to null to 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.

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, cursor

fetch 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 cursor

Run 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_tools

The 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 --json

Every price, cap, and ceiling uses USD units. The CLI pays on three rails:

RailNetwork and tokenTestnet and token
Basebase, USDCbase-sepolia, USDC
Tempo (MPP)tempo, USDC.etempo-moderato, AlphaUSD
Solanasolana, USDCsolana-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, or solana-devnet. With no --network and no network in 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-amount defaults to 0.01, which is also the common per-call price. The ceiling is inclusive, so a call priced at exactly 0.01 goes through — raise it only for a route you know costs more.
  • --yes skips the payment confirmation. The ceiling is still enforced.
  • Use --yes only 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 curl then pays on Base Sepolia. A testnet holds no real money, so the CLI asks for no confirmation. With an explicit --network that the 402 does not offer, baz curl stops and names the network the 402 offered.
  • A standard or broad grant supports Base and Base Sepolia with one shared cap. Use the same --account for 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-service for a broad external grant. An HTTPS --service value requires --name, --cap, --recipient, --network, and --max-per-request.
  • --verbose prints 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. --json prints neither line. --verbose does not print the 402 challenge. Use baz check to 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.json

baz 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 wallet

baz 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, recipient

With 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}/mcp with a JSON-RPC tools/list request 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

VariableWhat it does
BAZANTIC_GATEWAY_PRIVATE_KEYAn EVM private key that pays in place of the EVM key of the wallet file. No Solana equivalent exists.
BAZANTIC_GATEWAY_PASSPHRASEThe 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_KEYThe PEM private key of one grant. Use it to pay with one grant in a headless environment.
BAZANTIC_GATEWAY_RPC_URLThe EVM RPC for wallet balance and for a Tempo payment. The default is a public RPC of the chain.
SOLANA_RPC_URLThe 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_URLThe catalog for baz search and baz mcp: pre, prd, or a URL. The default is prd.
BAZANTIC_CONFIG_DIRThe directory for config.json, the wallet and the grant keys. The default is ~/.bazantic.
BAZANTIC_NO_UPDATE_CHECKStops 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 newer

baz 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, or GH_NO_UPDATE_NOTIFIER is set.
  • The command has --no-update-notifier or --json.
  • The CI variable is set.
  • stderr is not a terminal.