
Polymarket
- 55 installs
- 19 repo stars
- Updated March 16, 2026
- mvanhorn/clawdbot-skill-polymarket
Helps with ai & agent building tasks during AI-assisted development.
About
polymarket is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- polymarket
- AI & Agent Building
- AI-coding skill
Polymarket by the numbers
- 55 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #6,762 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mvanhorn/clawdbot-skill-polymarket --skill polymarketAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 55 |
|---|---|
| repo stars | ★ 19 |
| Last updated | March 16, 2026 |
| Repository | mvanhorn/clawdbot-skill-polymarket ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Polymarket
Query Polymarket prediction markets and trade from the terminal. Browse odds, research events, compare markets, track your portfolio, stream live data, bridge funds, and execute trades - all through natural language.
Polymarket exposes 4 separate APIs plus the Gamma convenience layer. This skill covers all of them.
Setup
Read-only commands work immediately (no install needed). Browsing, searching, trending, categories, market research, and comparison mode all use the public Gamma API.
For trading, order books, price history, and advanced features, install the Polymarket CLI (Rust binary, v0.1.5+):
brew install polymarket/tap/polymarket-cliFor trading, set up a wallet:
polymarket wallet create
polymarket approve setOr manually configure ~/.config/polymarket/config.json with your private key. See the CLI docs for details.
The CLI also provides an interactive REPL:
polymarket shellUse --output json on any CLI command for machine-readable output suitable for scripting and piping.
Commands
Browse Markets (no CLI needed)
# Trending/active markets (sorted by 24h volume)
python3 {baseDir}/scripts/polymarket.py trending
# Trending with more results
python3 {baseDir}/scripts/polymarket.py trending --limit 20
# Search markets by keyword
python3 {baseDir}/scripts/polymarket.py search "trump"
# Get specific event by slug
python3 {baseDir}/scripts/polymarket.py event "fed-decision-in-october"
# Get markets by category
python3 {baseDir}/scripts/polymarket.py category politics
python3 {baseDir}/scripts/polymarket.py category crypto
python3 {baseDir}/scripts/polymarket.py category sports
python3 {baseDir}/scripts/polymarket.py category tech
python3 {baseDir}/scripts/polymarket.py category entertainment
python3 {baseDir}/scripts/polymarket.py category science
python3 {baseDir}/scripts/polymarket.py category businessTrending Markets Dashboard (no CLI needed)
Show a categorized dashboard of the hottest markets across Polymarket. Combine trending with category filters to build a full overview.
# Full trending dashboard - run these in sequence to build a picture:
python3 {baseDir}/scripts/polymarket.py trending --limit 10
python3 {baseDir}/scripts/polymarket.py category politics --limit 5
python3 {baseDir}/scripts/polymarket.py category crypto --limit 5
python3 {baseDir}/scripts/polymarket.py category sports --limit 5
python3 {baseDir}/scripts/polymarket.py category tech --limit 5When the user asks for a "dashboard" or "overview," run all category queries and present the results grouped by section with clear headings. Include volume and current odds for each market.
Market Research Mode (no CLI needed)
Market research combines Polymarket odds with contextual analysis. When the user asks to "research" a market or wants deeper analysis beyond just odds:
1. Fetch the market data using search or event commands 2. Analyze the odds - what does the market imply? Is there an edge? 3. Provide context - use your knowledge to explain what drives the odds 4. Show historical movement - if CLI is available, pull price history 5. Compare to consensus - how do Polymarket odds compare to polls, expert opinion, or other prediction markets?
# Step 1: Find the market
python3 {baseDir}/scripts/polymarket.py search "fed rate cut"
# Step 2: Get detailed event data
python3 {baseDir}/scripts/polymarket.py event "fed-rate-decision-march-2026"
# Step 3: If CLI available, get price history to show trend
python3 {baseDir}/scripts/polymarket.py price-history TOKEN_ID --interval 1d
# Step 4: Check order book depth for liquidity assessment
python3 {baseDir}/scripts/polymarket.py book TOKEN_IDAfter gathering data, synthesize the research into a structured report:
- Current Odds: Yes/No percentages and what they imply
- Volume & Liquidity: How much money is in this market, is it liquid enough to trade?
- Trend: Are odds moving up or down? Any recent spikes?
- Context: What real-world events or data points are driving the odds?
- Key Dates: When does the market resolve? Any upcoming catalysts?
- Risk Factors: What could cause a sudden move?
Market Comparison Mode (no CLI needed)
Compare related markets side-by-side. Useful for finding arbitrage, understanding conditional probabilities, or just seeing how different outcomes relate.
# Compare two or more related markets by searching for each
python3 {baseDir}/scripts/polymarket.py search "trump 2028"
python3 {baseDir}/scripts/polymarket.py search "desantis 2028"
python3 {baseDir}/scripts/polymarket.py search "newsom 2028"When the user asks to "compare markets" or "side-by-side odds":
1. Search for each market the user mentions 2. Present odds in a comparison table format 3. Note volume differences (higher volume = more reliable odds) 4. Flag any apparent inconsistencies (e.g., probabilities that should sum to ~100% but don't) 5. Highlight the spread between related outcomes
Format the comparison as a table:
Market Comparison: 2028 Presidential Election
| Candidate | Yes | Volume | Liquidity |
|---------------|---------|---------|-----------|
| Trump | 32.5% | $4.2M | High |
| DeSantis | 18.1% | $1.8M | Medium |
| Newsom | 12.4% | $890K | Medium |
| Harris | 8.7% | $2.1M | Medium |Portfolio Dashboard (CLI + wallet required)
View your complete portfolio with positions, P&L, and open orders in one view.
# View all open positions
python3 {baseDir}/scripts/polymarket.py positions
# View positions for a specific wallet
python3 {baseDir}/scripts/polymarket.py positions --address 0xYOUR_WALLET
# Check USDC balance
python3 {baseDir}/scripts/polymarket.py wallet-balance
# Check balance for a specific token
python3 {baseDir}/scripts/polymarket.py wallet-balance --token TOKEN_ID
# List all open orders
python3 {baseDir}/scripts/polymarket.py ordersWhen the user asks for a "portfolio dashboard" or "how am I doing," run all three commands (positions, wallet-balance, orders) and present a unified view:
- Positions: Each position with current market price, your entry price (if available), and unrealized P&L
- USDC Balance: Available cash for new trades
- Open Orders: Pending limit orders with price and size
- Total Portfolio Value: Sum of positions + USDC balance
Order Book & Prices (CLI required, no wallet)
# Order book for a token
python3 {baseDir}/scripts/polymarket.py book TOKEN_ID
# Price history (intervals: 1m, 1h, 6h, 1d, 1w, max)
python3 {baseDir}/scripts/polymarket.py price-history TOKEN_ID --interval 1d
# Price history with specific number of data points
python3 {baseDir}/scripts/polymarket.py price-history TOKEN_ID --interval 1h --fidelity 48Wallet (CLI required)
polymarket wallet create
polymarket wallet show
polymarket wallet balance
polymarket wallet balance --token TOKEN_IDTrading (CLI + wallet required)
All trades require --confirm to execute. Without it, the order is previewed only. This is a safety feature - you always see what will happen before it happens.
Cost & Fee Transparency
Before executing any trade, the skill displays:
- Order type: Limit or Market
- Side: Buy or Sell
- Price: Your limit price (or "market" for market orders)
- Size: Number of shares
- Estimated cost: Price x Size for limit orders, or dollar amount for market orders
- Polymarket fee: Polymarket charges no trading fees on the CLOB (Central Limit Order Book)
- Gas fees: On-chain operations (approvals, splits, redeems) require MATIC for gas on Polygon. Typical gas: $0.01-0.05
# Preview a limit order (no --confirm = preview only)
python3 {baseDir}/scripts/polymarket.py trade buy --token TOKEN_ID --price 0.50 --size 10
# Execute a limit order
python3 {baseDir}/scripts/polymarket.py --confirm trade buy --token TOKEN_ID --price 0.50 --size 10
# Sell limit order
python3 {baseDir}/scripts/polymarket.py --confirm trade sell --token TOKEN_ID --price 0.70 --size 10
# Market order: buy $5 worth at current price
python3 {baseDir}/scripts/polymarket.py --confirm trade buy --token TOKEN_ID --market-order --amount 5
# Post-only limit order (rests on book only, never takes liquidity - Jan 2026+)
python3 {baseDir}/scripts/polymarket.py --confirm trade buy --token TOKEN_ID --price 0.45 --size 20 --post-onlyOrders & Positions (CLI + wallet required)
# List open orders
python3 {baseDir}/scripts/polymarket.py orders
# Cancel a specific order
python3 {baseDir}/scripts/polymarket.py --confirm orders --cancel ORDER_ID
# Cancel all orders
python3 {baseDir}/scripts/polymarket.py --confirm orders --cancel all
# View positions
python3 {baseDir}/scripts/polymarket.py positions
python3 {baseDir}/scripts/polymarket.py positions --address 0xYOUR_WALLET---
API Reference
Polymarket exposes 4 distinct APIs plus the Gamma convenience layer. Each serves a different purpose.
1. Gamma API (gamma-api.polymarket.com) - Public, no auth
The high-level convenience API for browsing and searching markets. Used by all read-only commands.
- Base URL:
https://gamma-api.polymarket.com GET /events- List events (params:order,ascending,closed,limit,tag_slug)GET /search- Search markets (params:query,limit)GET /events/slug/{slug}- Event by slugGET /comments- List and filter comments on marketsGET /profiles/{address}- Public user profilesGET /series- Grouped event collections (e.g., "2028 Election" series)GET /sports- Sports metadata including teams, matches, and resolution criteria- GraphQL:
POST /query- Full GraphQL endpoint with subscription support
2. CLOB API (clob.polymarket.com) - Trading
The Central Limit Order Book API for all trading operations. Wrapped by the Polymarket CLI.
- Base URL:
https://clob.polymarket.com GET /prices-history- Historical prices (intervals:1m,1h,6h,1d,1w,max)GET /spread- Bid-ask spread for a tokenGET /fee-rate- Fee structure detailsGET /rewards- Daily maker/taker earningsPOST /order- Place an orderPOST /orders- Batch orders (up to 15 per request)DELETE /order/{id}- Cancel an order- Order scoring - Check maker rebate eligibility before placing orders
- Post-Only orders (Jan 2026) - Orders that rest on the book only, never cross the spread
- Heartbeat API (Jan 2026):
POST /heartbeat- Must send within 10 seconds or all open orders auto-cancel- Used by market makers to maintain order presence
- If heartbeat lapses, all resting orders for that API key are cancelled
3. Data API (data-api.polymarket.com) - Portfolio & Analytics
The dedicated API for portfolio tracking, trade history, and market analytics. No auth needed for public endpoints.
- Base URL:
https://data-api.polymarket.com GET /positions?user={address}- Current open positions- Sort by:
TOKENS,CURRENT,INITIAL,CASHPNL,PERCENTPNL GET /closed-positions?user={address}- Historical closed positionsGET /activity?user={address}- Activity feed- Types:
TRADE,SPLIT,MERGE,REDEEM,REWARD GET /value?user={address}- Portfolio valuation in USDGET /trades- Trade history- Filter by:
user,market,side - Max 500 results per page
GET /holders?market={conditionId}- Top token holders for a marketGET /oi- Open interest across marketsGET /volume- Trading volume across marketsGET /leaderboard- Trader rankings (configurable time period)
Use the Data API for portfolio dashboards and analytics. It provides richer position data than the CLOB API, including P&L calculations and activity history.
4. RTDS WebSocket (wss://ws-live-data.polymarket.com) - Real-time Streaming
Real-time data streaming via WebSocket. Subscribe to topics for live updates without polling.
- URL:
wss://ws-live-data.polymarket.com - Protocol: JSON messages over WebSocket
- Topics:
comments- Real-time comment activity- Events:
comment_created,comment_removed,reaction_created,reaction_removed crypto_prices- Real-time cryptocurrency prices- Assets: BTC, ETH, SOL, XRP
- Sources: Binance + Chainlink oracles
- Dynamic subscription management - Subscribe and unsubscribe to topics on the fly within a single connection
- Useful for building live dashboards, monitoring comment sentiment, or tracking crypto prices that feed into 5-minute crypto markets
5. Bridge API (bridge.polymarket.com) - Cross-chain Deposits & Withdrawals
Bridge funds into and out of Polymarket across multiple chains.
- Base URL:
https://bridge.polymarket.com POST /deposit- Generate deposit addresses- Supported chains: EVM (Ethereum, Polygon, Arbitrum, etc.), Solana, Bitcoin
- Returns a unique deposit address for the selected chain
POST /withdraw(Jan 2026) - Bridge USDC.e to any supported chainGET /supported-assets- List all supported assets and chainsGET /quote- Get cross-chain bridging quotes (fees, estimated time)
Use the Bridge API when a user needs to move funds in or out of Polymarket without leaving the terminal.
---
New Market Types
- 5-minute crypto markets (Feb 2026) - Ultra-short-duration markets on BTC/ETH/SOL price movements. Fed by RTDS crypto_prices data.
- Sports markets - Dedicated sports metadata via Gamma
/sportsendpoint with team info, match schedules, and resolution criteria.
Error Recovery
API Errors (Gamma API)
If the Gamma API returns an error or is unreachable:
- HTTP 429 (Rate Limited): Wait 5-10 seconds and retry. The Gamma API has generous rate limits but can throttle during high-traffic events.
- HTTP 500/502/503: The API is temporarily down. Inform the user and suggest trying again in a minute.
- Connection Error: Check internet connectivity. The API endpoint is
https://gamma-api.polymarket.com. - Empty Results: The search might be too specific. Suggest broader search terms or browse by category instead.
Data API Errors
- HTTP 400 (Bad Request): Check the
useraddress format (must be a valid Ethereum address) or sort parameter spelling. - Empty positions: The address may have no open positions, or the address format may be wrong. Try with and without checksum casing.
- Pagination: Trades endpoint maxes at 500 per page. Use cursor-based pagination for full history.
CLOB API Errors
- Heartbeat timeout: If using the Heartbeat API and the connection lapses for >10 seconds, all orders auto-cancel. Reconnect and re-place orders.
- Post-Only rejection: A post-only order that would cross the spread is rejected instead of filling. Adjust price to rest on the book.
- Batch limit: Maximum 15 orders per batch request. Split larger batches.
Bridge API Errors
- Unsupported chain: Check
/supported-assetsfor current chain support. - Quote expired: Bridge quotes have a TTL. Fetch a fresh quote before executing.
- Minimum amount: Some chains have minimum deposit/withdrawal amounts.
CLI Errors
If the Polymarket CLI returns an error:
- "CLI not installed": Install with
brew install polymarket/tap/polymarket-cli. - "Config not found": The user needs to run
polymarket wallet createfirst. - "Insufficient balance": Show current balance and the required amount.
- "Order rejected": The price may be outside valid range (0-1) or the market may be closed/resolved.
- "Approval needed": Some operations require a one-time on-chain approval. Run:
polymarket approve set - Timeout: CLI commands have a 30-second timeout. If a command times out, it may be a network issue or the Polygon RPC may be slow.
WebSocket Errors
- Connection dropped: RTDS WebSocket may drop on network changes. Reconnect and re-subscribe to topics.
- Invalid topic: Check available topics. Only
commentsandcrypto_pricesare currently supported.
Market Not Found
If a market slug or event is not found:
1. Search for the market by keyword instead of slug 2. Check if the market has resolved (use closed: true parameter) 3. Suggest similar markets based on the search terms 4. Link to polymarket.com for manual browsing
Authentication Issues
- No wallet configured: Guide the user through
polymarket wallet create - Wrong network: Polymarket uses Polygon. Ensure the wallet is on the correct network.
- Insufficient MATIC: On-chain operations need MATIC for gas. Direct user to bridge or purchase MATIC.
Usage Examples
Example 1: Quick odds check
User: "What are the odds Trump wins 2028?"
python3 {baseDir}/scripts/polymarket.py search "trump 2028 president"Output:
Search: 'trump 2028 president'
Trump wins 2028 Presidential Election
Yes: 31.2% | No: 68.8%
Volume: $4.2M
Ends: Nov 05, 2028
polymarket.com/event/trump-wins-2028-presidential-electionExample 2: Trending dashboard
User: "What's hot on Polymarket right now?"
Run trending and present top markets grouped by volume:
Trending on Polymarket
Fed Rate Decision - March 2026
Markets: 3
- Rate cut: 72.3%
- No change: 25.1%
- Rate hike: 2.6%
Total Volume: $8.1M
Bitcoin above $150K by July 2026
Yes: 28.4% | No: 71.6%
Volume: $3.9M
UFC 310 Main Event Winner
Fighter A: 62.1% | Fighter B: 37.9%
Volume: $1.2MExample 3: Market research
User: "Research the Fed rate decision market for me"
The skill fetches market data, then provides analysis:
Market Research: Fed Rate Decision - March 2026
Current Odds:
Rate cut: 72.3% (down from 81% last week)
No change: 25.1% (up from 17% last week)
Rate hike: 2.6% (stable)
Volume & Liquidity:
Total Volume: $8.1M
24h Volume: $420K
Order book depth: Deep (>$50K on both sides)
Trend: Odds of a cut have fallen ~9 points in the past week,
likely driven by stronger-than-expected jobs report on Friday.
Key Dates:
- FOMC Meeting: March 18-19, 2026
- Market resolves: March 19, 2026
Context: The market is pricing in a ~72% chance of a 25bp cut.
This aligns roughly with CME FedWatch tool (68%) and economist
consensus (65-75% for a cut). The slight premium on Polymarket
may reflect retail sentiment skewing more dovish.Example 4: Portfolio via Data API
User: "How's my Polymarket portfolio doing?"
Use the Data API for rich portfolio data:
# Portfolio value
curl -s "https://data-api.polymarket.com/value?user=0xYOUR_WALLET"
# Open positions sorted by P&L
curl -s "https://data-api.polymarket.com/positions?user=0xYOUR_WALLET&sortBy=CASHPNL"
# Recent activity
curl -s "https://data-api.polymarket.com/activity?user=0xYOUR_WALLET"Output:
Portfolio Dashboard
Portfolio Value: $289.80
Positions (sorted by P&L):
Fed Rate Cut (Yes) 100 shares @ $0.65 Current: $0.72 P&L: +$7.00
BTC > $150K July (No) 50 shares @ $0.60 Current: $0.71 P&L: +$5.50
Recent Activity:
TRADE Bought 25 Fed Rate Cut (Yes) @ $0.68 2 hours ago
REDEEM Claimed $12.40 from resolved market 1 day ago
USDC Balance: $142.30
Open Orders: 1 pendingExample 5: Side-by-side comparison
User: "Compare the Republican primary candidates"
Market Comparison: 2028 Republican Primary
| Candidate | Win Primary | Win General | Volume (Primary) |
|---------------|-------------|-------------|------------------|
| Trump | 42.1% | 31.2% | $2.8M |
| DeSantis | 22.5% | 18.1% | $1.4M |
| Haley | 11.3% | 8.9% | $680K |
| Ramaswamy | 6.8% | 4.2% | $320K |
Note: Primary odds sum to ~95% (gap = long-tail candidates).
Win-general odds are conditional on winning the primary.Example 6: Trade with cost preview
User: "Buy 50 shares of Yes on the Fed rate cut at 68 cents"
python3 {baseDir}/scripts/polymarket.py trade buy --token TOKEN_ID --price 0.68 --size 50Output:
Buy Limit Order (PREVIEW)
Token: Fed Rate Decision - Rate Cut (Yes)
Side: BUY
Price: $0.68
Size: 50 shares
Estimated Cost: $34.00
Trading Fee: $0.00 (Polymarket CLOB has no trading fees)
Gas Fee: ~$0.01-0.05 MATIC (only on first approval)
Add --confirm to execute this trade.
This involves REAL MONEY on Polygon.Example 7: Leaderboard and top holders
User: "Who are the top Polymarket traders?"
# Trader leaderboard
curl -s "https://data-api.polymarket.com/leaderboard"
# Top holders for a specific market
curl -s "https://data-api.polymarket.com/holders?market=CONDITION_ID"Example 8: Bridge funds in
User: "I want to deposit funds to Polymarket from Ethereum"
# Check supported assets
curl -s "https://bridge.polymarket.com/supported-assets"
# Get a quote
curl -s -X POST "https://bridge.polymarket.com/deposit" \
-H "Content-Type: application/json" \
-d '{"chain": "ethereum", "asset": "USDC"}'Example 9: Historical price analysis
User: "Show me the price history for this market over the past week"
# Via CLOB API
curl -s "https://clob.polymarket.com/prices-history?tokenID=TOKEN_ID&interval=1d&fidelity=7"
# Or via CLI
polymarket price-history TOKEN_ID --interval 1d --output jsonExample 10: Spread and fee check
User: "What's the spread on this market?"
# Bid-ask spread
curl -s "https://clob.polymarket.com/spread?tokenID=TOKEN_ID"
# Fee rate
curl -s "https://clob.polymarket.com/fee-rate"Safety Notes
- Real money. Trades execute on Polygon with real USDC. Double-check everything.
- All trades require `--confirm`. Without it, you get a preview only. This is non-negotiable.
- The CLI is experimental. The Polymarket team warns: "Use at your own risk and do not use with large amounts of funds."
- Private key security. Your key is stored in
~/.config/polymarket/config.json. Never share it, never commit it. - Gas fees. On-chain operations (approvals, splits, redeems) require MATIC for gas on Polygon.
- Heartbeat API. If you use the heartbeat system for market making, a missed heartbeat (>10s) cancels all your resting orders.
- Market resolution. Markets resolve based on the resolution source specified in each market. Check the resolution criteria before trading.
- Slippage. Market orders execute at the best available price, which may differ from the displayed price in fast-moving markets.
- Liquidity. Low-volume markets may have wide bid-ask spreads. Check the order book before placing large orders.
- Bridge funds. Cross-chain bridging involves smart contract risk. Verify addresses and amounts before confirming.
Related Skills
Looking for more market intelligence? Try these OpenClaw skills:
- /search-x - Search X/Twitter for real-time sentiment on any topic. Pair with Polymarket odds to gauge whether the market is ahead of or behind public opinion.
- /last30days - Deep research on any topic using web + social sources. Use it to build context before placing a trade.
- /parallel - Run multiple research tasks simultaneously. Combine Polymarket odds with news, social sentiment, and expert analysis in one shot.
{
"ownerId": "kn7d7xy7794nh6aaabfga5wwzh7zptdm",
"slug": "polymarket",
"version": "1.0.0",
"publishedAt": 1769068161418
}{
"version": 1,
"registry": "https://clawhub.ai",
"slug": "polymarket",
"installedVersion": "1.0.0",
"installedAt": 1770777484545
}
# Exclude binaries and dev artifacts from ClawHub bundle
node_modules/
*.png
*.jpg
*.jpeg
*.gif
*.mp3
*.mp4
*.zip
*.tar.gz
tests/
test/
__pycache__/
*.pyc
.DS_Store
Polymarket Skill for OpenClaw
Browse prediction markets, check odds, research events, compare markets, track your portfolio, and trade on Polymarket directly from your AI agent.
What it does
- Browse markets - trending, search, filter by category (politics, crypto, sports, tech, and more)
- Check odds - real-time Yes/No prices, volume, end dates
- Market research - AI-powered analysis combining odds with context about the event
- Compare markets - side-by-side odds for related markets with arbitrage detection
- Portfolio dashboard - view positions, P&L, balances, activity history, and open orders
- View order books - see bid/ask depth and spread for any market
- Price history - track how odds have moved over time (1m to max intervals)
- Trade - place limit, market, post-only, and batch orders with built-in safety confirmations
- Leaderboard & analytics - trader rankings, open interest, volume, top holders
- Live streaming - real-time comments and crypto prices via RTDS WebSocket
- Bridge funds - deposit and withdraw across EVM, Solana, and Bitcoin chains
- Manage positions - view open orders, cancel trades, check balances
Quick start
Install the skill
# Via OpenClaw CLI
openclaw install mvanhorn/clawdbot-skill-polymarket
# Or clone directly from GitHub
git clone https://github.com/mvanhorn/clawdbot-skill-polymarket.git ~/.openclaw/skills/polymarketBrowse markets (works immediately, no setup)
Just ask your agent:
- "What's trending on Polymarket?"
- "Search Polymarket for AI regulation"
- "What are the odds on the Fed cutting rates?"
- "Research the Bitcoin $150K market for me"
- "Compare the 2028 presidential candidates"
- "Who are the top Polymarket traders?"
Trade (requires Polymarket CLI + wallet)
1. Install the Polymarket CLI (Rust binary):
brew install polymarket/tap/polymarket-cli2. Set up a wallet:
polymarket wallet create
polymarket approve set3. Use the interactive REPL for exploratory sessions:
polymarket shell4. Ask your agent:
- "Buy 10 shares of YES on [market] at $0.45"
- "Show me my portfolio dashboard"
- "What are my open positions?"
- "Cancel all my orders"
- "Deposit funds from Ethereum"
All trades require explicit confirmation before executing. No surprises.
APIs covered
This skill covers all 4 Polymarket APIs plus the Gamma convenience layer:
| API | Base URL | Purpose | Auth |
|---|---|---|---|
| Gamma | gamma-api.polymarket.com | Browse, search, comments, profiles, sports, GraphQL | None |
| CLOB | clob.polymarket.com | Trading, order books, price history, heartbeat, batch orders | API key |
| Data | data-api.polymarket.com | Positions, P&L, activity, trades, leaderboard, open interest | None (public) |
| RTDS | wss://ws-live-data.polymarket.com | Live comments, crypto prices (BTC/ETH/SOL/XRP) | None |
| Bridge | bridge.polymarket.com | Cross-chain deposits/withdrawals (EVM, Solana, Bitcoin) | Wallet |
Safety
- Trades preview by default. Nothing executes without
--confirm. - This is real money (USDC on Polygon). The Polymarket CLI is experimental software.
- Your private key lives in
~/.config/polymarket/config.json. Keep it safe. - Check the order book before placing large orders in low-volume markets.
- Heartbeat API: missed heartbeats (>10s) auto-cancel all resting orders.
Version
v3.0.0 - Data API (positions, P&L, leaderboard, open interest), RTDS WebSocket (live comments, crypto prices), Bridge API (cross-chain deposits/withdrawals), CLOB additions (heartbeat, post-only, batch orders, spread, fee-rate), Gamma additions (comments, profiles, series, sports, GraphQL), CLI corrected to Rust binary via Homebrew, new market types (5-minute crypto, sports).
License
MIT
#!/usr/bin/env python3
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "requests>=2.28.0",
# ]
# ///
"""
Polymarket prediction market data + trading.
Read-only commands use the Gamma API (no auth needed).
Trading commands wrap the official Polymarket CLI (Rust binary).
"""
import argparse
import json
import os
import shutil
import subprocess
import sys
from datetime import datetime
import requests
BASE_URL = "https://gamma-api.polymarket.com"
# ---------------------------------------------------------------------------
# CLI binary detection
# ---------------------------------------------------------------------------
def find_polymarket_cli() -> str | None:
"""Find the polymarket CLI binary."""
# Check common locations
for p in [
shutil.which("polymarket"),
os.path.expanduser("~/.local/bin/polymarket"),
"/usr/local/bin/polymarket",
]:
if p and os.path.isfile(p) and os.access(p, os.X_OK):
return p
return None
def require_cli() -> str:
"""Return CLI path or exit with install instructions."""
cli = find_polymarket_cli()
if not cli:
print("❌ Polymarket CLI not installed. Trading commands require it.", file=sys.stderr)
print(" Install: curl -sSL https://raw.githubusercontent.com/Polymarket/polymarket-cli/main/install.sh | sh", file=sys.stderr)
sys.exit(1)
return cli
def run_cli(args: list[str], json_output: bool = True) -> dict | str:
"""Run a polymarket CLI command and return output."""
cli = require_cli()
cmd = [cli]
if json_output:
cmd += ["-o", "json"]
cmd += args
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if result.returncode != 0:
err = result.stderr.strip() or result.stdout.strip()
print(f"❌ CLI error: {err}", file=sys.stderr)
sys.exit(1)
if json_output:
try:
return json.loads(result.stdout)
except json.JSONDecodeError:
return result.stdout.strip()
return result.stdout.strip()
# ---------------------------------------------------------------------------
# Gamma API helpers (read-only, no auth)
# ---------------------------------------------------------------------------
def fetch(endpoint: str, params: dict = None) -> dict:
url = f"{BASE_URL}{endpoint}"
resp = requests.get(url, params=params, timeout=30)
resp.raise_for_status()
return resp.json()
def format_price(price) -> str:
if price is None:
return "N/A"
try:
return f"{float(price) * 100:.1f}%"
except Exception:
return str(price)
def format_volume(volume) -> str:
if volume is None:
return "N/A"
try:
v = float(volume)
if v >= 1_000_000:
return f"${v/1_000_000:.1f}M"
elif v >= 1_000:
return f"${v/1_000:.1f}K"
else:
return f"${v:.0f}"
except Exception:
return str(volume)
def format_market(market: dict) -> str:
lines = []
question = market.get('question') or market.get('title', 'Unknown')
lines.append(f"📊 **{question}**")
outcomes = market.get('outcomes', [])
if outcomes and len(outcomes) >= 2:
prices = market.get('outcomePrices', [])
if prices and len(prices) >= 2:
lines.append(f" Yes: {format_price(prices[0])} | No: {format_price(prices[1])}")
elif market.get('bestBid') or market.get('bestAsk'):
lines.append(f" Bid: {format_price(market.get('bestBid'))} | Ask: {format_price(market.get('bestAsk'))}")
volume = market.get('volume') or market.get('volumeNum')
if volume:
lines.append(f" Volume: {format_volume(volume)}")
end_date = market.get('endDate') or market.get('end_date_iso')
if end_date:
try:
dt = datetime.fromisoformat(end_date.replace('Z', '+00:00'))
lines.append(f" Ends: {dt.strftime('%b %d, %Y')}")
except Exception:
pass
slug = market.get('slug') or market.get('market_slug')
if slug:
lines.append(f" 🔗 polymarket.com/event/{slug}")
return '\n'.join(lines)
def format_event(event: dict) -> str:
lines = []
title = event.get('title', 'Unknown Event')
lines.append(f"🎯 **{title}**")
volume = event.get('volume')
if volume:
lines.append(f" Total Volume: {format_volume(volume)}")
markets = event.get('markets', [])
if markets:
lines.append(f" Markets: {len(markets)}")
for m in markets[:5]:
q = m.get('question', m.get('groupItemTitle', ''))
prices = m.get('outcomePrices')
if prices:
if isinstance(prices, str):
try:
prices = json.loads(prices)
except Exception:
pass
if isinstance(prices, list) and len(prices) >= 1:
lines.append(f" • {q}: {format_price(prices[0])}")
else:
lines.append(f" • {q}")
else:
lines.append(f" • {q}")
if len(markets) > 5:
lines.append(f" ... and {len(markets) - 5} more")
slug = event.get('slug')
if slug:
lines.append(f" 🔗 polymarket.com/event/{slug}")
return '\n'.join(lines)
# ---------------------------------------------------------------------------
# Read-only commands (Gamma API)
# ---------------------------------------------------------------------------
def cmd_trending(args):
"""Get trending/active markets."""
params = {
'order': 'volume24hr',
'ascending': 'false',
'closed': 'false',
'limit': args.limit
}
data = fetch('/events', params)
print(f"🔥 **Trending on Polymarket**\n")
for event in data:
print(format_event(event))
print()
def cmd_search(args):
"""Search markets."""
params = {'closed': 'false', 'limit': args.limit}
try:
resp = requests.get(f"{BASE_URL}/search", params={'query': args.query, 'limit': args.limit}, timeout=30)
if resp.status_code == 200:
data = resp.json()
events = data if isinstance(data, list) else data.get('events', data.get('markets', []))
print(f"🔍 **Search: '{args.query}'**\n")
if not events:
print("No markets found.")
return
for item in events[:args.limit]:
if 'markets' in item:
print(format_event(item))
else:
print(format_market(item))
print()
return
except Exception:
pass
# Fallback
data = fetch('/events', {'closed': 'false', 'limit': 100})
query_lower = args.query.lower()
matches = []
for event in data:
title = event.get('title', '').lower()
desc = event.get('description', '').lower()
if query_lower in title or query_lower in desc:
matches.append(event)
continue
for m in event.get('markets', []):
if query_lower in m.get('question', '').lower():
matches.append(event)
break
print(f"🔍 **Search: '{args.query}'**\n")
if not matches:
print("No markets found.")
return
for event in matches[:args.limit]:
print(format_event(event))
print()
def cmd_event(args):
"""Get specific event by slug."""
try:
data = fetch(f'/events/slug/{args.slug}')
if isinstance(data, list) and data:
data = data[0]
print(format_event(data))
markets = data.get('markets', [])
if markets:
print(f"\n📊 **All Markets:**\n")
for m in markets:
print(format_market(m))
print()
except requests.HTTPError as e:
if e.response.status_code == 404:
print(f"❌ Event not found: {args.slug}")
else:
raise
def cmd_category(args):
"""Get markets by category."""
categories = {
'politics': 'politics', 'crypto': 'crypto', 'sports': 'sports',
'tech': 'tech', 'entertainment': 'entertainment',
'science': 'science', 'business': 'business'
}
tag = categories.get(args.category.lower(), args.category)
params = {
'closed': 'false', 'limit': args.limit,
'order': 'volume24hr', 'ascending': 'false'
}
data = fetch('/events', params)
tag_lower = tag.lower()
matches = []
for event in data:
title = event.get('title', '').lower()
tags = [t.get('label', '').lower() for t in event.get('tags', [])]
if tag_lower in title or tag_lower in ' '.join(tags):
matches.append(event)
print(f"📁 **Category: {args.category.title()}**\n")
if not matches:
print(f"(No exact matches for '{tag}', showing trending)\n")
matches = data[:args.limit]
for event in matches[:args.limit]:
print(format_event(event))
print()
# ---------------------------------------------------------------------------
# Order book / price commands (CLI, no wallet needed)
# ---------------------------------------------------------------------------
def cmd_book(args):
"""Show order book for a token."""
data = run_cli(["clob", "book", args.token])
if isinstance(data, dict):
print(f"📖 **Order Book** ({args.token[:16]}...)\n")
bids = data.get("bids", [])
asks = data.get("asks", [])
if asks:
print(" Asks:")
for a in asks[:10]:
print(f" {a.get('price', '?')} — {a.get('size', '?')} shares")
if bids:
print(" Bids:")
for b in bids[:10]:
print(f" {b.get('price', '?')} — {b.get('size', '?')} shares")
else:
print(data)
def cmd_price_history(args):
"""Show price history for a token."""
cli_args = ["clob", "price-history", args.token, "--interval", args.interval]
if args.fidelity:
cli_args += ["--fidelity", str(args.fidelity)]
data = run_cli(cli_args)
if isinstance(data, list):
print(f"📈 **Price History** ({args.token[:16]}..., interval={args.interval})\n")
for point in data[-20:]: # Last 20 points
t = point.get("t", "")
p = point.get("p", "")
print(f" {t} {format_price(p)}")
else:
print(data)
# ---------------------------------------------------------------------------
# Wallet commands (CLI, no trading)
# ---------------------------------------------------------------------------
def cmd_wallet_setup(args):
"""Interactive wallet setup."""
cli = require_cli()
print("🔧 **Wallet Setup**")
print("Running interactive setup. This will guide you through wallet creation.\n")
os.execvp(cli, [cli, "setup"])
def cmd_wallet_show(args):
"""Show wallet info."""
data = run_cli(["wallet", "show"], json_output=False)
print(f"👛 **Wallet Info**\n")
print(data)
def cmd_wallet_balance(args):
"""Show balances."""
print(f"💰 **Balances**\n")
# Collateral (USDC)
data = run_cli(["clob", "balance", "--asset-type", "collateral"], json_output=False)
print(f" USDC: {data}")
if args.token:
data2 = run_cli(["clob", "balance", "--asset-type", "conditional", "--token", args.token], json_output=False)
print(f" Token ({args.token[:16]}...): {data2}")
# ---------------------------------------------------------------------------
# Trading commands (CLI, wallet required, confirmation required)
# ---------------------------------------------------------------------------
def cmd_trade(args):
"""Place a trade (buy or sell)."""
side = args.side
token = args.token
if args.market_order:
# Market order
amount = args.amount
if not amount:
print("❌ --amount required for market orders", file=sys.stderr)
sys.exit(1)
print(f"🔔 **{'Buy' if side == 'buy' else 'Sell'} Market Order**")
print(f" Token: {token}")
print(f" Side: {side.upper()}")
print(f" Amount: ${amount}")
print(f"\n⚠️ This will execute immediately at current market price.")
if not args.confirm:
print(f"\n❗ Add --confirm to execute this trade.")
print(f" This involves REAL MONEY on Polygon.")
return
data = run_cli(["clob", "market-order", "--token", token, "--side", side, "--amount", str(amount)], json_output=False)
print(f"\n✅ Order submitted:\n{data}")
else:
# Limit order
price = args.price
size = args.size
if not price or not size:
print("❌ --price and --size required for limit orders (or use --market-order with --amount)", file=sys.stderr)
sys.exit(1)
cost = float(price) * float(size)
print(f"🔔 **{'Buy' if side == 'buy' else 'Sell'} Limit Order**")
print(f" Token: {token}")
print(f" Side: {side.upper()}")
print(f" Price: {price}")
print(f" Size: {size} shares")
print(f" Cost: ~${cost:.2f}")
if not args.confirm:
print(f"\n❗ Add --confirm to execute this trade.")
print(f" This involves REAL MONEY on Polygon.")
return
cli_args = ["clob", "create-order", "--token", token, "--side", side, "--price", str(price), "--size", str(size)]
if args.post_only:
cli_args.append("--post-only")
data = run_cli(cli_args, json_output=False)
print(f"\n✅ Order submitted:\n{data}")
def cmd_orders(args):
"""List or cancel orders."""
if args.cancel:
if args.cancel == "all":
print("🗑️ **Cancel All Orders**")
if not args.confirm:
print("\n❗ Add --confirm to cancel all open orders.")
return
data = run_cli(["clob", "cancel-all"], json_output=False)
else:
print(f"🗑️ **Cancel Order:** {args.cancel}")
if not args.confirm:
print("\n❗ Add --confirm to cancel this order.")
return
data = run_cli(["clob", "cancel", args.cancel], json_output=False)
print(f"\n✅ {data}")
else:
print(f"📋 **Open Orders**\n")
data = run_cli(["clob", "orders"], json_output=False)
print(data or "No open orders.")
def cmd_positions(args):
"""View positions."""
if args.address:
addr = args.address
else:
# Try to get address from wallet show
try:
data = run_cli(["wallet", "show"], json_output=False)
# Parse address from output
for line in data.split('\n'):
if '0x' in line:
addr = line.strip().split()[-1]
if addr.startswith('0x'):
break
else:
print("❌ Could not determine wallet address. Use --address.", file=sys.stderr)
sys.exit(1)
except Exception:
print("❌ Could not determine wallet address. Use --address.", file=sys.stderr)
sys.exit(1)
print(f"📊 **Positions** ({addr[:10]}...)\n")
data = run_cli(["data", "positions", addr], json_output=False)
print(data or "No open positions.")
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="Polymarket prediction markets")
parser.add_argument("--limit", "-l", type=int, default=5, help="Number of results")
parser.add_argument("--json", "-j", action="store_true", help="Output raw JSON")
parser.add_argument("--confirm", action="store_true", help="Confirm trade execution (required for all trades)")
sub = parser.add_subparsers(dest="command", required=True)
# Read-only (Gamma API)
sub.add_parser("trending", help="Trending markets")
sp = sub.add_parser("search", help="Search markets")
sp.add_argument("query", help="Search query")
sp = sub.add_parser("event", help="Get event by slug")
sp.add_argument("slug", help="Event slug")
sp = sub.add_parser("category", help="Markets by category")
sp.add_argument("category", help="Category name")
# Order book / prices (CLI, no wallet)
sp = sub.add_parser("book", help="Order book for a token ID")
sp.add_argument("token", help="Token ID")
sp = sub.add_parser("price-history", help="Price history for a token ID")
sp.add_argument("token", help="Token ID")
sp.add_argument("--interval", default="1d", help="Interval: 1m, 1h, 6h, 1d, 1w, max")
sp.add_argument("--fidelity", type=int, help="Number of data points")
# Wallet
sub.add_parser("wallet-setup", help="Interactive wallet setup")
sub.add_parser("wallet-show", help="Show wallet info")
sp = sub.add_parser("wallet-balance", help="Show balances")
sp.add_argument("--token", help="Token ID for conditional balance")
# Trading
sp = sub.add_parser("trade", help="Place a trade")
sp.add_argument("side", choices=["buy", "sell"], help="Buy or sell")
sp.add_argument("--token", required=True, help="Token ID")
sp.add_argument("--price", type=float, help="Limit price (0-1)")
sp.add_argument("--size", type=float, help="Number of shares")
sp.add_argument("--amount", type=float, help="Dollar amount (market orders)")
sp.add_argument("--market-order", action="store_true", help="Place market order instead of limit")
sp.add_argument("--post-only", action="store_true", help="Post-only limit order")
# Orders
sp = sub.add_parser("orders", help="List or cancel orders")
sp.add_argument("--cancel", help="Order ID to cancel, or 'all'")
# Positions
sp = sub.add_parser("positions", help="View positions")
sp.add_argument("--address", help="Wallet address (auto-detected if omitted)")
args = parser.parse_args()
commands = {
"trending": cmd_trending,
"search": cmd_search,
"event": cmd_event,
"category": cmd_category,
"book": cmd_book,
"price-history": cmd_price_history,
"wallet-setup": cmd_wallet_setup,
"wallet-show": cmd_wallet_show,
"wallet-balance": cmd_wallet_balance,
"trade": cmd_trade,
"orders": cmd_orders,
"positions": cmd_positions,
}
try:
commands[args.command](args)
except requests.RequestException as e:
print(f"❌ API Error: {e}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"❌ Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()