<!-- Generated: README.md + AGENTS.md concatenated for token-bounded ingestion. Regenerate with: pnpm gen:llms -->

# @howells/wisecli

CLI for [Wise](https://wise.com/) — balances, transfers, profiles.

Designed for AI agents and automation. All output is structured JSON. Multi-token. Read-only by design.

## Install

```bash
npm install -g @howells/wisecli
```

## Setup

Get an API token at [wise.com/settings/api-tokens](https://wise.com/settings/api-tokens) (read-only is sufficient) and set it:

```bash
export WISE_API_TOKEN="your-token"
```

For multiple Wise accounts, use the `WISE_<NAME>_TOKEN` pattern:

```bash
export WISE_BUSINESS_TOKEN="..."
export WISE_PERSONAL_TOKEN="..."
```

Account names are derived from the env var: `WISE_BUSINESS_TOKEN` → `--account business`.

## Usage

```bash
wisecli accounts                                      # List configured tokens
wisecli profiles --account business                   # List profiles in a token

wisecli balance                                       # All balances under default/first token
wisecli balance --account all                         # Aggregate across every token
wisecli balance --account business                    # Specific token, all profiles in it
wisecli balance --account business --profile-type business  # One profile

wisecli transfers --account business --profile-type business
wisecli transfers --account business --profile-type business \
  --from 2026-04-01 --to 2026-04-30 --limit 50

wisecli schema                                        # Schema introspection (for agents)
```

Always pair `transfers` with `--fields` to keep responses small:

```bash
wisecli transfers --account business --profile-type business \
  --fields sourceFormatted,targetFormatted,date,status --limit 20
```

## Output Format

```json
{
  "ok": true,
  "data": [ ... ],
  "command": "balance",
  "account": "business"
}
```

Errors:

```json
{
  "ok": false,
  "error": "No Wise tokens found. Set WISE_API_TOKEN or WISE_<NAME>_TOKEN env vars.",
  "command": "balance"
}
```

## Tokens, Profiles, Balances

Wise has two layers above your money:

- A **token** authenticates you — one per `WISE_<NAME>_TOKEN` env var.
- A **profile** is a sub-entity within a token — typically one `BUSINESS` and/or one `PERSONAL`.
- A **balance** is the money in a single currency under a profile. One profile commonly has multiple currency balances (GBP, USD, EUR, …).

`balance` returns one row per (profile × currency). If a token has multiple profiles, `--profile-type` lets you scope.

## Read-Only

This CLI deliberately exposes only read endpoints. Transfers, recipient management, and conversions are out of scope — use the Wise UI or app for those.

## License

MIT

---

# @howells/wisecli — Agent Guide

CLI for Wise (TransferWise). Read-only. Multi-token via env vars; profiles (business/personal) discovered from API.

## Quick Start

```bash
# Single token
export WISE_API_TOKEN="..."

# Or multi-token
export WISE_BUSINESS_TOKEN="..."
export WISE_PERSONAL_TOKEN="..."

# Balances across every profile under the default token
wisecli balance

# All tokens, all profiles
wisecli balance --account all

# Specific token + profile type
wisecli balance --account business --profile-type business

# Transfers (always use --fields)
wisecli transfers --account business --profile-type business \
  --fields sourceFormatted,targetFormatted,date,status --limit 20

# Schema introspection
wisecli schema
```

## Invariants

- **Always use `--fields`** on transfers — payloads are deeply nested otherwise.
- **`transfers` requires `--account`** when more than one token is configured. If a token has multiple profiles, `--profile-type` is required too.
- **`--account all`** with `balance` aggregates across every configured token.
- **All output is JSON** with `{ok, data, error, command, account}` envelope.
- **Read-only by design** — no transfer creation, no recipient management. Use the Wise UI or app for write operations.
- **Tokens come from env vars** — no config files, no token cache.

## Permissions

| Tier | Actions |
|------|---------|
| **Always** | Any wisecli command. They only call `GET` against api.wise.com. |
| **Ask first** | Storing a token in a shared `.env`, exporting to a long-lived shell. |
| **Never** | Writing transfers, managing recipients, rotating tokens. wisecli is read-only by design — the Wise UI or app handles writes. |

## Token Discovery

Tokens are derived from `WISE_<NAME>_TOKEN`:
- `WISE_API_TOKEN` → `--account default`
- `WISE_BUSINESS_TOKEN` → `--account business`
- `WISE_JOINT_GBP_TOKEN` → `--account joint-gbp`

Create tokens at [wise.com/settings/api-tokens](https://wise.com/settings/api-tokens) — choose **read-only** access. wisecli never writes, so a narrowly-scoped token limits blast radius if it leaks.

## Profiles vs. Tokens

A single token can contain both a `BUSINESS` and `PERSONAL` profile. wisecli treats:
- **Token** = top-level credential (one per `WISE_<NAME>_TOKEN` env var)
- **Profile** = sub-entity within a token (`business` or `personal`)
- **Currency balance** = the actual money — surfaced as one row per (profile × currency)

If a token has both profiles, `--profile-type business|personal` selects one. With one profile, the choice is automatic.

## Common Workflows

### Daily balance check
```bash
wisecli balance --account all --fields profile,currency,formatted
```

### Outbound transfers this month
```bash
wisecli transfers --account business --profile-type business \
  --from 2026-04-01 --status outgoing_payment_sent \
  --fields targetFormatted,reference,date --limit 50
```

### List configured tokens
```bash
wisecli accounts
```

### List profiles under a token
```bash
wisecli profiles --account business
```

## Source Layout

- `src/index.ts` — CLI entry point, command dispatch, schema introspection.
- `src/api.ts` — Bearer-authenticated `fetch` wrapper around api.wise.com; throws `ApiError` with `is_retriable` and `status` fields.
- `src/errors.ts` — Structured error envelope helpers (codes, retriability, semantic exit codes).
- `src/accounts.ts` — `WISE_<NAME>_TOKEN` env-var discovery and resolution.
- `src/profiles.ts` — Wise profile listing (BUSINESS / PERSONAL) and selection.
- `src/commands.ts` — Balance and transfer fetch + row mapping.
- `src/validate.ts` — Input hardening (account names, ISO dates, profile types).
- `src/mcp-server.ts` — MCP server exposing the same commands as agent-callable tools.

For runtime introspection, run `wisecli schema`.

## Development

```bash
pnpm install
pnpm test          # Run vitest suites
pnpm typecheck     # tsc --noEmit
pnpm lint          # biome check
pnpm build         # Compile to dist/
```

## Error Envelope

Errors carry structured fields for retry decisions:

```json
{
  "ok": false,
  "error": "Wise API rate limit",
  "code": "ERR_RATE_LIMIT",
  "is_retriable": true,
  "retry_after_seconds": 30,
  "command": "transfers"
}
```

Exit codes follow `sysexits.h` conventions:

| Exit | Meaning |
|------|---------|
| 0    | Success |
| 64   | Usage error (unknown command, no command supplied) |
| 65   | Validation failure (`--from yesterday`, invalid `--profile-type`) |
| 66   | Not found (no such account/profile) |
| 69   | Service unavailable (Wise 5xx, network error, rate limit) |
| 77   | Permission denied (Wise 401/403 — bad or revoked token) |
| 1    | Generic fallback |
