Skip to content
Get an API key

@predictefy/cli installs the predictefy binary, the terminal and AI-agent client for the Predictefy API. It is a thin wrapper over the TypeScript SDK: one command shape for every venue, with --venue <slug> choosing the lane. Reads and normalization stay server-side; signing stays on your machine.

From this workspace:

Terminal window
pnpm install
pnpm --filter @predictefy/cli... build
pnpm --filter @predictefy/cli exec predictefy --help

Or install the binary globally:

Terminal window
npm install --global @predictefy/cli
predictefy --help

Node >=20.19 <21 || >=22.12 is required.

Authenticate through the environment:

Terminal window
export PREDICTEFY_API_KEY='pk_live_…'
predictefy whoami

Or through a config file:

Terminal window
predictefy config init # writes a commented ~/.predictefy/config.toml
predictefy config show # prints it with the API key redacted

PREDICTEFY_HOME relocates the config directory: the CLI then reads $PREDICTEFY_HOME/config.toml. Environment authentication takes precedence over the file.

API keys are never accepted as command-line arguments. Argv is readable by other processes and lands in shell history, so the key comes from the environment or the config file only. The same rule covers the signing key and every venue credential.

status is public and keyless. Every other remote command uses the configured key.

Flag Default What it does
--json off Writes the API response bytes unchanged.
--venue <slug> router Selects the venue. There are no per-venue command namespaces.

--json does not rewrap, rename, or pretty-print fields, so it is offered only on commands backed by exactly one API request. The machine contract is the API envelope itself:

{ "success": true, "data": [] }

An API error envelope is written unchanged and exits 1:

{ "success": false, "error": { "code": "NOT_SUPPORTED", "message": "", "retryable": false } }

Exit codes:

  • 0 — success.
  • 1 — API, transport, config, or doctor-check failure.
  • 2 — command usage error.

Errors go to stderr, except a --json envelope, which goes to stdout.

Composite and local commands reject --json because there is no single envelope to pass through honestly: venues, doctor, config, skill, and watch. Two surfaces stream instead: webhooks listen and watch --raw emit NDJSON, one JSON object per line.

predictefy <command> --help lists the exact options a command accepts.

Venue-aware commands take --venue <slug>; the default router is the cross-venue aggregate. List verbs paginate with --limit plus either --offset or --cursor, depending on which pagination the route serves.

Service checks, identity, capability summaries, and local setup.

Terminal window
predictefy status # public service snapshot, no key required
predictefy whoami # prove the configured key works
predictefy venues # every venue with its honest capability summary
predictefy venues metrics --venue polymarket
predictefy doctor # sequenced connectivity, key, and catalog checks
predictefy config init
predictefy config show
predictefy skill install --agents # write the predictefy-cli agent skill

The API does not expose identity, scopes, plan, or credits, so whoami says so and uses an authenticated capability request as its proof. skill install also accepts --claude, --read-only, and --dry-run.

Search, read, and page the normalized market catalog.

Terminal window
predictefy markets search "central bank" --venue router --limit 5
predictefy markets get 0xabc --venue polymarket
predictefy markets list --venue kalshi --status active --sort liquidity --limit 20
predictefy markets page --venue router --limit 100
predictefy markets categories
predictefy markets tags --category politics
predictefy markets has --venue kalshi
predictefy markets orderbooks <outcomeId> <outcomeId>
predictefy markets execution-price <outcomeId> --side buy --size 250
predictefy markets execution-price <outcomeId> --side buy --size 250 --detailed
predictefy markets filter '<criteriaJson>' --markets '<marketsJson>'

markets search accepts --search-in title|description|both and --mode lexical|semantic|hybrid; semantic and hybrid stay subject to server capability flags. markets page is the cursor-paginated form, which freezes the catalog snapshot from page one. markets has prints one venue’s capability map.

markets execution-price is a stateless VWAP calculation over the venue’s order book: it estimates what a fill of that size would average. It places, routes, and prepares nothing. --side and --size are required, and --detailed returns the per-level breakdown. markets filter is a pure stateless filter over a market list: the positional argument is the criteria JSON and the required --markets is the JSON array to filter. That route is feature-flagged, so a deployment without it returns the server’s honest error.

Event-shaped listings, event metadata, and series.

Terminal window
predictefy events --venue router --status active --sort volume --limit 20
predictefy events get <eventId> --venue polymarket
predictefy events page --venue router --limit 100
predictefy events metadata <eventId> --venue kalshi
predictefy events series --venue kalshi
predictefy events filter '<criteriaJson>' --events '<eventsJson>'

events --sort accepts volume, newest, liquidity, or closeDate. events filter mirrors markets filter: criteria as the positional argument, the required --events array as the input.

Live books, the public trades tape, and candles.

Terminal window
predictefy orderbook <marketId> --venue polymarket --limit 20
predictefy trades <marketId> --venue polymarket --limit 20
predictefy candles <marketId> --venue polymarket --timeframe 1h --limit 100

These three verbs are outcome-keyed. The positional argument keeps the <marketId> spelling, but the value must be the venue’s outcome or CLOB token identifier. A venue without a public trades tape returns the server’s honest NOT_SUPPORTED error rather than an empty list.

Matched clusters, matched pairs, indicative price discrepancies, and the router’s executable assessment.

Terminal window
predictefy clusters --sort similarity --limit 20
predictefy clusters list --has-discrepancy --limit 20
predictefy clusters get <clusterId>
predictefy clusters markets --limit 20
predictefy clusters events --limit 20
predictefy discrepancies --live --limit 20
predictefy discrepancies qualify <clusterId> --size 100
predictefy arbitrage --venue router --contracts 100 --executable-only --limit 20
predictefy matches list --market-id polymarket:0xabc --limit 20
predictefy matches browse --category politics --limit 20
predictefy matches markets --min-difference 0.05 --sort priceDifference --limit 20
predictefy matches prices --min-similarity 0.9 --limit 20
predictefy matches compare --market-id polymarket:0xabc --live --limit 20
predictefy matches hedges --market-id polymarket:0xabc --limit 20
predictefy matches related --slug <marketSlug> --limit 20
predictefy matches events --event-id polymarket:<eventId> --limit 20

Cross-venue price gaps are indicative price discrepancies — observed mid-price gaps, not executable opportunities. discrepancies qualify runs the server’s qualification checks against one cluster at a size, and arbitrage applies the server’s live-ask, open-market, depth, fee/gas, and resolution-equivalence gates. The CLI neither weakens nor recreates those gates; it prints what the server decided, including the refusal reasons.

matches compare, matches hedges, and matches related are anchored on one market with --market-id (the canonical {venue}:{marketId} spelling) or --slug, and matches events takes an --event-id anchor instead. --sort accepts priceDifference or similarity. Hedge and related rows are candidates, not instructions.

Wallet-attributed tapes, holders, leaderboards, and scored trades.

Terminal window
predictefy traders leaderboard --window all --limit 20
predictefy traders leaderboard --venue polymarket --window month --limit 20
predictefy traders wallet <address> --venue polymarket
predictefy traders smart-money --venue kalshi --limit 20
predictefy traders market-trades <marketId> --venue polymarket --limit 50
predictefy traders holders <marketId> --venue polymarket --limit 50
predictefy traders wallet-trades <address> --venue polymarket --limit 50

Trader identity is capability-qualified per venue. Without --venue, traders leaderboard serves the cross-venue score ranking. Unsupported venue and verb combinations return the server’s honest error; scores are informational signals, not advice.

Terminal window
predictefy portfolio <address> --venues polymarket,limitless,opinion

One public address across the venues you name.

Hosted account reads. Every verb addresses one account on one venue, so all six require an explicit --venue: the router default is a catalog aggregate, never an account.

Terminal window
predictefy accounts capabilities --venue hyperliquid
predictefy accounts snapshot <accountId> --venue hyperliquid
predictefy accounts balances <accountId> --venue hyperliquid --limit 50
predictefy accounts positions <accountId> --venue hyperliquid --limit 50
predictefy accounts open-orders <accountId> --venue hyperliquid --limit 50
predictefy accounts fills <accountId> --venue hyperliquid --cursor <cursor>

Start with accounts capabilities: it reports which of these resources the venue actually serves. See Accounts & funding for the per-venue account model.

Funding prerequisites, ordered funding steps, and cross-chain bridge sessions.

Terminal window
predictefy funding requirements --venue polymarket
predictefy funding steps --venue polymarket --owner 0xabc --target-amount 250
predictefy funding transfer-plan --from-venue polymarket --to-venue hyperliquid \
--amount 250 --owner 0xabc
predictefy bridge quote --from-chain 8453 --from-token USDC --from-amount 250000000 \
--from-address 0xabc --to-venue hyperliquid
predictefy bridge session create --from-chain 8453 --from-token USDC \
--from-amount 250000000 --from-address 0xabc --to-venue hyperliquid \
--payment-currency <caip19>
predictefy bridge session get <sessionId>
predictefy bridge session payment <sessionId> --tx-hash 0xdef
predictefy bridge status --tx-hash 0xdef --from-chain 8453 --to-chain 42161

funding requirements and funding steps address one venue and require an explicit --venue; funding transfer-plan names both ends itself with --from-venue and --to-venue. bridge quote also accepts --to-chain, --to-token, --to-address, and --slippage.

Every artifact these commands return is unsigned. The CLI prints it; you sign and broadcast it yourself, then report the payment hash back with bridge session payment. Step bodies are venue-shaped, so funding steps takes repeatable --field key=value values that the server stays authoritative over — additive fields only, under the same rule as trade --field.

Reference price feeds, separate from the prediction-market venues.

Terminal window
predictefy feeds list
predictefy feeds markets <feed>
predictefy feeds ticker <feed> <symbol>
predictefy feeds tickers <feed> --symbols <symbol>,<symbol>
predictefy feeds candles <feed> <symbol> --timeframe 1h --limit 100
predictefy feeds orderbook <feed> --symbol <symbol>
predictefy feeds oracle-round <feed> <pair>
predictefy feeds oracle-history <feed> <pair> --limit 20
predictefy feeds history <feed> <symbol> --from <epochSeconds> --until <epochSeconds> --order asc

A feed is addressed by feed id and symbol, not by --venue. feeds candles also takes --since as an epoch-ms lower bound, and feeds history takes --max-size plus --order asc|desc.

feeds orderbook is a permanent capability gap, kept visible rather than hidden: reference feeds publish prices, not depth, so the route always returns a typed NOT_SUPPORTED error. Use predictefy orderbook for prediction-market depth.

Terminal window
predictefy billing checkout --pack <id>
predictefy billing subscribe --plan <id>
predictefy billing portal

Each command prints a hosted Stripe URL for you to open. The CLI never collects card or payment data. See Credits & billing for packs, plans, and metering.

Terminal window
predictefy sql "select venue, count(*) from markets group by venue"
predictefy mappings polymarket:0xabc kalshi:KXFED-26MAR-T4.00

sql requires an API key with the sql scope. A key without that scope gets an authorization error from the server — the scope is not granted by default and cannot be set from the CLI. mappings resolves venue:marketId pairs to their cross-venue identity.

Terminal window
predictefy webhooks create --url https://hooks.example.com/predictefy \
--events ingest.run.completed,execution.status.changed
predictefy webhooks list
predictefy webhooks delete <id>
predictefy webhooks listen --endpoint <id>
predictefy webhooks listen --endpoint <id> --forward http://localhost:3000/hooks

webhooks listen polls deliveries until SIGINT. Without --endpoint it creates a temporary endpoint, subscribes, polls, and deletes the endpoint on exit; a failed cleanup prints the endpoint id. Forwarding accepts only localhost, 127.0.0.1, or ::1, and POSTs the payload with an X-Predictefy-Event header. --interval <seconds> changes the poll interval, which defaults to 2. With --json, each delivery is one NDJSON line rather than an API envelope.

Terminal window
predictefy trade buy <marketId> <outcome> <size> --venue hyperliquid --price 0.62
predictefy trade sell <marketId> <outcome> <size> --venue hyperliquid --price 0.62 --preview
predictefy trade submit <executionId> --venue hyperliquid --side buy --artifact-digest <digest> --yes
predictefy trade cancel <executionId> --venue hyperliquid
predictefy trade modify <executionId> --venue hyperliquid --price 0.64
predictefy trade status <executionId> --venue hyperliquid
predictefy trade status <executionId> --venue hyperliquid --refresh

Every trade verb requires an explicit --venue: the router default is a catalog aggregate, never an execution lane. --price is required on buy and sell and lies in (0, 1]. trade modify needs at least one of --price, --size, or --field. trade status --refresh re-reads status from the venue, using the venue credentials described in Venue credentials — never command arguments.

--tif accepts Alo, Ioc, or Gtc and applies to hyperliquid only, which is the one builder that takes the field. It has no default: omit it and each venue applies its own. Passing it for another venue is refused locally, before any network call, because most builders reject the key outright and pascal rejects the value — its time-in-force vocabulary is uppercase GTC | GTT | IOC, which this flag deliberately does not translate. Translating would submit an order you did not describe.

trade cancel and trade modify sign locally, and only Hyperliquid’s cancel/modify artifact is signable by the local EVM key today. Both verbs refuse another venue by name before signing; use the REST API or the SDK for those.

polymarket_us is a capability-qualified exception. trade buy and trade sell refuse it by name. The CLI derives one generic order body — outcome, outcomeSide, isBuy, price, size, owner — and the polymarket_us builder takes a different vocabulary entirely (marketId, outcomeId, side, type, amount), so every field would be rejected. Use the REST API or the SDK for polymarket_us orders. Its other verbs are unaffected.

These verbs are gated. Read Trading gates before running any of them, and Trading & execution for the full non-custodial model.

Reads over the isolated execution service: the armed lane registry and your recorded orders, trades, positions, and balance.

Terminal window
predictefy exec venues
predictefy exec orders --venue hyperliquid --status open --limit 50
predictefy exec trades --venue hyperliquid --limit 50
predictefy exec positions --venue hyperliquid
predictefy exec balance --venue hyperliquid

exec venues is the registry the trading gates below consult: one row per venue the execution service arms, with a flag per verb and the gating that applies. The table prints the build, submit, cancel, modify, and redeem flags plus the geo-restriction gate; --json returns the row verbatim. Run it first when a trade is refused. exec orders --status accepts open, closed, or all and defaults to open. Every exec verb except venues addresses one venue and requires an explicit --venue.

These verbs read; they never sign. They therefore take exactly one requirement — PREDICTEFY_EXEC_BASE_URL, because there is no other origin to read from — and neither the [trading] opt-in nor a signing key. trade status follows the same rule, so no read is gated more tightly than its neighbour.

Terminal window
predictefy watch orderbook <marketId> --venue polymarket
predictefy watch trades <marketId> --venue polymarket
predictefy watch price <marketId> --venue rain --market-address 0xabc
predictefy watch feed-ticker <feed> <symbol>
predictefy watch arbitrage

See Streaming behavior for the socket lifecycle, --raw, and entitlements.

Trading is deliberately gated by three independent controls. None of them substitutes for another, and each one covers a different set of verbs.

  1. [trading] enabled = true in ~/.predictefy/config.toml — the local opt-in. Required by trade buy, trade sell, trade submit, trade cancel, and trade modify.
  2. PREDICTEFY_EXEC_BASE_URL — the isolated execution origin. It has no default, so the reads API can never become an execution proxy. Required by every command that talks to the execution service, reads included: all of exec * and trade status.
  3. PREDICTEFY_EVM_PRIVATE_KEY — required by trade buy, trade sell, trade submit, trade cancel, and trade modify, including an unsigned preview. A preview is built for your account, so the CLI reads that key to derive its address and puts the address in the build body. Nothing is signed and nothing is sent. exec * and trade status never read the key at all.
[trading]
enabled = true
Terminal window
export PREDICTEFY_EXEC_BASE_URL='https://execution.example.com'
export PREDICTEFY_EVM_PRIVATE_KEY='0x…'

The signing key is environment-only. It is never accepted in argv or config.toml, never printed, and never sent to Predictefy. Every byte the CLI writes — human output, --json envelopes, warnings, and error text — passes through one redaction seam that removes the API key, the signing key, and any configured venue credential, matching case-insensitively and with or without a 0x prefix. Signing happens locally, in-process.

Venue support is not a hardcoded CLI list. trade queries GET /v1/exec/venues — the server’s lane registry — at runtime, and allows any venue whose row arms the requested verb. When a venue or verb is not armed, the CLI refuses and names the venues that are armed, reading both answers out of the registry rather than out of a list baked into the client. A preview needs build; a confirmed persisted execution needs submit. Before signing, the CLI also honors the gating the same row publishes: a geo-restricted lane, or a lane armed without artifact bounds, is refused before a signature exists rather than after the venue rejects the submit.

Signing routes on your --venue, and the envelope is pinned. Structural validity is not authorization: a token Permit, a Permit2 batch and a marketplace listing are all valid EIP-712 typed data, so an execution service that returned one instead of an order could otherwise have it signed. Two rules prevent that:

  • The signing path is chosen by the venue you typed, never by the shape or the self-declared venue of the artifact. An artifact stamped for a different venue than --venue is refused by name.
  • Before signing, the envelope must match that venue’s pinned exchange domain — EIP-712 domain name, version, chainId, and a verifyingContract from the venue’s known-exchange allowlist — the exact struct of its deployed exchange (field names, types, count and order, not just the struct name), and your own intent: the struct’s signer field must be your signing address, and its side must be the buy or sell you asked for. Where the struct routes value or names a counterparty (beneficiary on XO, taker on Opinion, PredictStreet, and PRED), that field must be the zero address or your own account. Any mismatch is refused naming the field that failed, and no signature bytes are produced.

Hyperliquid’s native L1 path is pinned the same way. The signer canonicalizes the visible action, recomputes its official msgpack connectionId with the nonce and expiry, and requires the network source to match Mainnet or Testnet. It also requires the real Exchange domain (chainId 1337, zero verifyingContract) and refuses any action outside order, cancel, cancelByCloid, and modify. A different digest or fund-moving action is refused before signing.

A venue with no pinned envelope and no native path — one authenticating with venue-issued API credentials, or signing with a non-EVM key — is refused with a message naming what is supported. The CLI never signs an artifact it cannot account for.

Always preview first. The default builds and prints the unsigned artifact plus its notional and fee bounds. It signs nothing and submits nothing:

Terminal window
predictefy trade buy <marketId> <outcome> <size> --venue hyperliquid --price 0.62

The preview prints a canonical artifact digest and the exact second-step command. After a human confirms that artifact, submit the persisted execution rather than rebuilding it:

Terminal window
predictefy trade submit <executionId> --venue hyperliquid --side buy \
--artifact-digest <digest-from-preview> --yes

trade submit reloads the named execution, recomputes its digest, and refuses before signing when it differs from --artifact-digest. Under --json, the preview’s confirmation command and the confirmed artifact go to stderr, so stdout remains one clean API envelope. The older one-shot trade buy|sell --yes path no longer exists.

Read that artifact — it is your verification surface for the values the pins cannot cover. The order amounts (makerAmount/takerAmount) and the outcome tokenId are not pinned. Amounts are each venue’s own tick- and decimal-scaled derivation of price × size, and the token is resolved from your market through the venue’s catalog, so the CLI cannot re-derive either without duplicating every venue’s rounding rules — which would refuse legitimate orders. The honest consequence: an execution origin that has been compromised can put different values in the preview, so check its amounts and token. Once its digest is confirmed, however, the origin cannot swap those values before signing: any change produces a different digest and is refused.

Additive venue-shaped build fields go through repeatable --field key=value values, which the server — not the CLI — is authoritative over. The per-venue build schemas in Trading & execution name the fields each venue expects:

Terminal window
predictefy trade buy <marketId> <outcome> <size> --venue polymarket \
--field <key>=<value> --field <key>=<value>

A field value parses as JSON when it can, so numbers, booleans, and objects survive; anything else stays a literal string. trade modify takes the same escape hatch for venue-shaped modify bodies, and funding steps takes it for venue-shaped step bodies.

--field is additive only. It cannot set venue, owner, signer, funder, isBuy, side, price, size, outcome, outcomeSide, asset, targetAmount, dryRun, or idempotencyKey: those come from the command’s own arguments, --venue, its dedicated flags, and the signing key, and the safety gates already ran against them. Setting one would move the request to a different venue, account, side, price, or size than the one you typed — past the gate that checked it. Passing one is a usage error (exit 2) before any network call.

Some execution lanes require credentials the venue issued to you — an API key, secret, and passphrase, or an access/refresh token pair. Predictefy never holds them, so the CLI forwards them from your environment on the calls that need them: trade submit and trade status --refresh.

They are accepted from the environment only, never from command arguments, where they would land in the process list, shell history, and CI logs. One variable per field:

Terminal window
export PREDICTEFY_VENUE_CRED_XO_API_KEY=''
export PREDICTEFY_VENUE_CRED_XO_API_SECRET=''
export PREDICTEFY_VENUE_CRED_XO_API_PASSPHRASE=''

The name is PREDICTEFY_VENUE_CRED_<VENUE>_<FIELD>. <VENUE> is the venue slug upper-cased with separators removed, so polymarket_us becomes POLYMARKETUS and can never be confused with POLYMARKET. <FIELD> is the request field in SCREAMING_SNAKE_CASE, so ACCESS_TOKEN becomes accessToken. Any value set this way is redacted from CLI output like the other secrets.

watch opens the hosted WebSocket, prints frames until you press Ctrl-C, then unsubscribes and closes the socket cleanly.

Terminal window
predictefy watch orderbook <marketId> --venue polymarket
predictefy watch orderbook <marketId> --venue polymarket --raw

--raw emits each frame as one line of JSON (NDJSON) instead of the human summary, which is the form to pipe into another process. watch itself rejects --json: a stream has no single envelope.

watch orderbook, watch trades, and watch price each address one market on one venue, so they require an explicit --venue; watch price also requires --market-address, the on-chain market contract address.

watch arbitrage requires a plan entitling the arbitrage feature. The entitlement is re-checked while the socket is open, so a denial — or a mid-stream revocation — arrives as a PLAN_UPGRADE_REQUIRED error frame on a socket that stays open. The CLI prints those error frames to stderr rather than exiting silently, so a revoked stream never looks like a quiet market. A venue that does not serve a subscription answers NOT_SUPPORTED the same way, on every verb — order books, trades, prices, and feed tickers included.

Ctrl-C is the only clean ending. If the socket closes on its own — a server restart, an auth rejection, a dropped connection — the CLI prints the close code and reason to stderr and exits non-zero, so a dead stream is never mistaken for a quiet one.

The hosted stream requires an API key, so watch fails fast with a named error when none is configured, before opening a socket the server would immediately close.

See Streaming for venue coverage and the WebSocket API for the frame shapes.