A friendly CLI for trading on Polymarket from your API wallet — set up a wallet,
search markets by keyword, and place orders, as readable tables or -o json for scripts and agents.
Built on the official polymarket-client SDK (Polymarket/py-sdk), trading from your
deterministic API wallet — the SDK's signature-type-3 deposit wallet, which Polymarket's website labels
"for API use only — do not send funds".
Prerequisite: uv — it manages Python for you, so you don't need a
separate Python install.
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell): irm https://astral.sh/uv/install.ps1 | iexInstall straight from GitHub — no clone needed — and get a poly command available everywhere:
uv tool install git+https://github.com/NetMindAI-Open/polymarket_cli.gitOr from a local clone:
git clone https://github.com/NetMindAI-Open/polymarket_cli.git
cd polymarket_cli
uv tool install . # add --editable to track your local source changes liveVerify, then jump to The flow below:
poly --help
- If your shell can't find
polyafterward, runuv tool update-shelland restart the terminal (uv installs commands into~/.local/bin).- If install complains about a prerelease dependency, append
--prerelease allow.- Update later with
uv tool upgrade poly-cli; remove withuv tool uninstall poly-cli.
git clone https://github.com/NetMindAI-Open/polymarket_cli.git
cd polymarket_cli
uv sync --extra dev # creates .venv with dev deps
uv run poly --helpWith Option B there's no global
polycommand — prefix every example below withuv run(e.g.uv run poly markets search "world cup").
A full session goes: ① set up your wallet → ② check your account → ③ find a market → ④ trade.
flowchart LR
A["① Set up<br/>wallet import"] --> B["② Check<br/>balance · positions"]
B --> C["③ Find<br/>markets search"]
C --> D["④ Trade<br/>buy · sell"]
classDef step fill:#0b1020,stroke:#34d399,stroke-width:1.5px,color:#e2e8f0,rx:8,ry:8;
class A,B,C,D step;
Store your signer key once (your API wallet is derived from it automatically):
poly setup # interactive — paste your key when prompted
poly wallet import 0x<your-signer-key> # or non-interactiveThe key is saved to ~/.config/polymarket/config.json (mode 600). A project .env is not read.
Resolution order: --private-key flag → POLYMARKET_PRIVATE_KEY env → config file.
(See config.example.json for the format.)
poly wallet show # your signer EOA + api_wallet address + config path (never prints the key)
poly wallet address # just the api_wallet address
api_walletis your Polymarket account — it holds your funds and trades. It's the address the website labels "for API use only — do not send funds." Add money through the website's Deposit flow, not by sending crypto toapi_walletdirectly.
poly clob balance --asset-type collateral # your USDC cash
poly data positions # what you hold (defaults to your api_wallet)
poly data value # portfolio valueSearch by keyword — the table shows each market's slug (which you trade with);
full token ids and condition_id are available with -o json:
poly markets search "world cup" # keyword search
poly markets get will-usa-win-the-world-cup # one market by slug / id / URL
poly markets list --limit 20 # browse open marketsExample (poly markets search "world cup"):
question yes_price slug
Will Portugal reach the Round of 16 ... 0.745 will-portugal-reach-the-round-of-16-...
Will Mexico reach the Round of 16 ... 0.62 will-mexico-reach-the-round-of-16-...
(Tables show a readable subset of columns; -o json returns every field.)
Always dry-run first — it builds and signs the order locally and prints it, but never submits:
poly buy --slug will-portugal-reach-the-round-of-16 --outcome yes --usd 1 --price 0.75 --dry-runThen place it for real (shows a preview and asks you to type YES):
poly buy --slug <slug> --outcome yes --usd 1 --price 0.75 # buy $1 of YES at a 0.75 limit
poly sell --slug <slug> --outcome no --size 10 --price 0.40 # sell 10 NO shares at 0.40
poly buy --token-id 4636895... --usd 2 --market # market buy $2 by token idManage your orders afterward:
poly clob orders # open orders
poly clob trades # your trade history
poly clob cancel <ID> # cancel one; or `poly clob cancel-all`Global options (before the command): -o, --output table|json (default table), --private-key.
| Group | Commands |
|---|---|
| (top level) | setup, buy, sell |
wallet |
create, import, show, address, reset |
markets |
search, get, list |
clob |
create-order, market-order, post-orders, orders, order, trades, balance, cancel, cancel-orders, cancel-market, cancel-all |
data |
positions, value |
poly buy/sell are friendly aliases for clob create-order / market-order. Run poly <group> --help
or poly <group> <command> --help for full options.
For buy, sell, clob create-order, and clob market-order:
| Flag | Meaning |
|---|---|
--token-id · --slug · --url |
What to trade — pick one. With --slug/--url, add --outcome. |
--outcome yes|no |
Which side of the market (default yes). Ignored with --token-id. |
--usd · --size |
Spend N dollars or trade N shares. (Limit: either. Market BUY needs --usd; market SELL needs --size.) |
--price |
Limit price per share, between 0 and 1. Required unless --market. Rounded to the market tick. |
--market |
Market order instead of a limit order. |
--max-spend |
Market BUY only: fee-inclusive USD cap (defaults to --usd, so you never overspend). |
--dry-run |
Build and sign locally, print details, do not submit. |
--yes |
Skip the typed-YES confirmation. |
Add -o json before any command for machine-readable output:
poly -o json markets search "election" | jq '.[].slug'
poly -o json data positions 0x9377... | jq '.[].cash_pnl'- Every real submit shows a preview and requires typing
YES(skip with--yes). - Use
--dry-runto see exactly what would be sent — signed locally, never submitted. - Prices/sizes are validated and sent to the SDK as strings, never floats (avoiding the legacy
client's precision bugs). Market BUY is capped by
--max-spendso fees can't overspend.
~/.config/polymarket/config.json holds your key (and, optionally, a wallet to trade from):
{
"private_key": "0x...",
"wallet_address": "0x..." // optional — omit to use the default api_wallet
}- Not built on
py-clob-client-v2(Python) orrs-clob-client-v2(the Rust CLI) — both are outdated trade paths that can't post from deposit wallets. --signature-typeandclob update-balanceare intentionally absent: the SDK supports only the deposit-wallet derivation and has no distinct "refresh balance" call.- Requires Python ≥3.11; run via
uv. Tests are offline:uv run pytest.