Skip to content
LogoLogo

Nava CLI

Developer Preview

@navalabs/sdk ships the nava binary with the four base verification commands:

nava request-verification --proposed-tx-json '{…}' --reason 'Why this action'
nava await-verification --proposed-tx-json '{…}' --reason 'Why this action'
nava check-verification-status --request-hash 0x…
nava get-user-address

Every option, default, and requirement is on the operations reference; this page covers only what is specific to running the CLI. Credentials and chain selection come from the environment; see configuration.

Adapters

Installing an adapter adds its protocol's commands to the same nava binary, spelled nava <protocol> <operation>:

An adapter brings @navalabs/sdk with it, so installing it alone is enough. Or skip installing and run it directly:

npx -p @navalabs/uniswap-adapter nava uniswap find-all-pools --protocol v3

pnpm dlx, yarn dlx, and bunx work the same way. For base verification with no protocol, point them at @navalabs/sdk instead.

Help output

Every level has help. nava --help lists the four base commands, then the protocols this install registers. A bare @navalabs/sdk registers none and says so. nava <protocol> --help lists that protocol's commands. nava <command> --help covers one command.

Exit code 0 does not mean approved

The exit code tracks whether the command ran, not what the verdict was. A rejected verdict is a completed operation, so it exits 0. Exit 2 is a usage error, exit 1 is an unknown command or a thrown error, including an await-verification timeout, which raises NavaTimeoutError rather than returning a PENDING payload.

Branch on the payload, not $?. The fields that carry the answer:

{
  "status": "APPROVED",   // or REJECTED | UNDECIDED | PENDING | EXECUTED | FAILED
  "canExecute": true,     // false on anything that is not an approval
  "verdict": {
    "outcome": "approved",   // or "rejected" | "pending"
    "reasonCode": "allowed", // a violation code when rejected
    "humanReason": "…",
    "policyVersion": 7       // the version the action was permitted under
  }
}

An approval has status: "APPROVED", outcome: "approved", reasonCode: "allowed", and canExecute: true. Anything else, including a missing verdict, is not approval. The Hyperliquid writes wrap the same information as success: false, the message under error, and requestHash plus decision under verification.

A script that keys off the exit code alone reads a rejection as a success, the same trap MCP has with isError.