npm package: @obul.ai/obulx
Description: Obul x402 CLI and library.
Latest version: 0.2.13

# @obul.ai/obulx

Obul x402 CLI and library.

## Install
```bash
npm install -g @obul.ai/obulx
```

Direct x402 mode (non-proxy) requires installing the optional addon:
```bash
npm install -g @obul.ai/obulx-x402
```

## What It Does
`obulx` is a CLI for calling x402-protected endpoints. It supports:
- Proxy mode (via Obul proxy) API key auth.
- Direct x402 mode with a local private key for signing payments.

## CLI Usage
```bash
obulx <command>
obulx [options] <url>
```

Commands:
- `obulx login`: OAuth device login. If already authenticated, prints current session and exits. Use `--force` to re-authenticate.
- `obulx logout`: Best-effort refresh token revocation + local credential removal.
- `obulx whoami`: Prints the current authenticated user.

## Key Parameters
- `--obul-proxy <BASE>`: Enables proxy mode and rewrites the URL as `BASE/{scheme}/{host}{path}?{query}`. Defaults to `OBUL_PROXY_URL` or `https://proxy.obul.ai/proxy`.
- `--network <NETWORK>`: Required for direct x402 mode. Repeatable or comma-separated.
- `--auto-approve-limit <N>`: Optional for direct x402 mode. Integer string in token units. Defaults to `0` (always prompt for approval).
- `--asset <ADDRESS>`: Optional in direct mode. Exact match (case-insensitive).
- `-X, --method <METHOD>`: HTTP method (default `GET`).
- `-d, --data <BODY>`: Raw request body. Defaults method to `POST` if method is not set.
- `-H, --header <NAME: VALUE>`: Add a request header (repeatable).
- `-v`: Show final response status and headers.
- `-vv`: Show final request + response.
- `-vvv`: Also show probe request + response in direct x402 mode.
- `--force`: With `obulx login`, forces a fresh auth flow even if already logged in.

## Environment Variables
- `OBUL_ISSUER_URL`: OAuth issuer URL (defaults to `https://api.obul.ai`) used by `login`, `logout`, and `whoami`.
- `OBUL_PROXY_URL`: Override proxy base (defaults to `https://proxy.obul.ai/proxy`).
- `OBUL_API_KEY`: API key for proxy mode.
- `OBUL_X402_PRIVATE_KEY`: Private signing key for direct x402 mode.
 - `PRIVATE_KEY`: Fallback private key for direct x402 mode.

## Auth Precedence (Proxy Mode)
When running proxy fetches (`obulx [options] <url>`), auth selection is:
1. `OBUL_API_KEY` env var
2. OAuth access token from `~/.obul/credentials.json` (auto-refreshes with refresh token)
3. error if neither is available

Notes:
- Credentials are stored in `~/.obul/credentials.json` (file mode `0600`).
- `whoami` and post-login identity output are JWT-first and opportunistically use `/oauth/userinfo` when available.

## Examples

Login:
```bash
obulx login
```

Who am I:
```bash
obulx whoami
```

Logout:
```bash
obulx logout
```

Proxy mode (API key):
```bash
export OBUL_PROXY_URL="https://proxy.devnet.obul.ai/proxy"
export OBUL_API_KEY="your-api-key"

obulx <x402-protected endpoint>
```

Proxy mode with custom headers:
```bash
obulx --obul-proxy https://proxy.devnet.obul.ai/proxy \
  -H "Content-Type: application/json" \
  -H "X-Custom: value" \
  <x402-protected endpoint>
```

Direct x402 mode:
```bash
export OBUL_X402_PRIVATE_KEY="0x..."
npm install -g @obul.ai/obulx-x402

obulx --network base --auto-approve-limit 1000 \
  https://x402.example.com/resource
```

Direct mode with network priority and asset filter:
```bash
export OBUL_X402_PRIVATE_KEY="0x..."
npm install -g @obul.ai/obulx-x402

obulx --network base,optimism --asset 0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 \
  --auto-approve-limit 1000 \
  https://x402.example.com/resource
```

Verbose output (final request + response):
```bash
obulx -vv --obul-proxy https://proxy.devnet.obul.ai/proxy \
  <x402-protected endpoint>
```

Verbose output (probe + final in direct mode):
```bash
npm install -g @obul.ai/obulx-x402
obulx -vvv --network base --auto-approve-limit 1000 \
  https://x402.example.com/resource
```

## CLI
```bash
obulx --obul-proxy https://proxy.devnet.obul.ai/proxy \
  -X POST -d '<x402 request body>' \
  <x402-protected endpoint>
```

## Library
```ts
import { obulxFetch } from "@obul.ai/obulx"

const response = await obulxFetch({
  url: "<x402-protected endpoint>",
  method: "POST",
  body: "...",
  obulProxy: "https://proxy.devnet.obul.ai/proxy",
  obulApiKey: process.env.OBUL_API_KEY,
  verbose: 1
})

process.stdout.write(response.body)
```