> ## Documentation Index
> Fetch the complete documentation index at: https://jephalabs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI Reference

> qtg and qtg-agent command-line interface reference

# QTG CLI & MCP — Reference

QTG ships 3 entry points for the control plane:

| Binary      | Surface                                      | When to use                                |
| ----------- | -------------------------------------------- | ------------------------------------------ |
| `qtg`       | full role-aware (agent + minimal admin)      | operator running commands from a shell     |
| `qtg-agent` | agent-only subset (admin subcommands hidden) | LLM agent / CI / autopilot                 |
| `qtg-mcp`   | stdio MCP server                             | Claude Desktop / Cursor / Claude Agent SDK |

All 3 binaries share the same env vars and HMAC signing path. Role enforcement
happens server-side (HMAC middleware `ROLE_ALLOWED_ROUTES`); the binaries
surface server responses unchanged.

***

## Env vars (single set, all 3 binaries)

| Var                    | Required                                    | Meaning                                                          |
| ---------------------- | ------------------------------------------- | ---------------------------------------------------------------- |
| `QTG_KEY_ID`           | yes                                         | HMAC `key_id` registered in `api_client_keys`                    |
| `QTG_HMAC_SECRET`      | one of                                      | raw secret string (lower priority)                               |
| `QTG_HMAC_SECRET_FILE` | one of                                      | path to file containing secret (preferred — wins over raw)       |
| `QTG_API_URL`          | no                                          | default `http://localhost:8100`                                  |
| `QTG_AGENT_NAMESPACE`  | yes for `qtg-mcp`, optional for `qtg-agent` | agent namespace (`agent/<authority_key>`)                        |
| `QTG_AUTHORITY_KEY`    | no                                          | explicit authority\_key override (bypasses namespace derivation) |
| `QTG_OUTPUT`           | no                                          | `json` forces JSON output (CLI)                                  |

The shared HMAC client emits both `X-MG-*` and `X-QTG-*` headers (v3 nonce +
timestamp), matching `qtg.interfaces.api.middleware.auth.hmac.sign_request_headers`.

***

## Agent CLI (`qtg-agent`, 8 commands, read + propose only)

### `qtg-agent balances`

```bash theme={null}
qtg-agent balances --json
```

→ `GET /v3/balances`. Returns the balance view this agent can see.

### `qtg-agent movements list / get / timeline`

```bash theme={null}
qtg-agent movements list --limit 20
qtg-agent movements get <movement_id>
qtg-agent movements timeline <movement_id>
```

→ `GET /v3/movements?limit=20`, `GET /v3/movements/{id}`,
`GET /v3/movements/{id}/timeline`.

### `qtg-agent authority describe`

```bash theme={null}
qtg-agent authority describe
```

→ `GET /v3/agent-authorities/{authority_key}`. The `authority_key` is derived
from `QTG_AGENT_NAMESPACE` (strip `agent/` prefix), or `QTG_AUTHORITY_KEY` if set,
or fetched from `/v3/whoami` as fallback.

### `qtg-agent template-proposals get`

```bash theme={null}
qtg-agent template-proposals get <proposal_id>
```

→ `GET /v3/template-proposals/{id}`. Poll this after `template-propose` until
`status == "auto_promoted"` (or admin promotes manually) to learn the
resulting `template_key`.

### `qtg-agent template-propose`

```bash theme={null}
qtg-agent template-propose \
  --asset USDC \
  --protocol-family cex_to_cex \
  --proposal-kind static \
  --source-chain binance \
  --destination-chain arbitrum \
  --destination-chain-id 42161 \
  --destination-address 0xabc... \
  --signer-profile kms \
  --requested-notional 100 \
  --ttl-seconds 600
```

→ `POST /v3/agent-authorities/{authority_key}/template-proposals`. Side-effect
free until promoted. Returns `{proposal_id, status, ...}`.

### `qtg-agent bridge-attempt`

Same field set as `template-propose` plus optional `--callback-url`. D10 rule
applies — propose only, no auto-execute.

> **No `movement-run`.** The agent CLI is read + propose only — it cannot
> execute a movement. A movement an agent originates (via the API) always parks
> at `PENDING_APPROVAL` with `agent_auto_approve_skipped`, regardless of the
> operator's `auto_approve_enabled` setting; a human promotes + approves.

***

## Admin CLI (`qtg`)

`qtg` exposes all 8 agent commands plus the Free admin surface below. Venue
checks (`qtg venue probe/smoke`) are implemented and wired today. Key/role
provisioning (`qtg admin keys` / `admin role`) is still deferred to v0.2.0+ —
use legacy `seed_auth_client.py` / `bootstrap_admin_cli_key.py` for that.

### `qtg init`

```bash theme={null}
qtg init --network testnet
```

Interactive first-run onboarding: brings up PostgreSQL via compose, runs the
Alembic chain for `public` plus the one selected network bucket, renders a `.env`
from `.env.example`, and provisions a local signer and admin key. Walkthrough:
[Local Setup](/quickstart/01-local-setup).

<Warning>
  `qtg init` renders `.env` **from `.env.example`**, not from your live `.env`. Running
  it again after you have added keys by hand overwrites them.
</Warning>

### `qtg whoami`

```bash theme={null}
qtg whoami
```

→ `GET /v3/whoami`. Returns `{client_id, key_id, role, namespace?}`. Useful
sanity check for key/secret setup.

### `qtg audit query`

```bash theme={null}
qtg audit query --action movement.create --outcome denied --limit 50
```

→ `GET /v3/audit/events`. Supported filters mirror
`src/qtg/interfaces/api/routes/audit.py:58-74` exactly:
`--time-range-start`, `--time-range-end`, `--actor-client-id`,
`--actor-key-id`, `--entity-type`, `--entity-key`, `--action`,
`--request-id`, `--outcome`, `--namespace`, `--cursor`, `--limit`.

### `qtg template promote`

```bash theme={null}
qtg template promote <proposal_id>
```

→ `POST /v3/template-proposals/{proposal_id}/promote`. Admin-only.

### `qtg template patch`

```bash theme={null}
qtg template patch <template_key> \
  --auto-approve-enabled true \
  --daily-cap-amount 100 \
  --daily-cap-asset USDC
```

→ `PATCH /v3/plan-templates/{template_key}`. Plan 2 admin cap mutation.

### `qtg allowlist list`

```bash theme={null}
qtg allowlist list --chain-family evm --chain-id 8453
qtg allowlist list --include-inactive
```

→ `GET /dashboard/allowed-addresses`. Read-only view of the address allowlist
that guards fund movement. Filters: `--chain-family` (`evm` | `cex`),
`--chain-id`, `--include-inactive` (adds revoked rows).

A row with `"chain_id": null` is an **any-chain wildcard** — it authorises the
address on every chain of its family. Review those first when auditing.

The group is read-only by design. Registering and revoking stay on the audited
write surfaces — `python -m qtg.interfaces.tools.seed_allowed_address` /
`... .revoke_allowed_address`, or the dashboard writer-HMAC routes — because a
convenience CLI mutation on a fund-safety gate is an open security decision. See
[Runbook — Address Allowlist Management](/reference/runbook-v3).

### `qtg chain probe`

```bash theme={null}
qtg chain probe base_sepolia --rpc-url https://... --usdc 0x...
```

Reports whether a chain's CCTP and Gateway lanes are actually open before you
route funds through them. Read-only. Each lane also probes a domain that must
*not* exist, so an endpoint that answers everything identically cannot read as
GO. Exits non-zero unless every requested lane passes.

### `qtg agent-wallet topup`

The Agent Wallet top-up stage ladder — `env-probe`, `init-packet`, `seed-stage1`,
`drill-stage2`, `live-stage3`, `validate-packet`. Only `live-stage3` can sign or
broadcast, and it requires an explicit acknowledgement flag. See
[Agent Wallet](/guide/agent-wallet).

### `qtg testnet-truncate`

Truncates every network-scoped table in the **testnet** schema. Prompts unless
`--yes` is passed. There is no mainnet equivalent.

***

## Venue CLI (`qtg venue`)

Adapter health check + live smoke test. See
[`guide/venue-smoke-test.md`](/guide/venue-smoke-test) for the end-to-end
walkthrough.

### `qtg venue probe`

```bash theme={null}
qtg venue probe <venue> --asset USDC --network ethereum
```

Read-only adapter health check — verifies credentials and connectivity for the
named exchange (e.g. `binance`, `upbit`, `bybit`). Exits non-zero if the probe
fails. Runs the probe harness locally; no movement is created.

### `qtg venue smoke`

```bash theme={null}
qtg venue smoke <source> \
  --dest <destination> \
  --asset USDC \
  --network ethereum \
  --amount 5 \
  --timeout 300
```

Live smoke test — sends a small stablecoin transfer (capped at \$5) through the
full movement lifecycle and observes settlement. Prompts for confirmation unless
`--no-confirm` is passed. `--timeout` bounds the observe phase (default 300s).
Exits zero only when the movement reaches `COMPLETED`.

***

## MCP server — Claude Desktop / Cursor

`qtg-mcp` is a stdio MCP server exposing 8 read+propose tools to MCP-aware clients (no movement-execution tool).

### `claude_desktop_config.json`

```jsonc theme={null}
{
  "mcpServers": {
    "qtg": {
      "command": "qtg-mcp",
      "env": {
        "QTG_KEY_ID": "agent-key-001",
        "QTG_HMAC_SECRET_FILE": "/path/to/agent_hmac_secret",
        "QTG_API_URL": "http://localhost:8100",
        "QTG_AGENT_NAMESPACE": "agent/auth_alpha"
      }
    }
  }
}
```

### Tool list

| Tool                                                | HTTP                                                            |
| --------------------------------------------------- | --------------------------------------------------------------- |
| `qtg_balances`                                      | `GET /v3/balances`                                              |
| `qtg_movements_list(limit)`                         | `GET /v3/movements?limit=...`                                   |
| `qtg_movement_get(movement_id)`                     | `GET /v3/movements/{id}`                                        |
| `qtg_movement_timeline(movement_id)`                | `GET /v3/movements/{id}/timeline`                               |
| `qtg_template_proposals_get(proposal_id)`           | `GET /v3/template-proposals/{id}`                               |
| `qtg_authority_describe()`                          | `GET /v3/agent-authorities/{authority_key}`                     |
| `qtg_template_propose(asset, protocol_family, ...)` | `POST /v3/agent-authorities/{authority_key}/template-proposals` |
| `qtg_bridge_attempt(asset, protocol_family, ...)`   | `POST /v3/agent-authorities/{authority_key}/bridge-attempt`     |

### Boot-time role probe (fail-fast)

`qtg-mcp` does a synchronous `GET /v3/whoami` before opening the stdio
handshake. If:

* the env is incomplete → exit 2 with stderr `qtg-mcp: config error: ...`
* whoami HTTP fails → exit 1 with stderr `qtg-mcp: whoami probe failed: ...`
* role != `agent` → exit 1 with stderr `qtg-mcp: refusing to start — key role is 'admin', expected 'agent'`
* env namespace != server-reported namespace → exit 1 with stderr `qtg-mcp: namespace mismatch — ...`

This prevents silent registration in Claude Desktop with a misconfigured key.

### e2e smoke runbook

```bash theme={null}
# 1. Seed an agent key + AgentAuthority in dev DB.
# 2. Export env:
export QTG_KEY_ID=agent-key-001
export QTG_HMAC_SECRET_FILE=/path/to/secret
export QTG_API_URL=http://localhost:8100
export QTG_AGENT_NAMESPACE=agent/auth_alpha

# 3. Run dev server (separate shell).
uv run uvicorn qtg.main:app --reload --port 8100

# 4. Smoke test:
qtg whoami                 # role=agent + namespace (whoami is on the `qtg` binary only)
qtg-agent balances --json  # should return the balance shape

# 5. MCP subprocess:
qtg-mcp <<< '{"jsonrpc":"2.0","method":"tools/list","id":1}'
# → JSON response listing 8 tools.

# 6. (Opt-in pytest e2e — requires dev server running)
QTG_MCP_E2E=1 \
  QTG_E2E_AGENT_KEY_ID=$QTG_KEY_ID \
  QTG_E2E_AGENT_SECRET=$(cat /path/to/secret) \
  QTG_E2E_AGENT_NAMESPACE=$QTG_AGENT_NAMESPACE \
  uv run pytest tests/qtg/mcp_server/test_mcp_e2e.py -v
```

***

## Out of scope (v0.1.0 GA)

* Template discovery (`qtg-agent templates list/search`) — v0.2.0
* Streamable HTTP MCP transport — v0.2.0+ (stdio only for now)
* `qtg admin keys` / `admin role` (key/role provisioning) — server routes
  pending; use legacy `seed_auth_client.py` for now.
* Migration of 55+ legacy admin tools — v0.2.0+ gradual
* Colored / pretty CLI output (rich) — v0.2.0+
* Windows shell compatibility — macOS + Linux verified only

***
