@anyway-sh/cli
v0.4.2
Published
Anyway CLI — terminal interface for the Anyway merchant platform
Readme
Anyway CLI
Terminal interface for the Anyway merchant platform. Manage products, payment links, orders, and more — directly from your terminal or agent environment.
Installation
npm install -g @anyway-sh/cliOr use without installing:
npx @anyway-sh/cli <command>Quick Start
# Authenticate (opens browser)
anyway login
# Create a product with payment link
anyway products create --name "My Product" --price 29.99
# Get JSON output (for agent/automation use)
anyway products create --name "My Product" --price 29.99 --format jsonAuthentication
anyway login # Open browser to authenticate
anyway logout # Clear stored credentials
anyway whoami # Show current session infoFirst-time login opens a browser window to complete authentication. Credentials are stored at ~/.anyway/credentials.json and auto-refreshed.
For environments without a browser, the login page will display a token you can paste back into the terminal.
Commands
products
anyway products list
anyway products list --status active --page 1 --size 20
anyway products get <productId>
anyway products create --name <name> --price <amount> [--currency usd] [--description <desc>]
anyway products create --name <name> --price <amount> --type recurring --interval month
anyway products update <productId> --name <name> [--description <desc>]
anyway products archive <productId>
anyway products publish <productId>
anyway products payment-links <productId>Creating a product automatically creates a payment link. The payment link URL is returned in the output.
orders
anyway orders list
anyway orders list --status paid --page 1 --size 20
anyway orders list --product <productId> --from 2024-01-01 --to 2024-12-31wallets
anyway wallets balance
anyway wallets transactions
anyway wallets transactions --limit 50wallets agents
Delegated wallet records for agent runtimes. This CLI currently creates, lists, and verifies agent wallet records in the public command surface. Up to 5 agent wallets per merchant.
Create
Create hands off to the browser for Privy MFA.
# First time (count must be 0).
anyway init wallets --type agent --name "My Research Agent"
# Add another (count must be >=1).
anyway wallets agents create --name "Pricing Bot"Read
# List all agent wallets — table or JSON.
anyway wallets agents list
anyway wallets agents list --format json
# Policies for the selected agent wallet.
anyway wallets agents policies [<agentId>]
# Recent activity for the selected agent wallet (max 200, default 50).
anyway wallets agents history [<agentId>] [--limit N]agentId is only the server-side identifier for an agent wallet. Get it from
anyway wallets agents list or the dashboard's agent wallet details. It is
safe to print in command output, but it is not a credential and cannot
authorize wallet operations by itself.
Non-interactive (CI / agents)
Setup always requires a browser + human confirmation (Privy MFA). For
environments without a local browser, create accepts --non-interactive
(also auto-detected when stdin isn't a TTY): the CLI prints the dashboard
URL and exits.
anyway wallets agents create --non-interactive --name "Pricing Bot"dashboard
anyway dashboard templates
anyway dashboard query <templateId>
anyway dashboard query <templateId> --days 30traces
anyway traces status
anyway traces list
anyway traces list --limit 50developer
anyway developer keys list
anyway developer keys list --type sdk_key
anyway developer keys create --name <name>
anyway developer keys delete <keyId>Global Options
| Option | Values | Default | Description |
| ----------- | ------------------------------------- | ------- | ------------------------------------------------------------------------------------ |
| --env | prod, sandbox, dev, dev-local | prod | Target environment |
| --format | table, json, csv | table | Output format |
| --timeout | 10s, 500ms, 2m, 30 (bare = s) | (off) | Hard deadline. On timeout, exits 4 with a TIMEOUT error. Recommended for probes. |
Agent / Automation Usage
All commands return non-zero exit codes on failure so shell pipelines and probes can detect errors via $?.
The following commands support --format json for machine-readable output on stdout:
| Command | --format json |
| ----------------------------- | --------------- |
| whoami | ✅ |
| products list / get / create / payment-links | ✅ |
| orders list | ✅ |
| wallets balance / transactions | ✅ |
| wallets agents list / policies / history | ✅ |
| dashboard templates / query | ✅ |
| traces status / list | ✅ |
| developer keys list / create / delete | ✅ |
| login --token (success and failure) | ✅ |
Commands not emitting JSON (still human-readable text only): login (browser flow), logout, init, update, products archive / publish, products update.
# Create product and capture output
result=$(anyway products create --name "API Product" --price 49.99 --format json)
payment_link=$(echo $result | jq -r '.paymentLink.paymentLinkUrl')
# List orders as CSV
anyway orders list --format csv > orders.csvMonetary values
To avoid agents / probes misreading raw on-chain amounts (USDC uses 6 on-chain decimals, i.e. 1 USDC = 1_000_000 raw units):
- Transaction/order amounts (
orders list,wallets balance,wallets transactions,products.paymentLinks[].amount) are always in major units (human-readable decimals, e.g.0.5USDC, not500000). Each row carries an explicitcurrencyfield. dashboard queryrows are raw aggregates returned by the backend — columns are unit-less numbers and the currency metadata lives on the template (fetch viadashboard templatesfirst). Agents should look up the template'srender.spec.items[].formatand the org's default currency before interpreting values.
Structured error output
When a command with --format json fails, stdout is a single JSON object:
{"success": false, "error": {"message": "<human-readable reason>", "code": "<ERR_CODE>"}}Parse .success (or check $?) to detect failure; read .error.message for diagnostics and .error.code to route alerts. Shell callers that don't want to parse JSON can use $? alone — each error code maps to a dedicated exit code:
| Exit | error.code | Meaning |
| ---- | ----------------------------------- | ----------------------------------------------- |
| 0 | — | Success |
| 1 | UNKNOWN | Uncategorised failure (fallback) |
| 2 | VALIDATION | Bad CLI args / missing required input |
| 3 | AUTH_NOT_LOGGED_IN / AUTH_EXPIRED / AUTH_FAILED | Not logged in, session expired, or 401/403 |
| 4 | TIMEOUT | --timeout deadline reached |
| 5 | NETWORK | DNS, TLS, ECONNREFUSED, ECONNRESET, etc. |
| 6 | SERVER_5XX | Upstream returned 5xx |
| 7 | RATE_LIMITED | HTTP 429 |
| 8 | CLIENT_4XX | Other 4xx (not auth / not rate-limited) |
Example routing:
anyway products list --format json --timeout 10s
case $? in
0) echo "ok" ;;
3) pagerduty "auth expired" ;;
4|5) pagerduty "network / cli unreachable" ;;
6|7) pagerduty "upstream degraded" ;;
*) pagerduty "cli unknown failure" ;;
esacTrace output for synthetic monitoring
Set ANYWAY_TRACE=1 to emit one JSON Lines event per lifecycle step and per outgoing HTTPS request to anyway.sh. Default sink is stderr (stdout keeps the command's normal output):
anyway whoami --format json 2> trace.log | jq .emailExample trace (comments added for clarity, each line is one JSONL event):
{"v":1,"ts":...,"t":"start","cliVersion":"0.1.10","env":"prod","apiUrl":"https://app-prod.anyway.sh","argv":["products","list"]}
{"v":1,"ts":...,"t":"req","method":"GET","url":"https://app-prod.anyway.sh/v1/product?page=1&size=20","requestId":"a1b2c3d4-..."}
{"v":1,"ts":...,"t":"res","method":"GET","url":"...","status":200,"durationMs":142,"requestId":"a1b2c3d4-..."}
{"v":1,"ts":...,"t":"span","phase":"auth.refresh","durationMs":342}
{"v":1,"ts":...,"t":"err","method":"GET","url":"...","code":"ENOTFOUND","message":"..."}
{"v":1,"ts":...,"t":"exit","code":0,"totalMs":528}Event kinds:
start— first event of every run; records CLI version, target env, API URL, argv (with--token <value>scrubbed to<redacted>).span— a named phase with measured duration. Current phases:auth.refresh(auto token refresh),auth.exchange(login --token exchange). Tells the probe which stage the CLI was executing when it exited.req/res— HTTP request/response against anyway.sh hosts, including duration and arequestIdUUID set via theX-Request-Idheader so backend logs can be correlated.err— network-level failure (DNS / TLS / connection refused / reset). Noresevent follows.exit— final event with process exit code and total runtime.v— event schema version (1today).
Probes typically assert: every res has status < 400, no err events, final exit.code === 0. Failure diagnosis: the last span before exit tells you which phase died; requestId links to server-side logs.
Extra knobs:
ANYWAY_TRACE_FILE=/path— append JSONL to a file instead of stderr. Useful when stderr is noisy (ink spinners, progress bars).ANYWAY_TRACE_BODY=1— include up to 2 KB of each response body onresevents as abodyfield. For debugging only; do not enable unconditionally in logs where response payloads may contain sensitive data.
Development
# Build
yarn cli:build
# Run locally
node cli/dist/index.js <command>
# Link globally for development
yarn cli:linkLicense
MIT
