Jupiter CLI (jup) — a TypeScript CLI for interacting with Jupiter's products on Solana: Spot, Perps, Lend, Prediction Markets and more. Uses Commander.js for command parsing, @solana/kit for transaction signing, and ky for HTTP requests.
Distribution: See .github/workflows/release.yml — publishes to npm and creates GitHub releases with compiled binaries on version bump to main.
# Run in development
bun run dev
# Compile to standalone binary
bun build src/index.ts --compile --outfile jup
# Format code
bunx prettier --write .
# Run all tests: lint, typecheck, tests
bun run ciEntry point: src/index.ts — initializes config, registers 9 command groups with Commander.
Commands (src/commands/): Static classes that register subcommands. Each delegates to library modules.
ConfigCommand—config list,config setKeysCommand—keys list/add/delete/edit/use/solana-importLendCommand—lend earn tokens/positions/deposit/withdrawPerpsCommand—perps positions/markets/open/set/closePredictionsCommand—predictions events/positions/open/close/historySignCommand—sign --tx <base64>SpotCommand—spot tokens/quote/swap/portfolio/transfer/reclaimUpdateCommand—update(self-update CLI to latest version)VrfdCommand—vrfd check/submit
Libraries (src/lib/):
Asset— token metadata (mint addresses, decimals) for SOL, BTC, ETH, USDC;resolveAsset()for name lookupConfig— manages~/.config/jup/settings.json(activeKey, output format, API key)Signer— loads keypairs from~/.config/jup/keys/{name}.json, signs transactionsKeyPair— generates/recovers keypairs (BIP39 mnemonics, BIP32 derivation)Output— renders data as table (via cli-table3) or JSON based on config; also provides display formatters (formatDollar,formatBoolean,formatPercentageChange)NumberConverter— converts between human-readable and on-chain decimal amountsSwap— shared swap execution logic used by SpotCommand and LendCommand
API Clients (src/clients/):
DatapiClient— Jupiter token data/search APIUltraClient— Jupiter Ultra swap API (quote + execute)PerpsClient— Jupiter Perps API v2 (positions, orders, TP/SL)LendClient— Jupiter Lend API (earn tokens, positions, earnings)PredictionsClient— Jupiter Predictions API v1 (events, positions, orders, history)VrfdClient— Jupiter Token Verification API (eligibility check, payment, execute)
Spot swap flow: token search → Swap.execute → UltraClient.getOrder → Signer.signTransaction → UltraClient.postExecute
Perps flow: PerpsClient.post* → Signer.signTransaction → PerpsClient.postExecute
Lend deposit/withdraw flow: LendClient.getTokens → resolve jlToken → Swap.execute → LendClient.getPositions (updated state)
Predictions flow: PredictionsClient.postOrder → Signer.signTransaction → PredictionsClient.postExecute
Vrfd flow: VrfdClient.checkEligibility → VrfdClient.craftTxn → Signer.signTransaction → VrfdClient.execute
When adding new commands, both input (options/arguments) and output (JSON/table) must be consistent with existing commands so that both humans and AI agents can reliably use and parse them. Check docs/ for the canonical command shapes.
- Option naming: Reuse established option names — e.g.
--key <name>,--address <address>,--side <side>,--amount <usd>,--limit <n>,--asset <asset>. Avoid synonyms for the same concept across commands. - Mutually exclusive options:
--keyand--addressare mutually exclusive (one resolves from keystore, the other is a raw wallet address). Follow this pattern for wallet resolution. - Side values: Accept both long/short forms where applicable — e.g.
yes/y/no/nfor predictions,long/short/buy/sellfor perps. - Subcommand verbs: Use
open/closefor entering/exiting positions,setfor updating,positions/history/marketsfor read-only queries.
- Field naming: Reuse established key names — e.g.
sizeUsd,priceUsd,pnlUsd,pnlPct,feeUsd,signature,positionPubkey,side,asset,leverage. Checkdocs/perps.md,docs/spot.md, anddocs/predictions.mdfor the canonical JSON shapes. - Value types: Dollar amounts are
number, percentages arenumber(e.g.5.97means +5.97%), nullable fields usenull(not0or""), transaction hashes usesignature. - Table headers: Match the JSON key semantics — e.g. a JSON field
signaturemaps to table header "Tx Signature",pnlUsdmaps to "PnL". - Formatters: Use
Output.formatDollar(),Output.formatDollarChange(),Output.formatPercentageChange()for consistent styling. Pass{ decimals: N }toformatDollarwhen explicit precision is needed.
- Prettier with default config (double quotes, semicolons, 80 char width, trailing commas in ES5 positions)
- TypeScript strict mode, ESNext target, bundler module resolution
- All core modules use static methods (no instantiation for Config, Output, NumberConverter, clients)
- Signer and KeyPair use instance methods with static factory constructors