geodesics is gasless, self-custodial cross-chain swaps as one command. The agent holds only the token it wants to swap; gas and fees come out of the input, funds never leave the agent’s own wallet, and settlement is typically 5-15 seconds, including cross-chain. It works in both directions across Base, Ethereum, Arbitrum, Optimism, Polygon, BNB, Robinhood Chain, and Solana.
The package doubles as an agent skill: a packaged SKILL.md for agent runtimes such as Claude Code and Cursor, so an agent can drive these commands unattended. This page is the command reference.
New here? The Quickstart walks a fresh agent to its first swap in about 5 minutes.
Install
Configure
geodesics init walks through everything below interactively: it first asks which wallet the agent swaps with (create or import its own keys, or plug in a Virtuals ACP agent wallet), validates each value, stores wallet keys in the OS keychain, saves the rest to a .env in the current project, or to ~/.geodesics/.env for all your projects if you choose, and finishes by installing the agent skill for your AI tools. The keychain is macOS Keychain, Windows Credential Manager, or Secret Service on Linux, and entries are encrypted at rest, so no key sits in a plaintext file. On a system without a keychain, such as a headless server, init asks before saving a key to the .env as plain text; pass --allow-plaintext-key to pre-approve that in scripted setups.
The wallet profile is chosen by the credentials you set, no mode flag anywhere. The agent’s own wallet: a raw EVM key with no AGENT_WALLET_ID; the address is derived from the key, and the wallet onboards itself during its first swap from each chain, gasless. A Virtuals ACP agent wallet: setting AGENT_WALLET_ID selects it, and the signer key is then the base64 MIG… authorization key from the dashboard. A key that does not match its profile is rejected with a message that says exactly which variable to change.
Load order: a working-directory .env wins, then ~/.geodesics/.env, and real shell env vars override both. Wallet keys specifically resolve as a shell env var first, then the keychain, then a .env value. Setup is a one-time user action; how agents behave around it is covered on the Agent skill page.
On-chain reads, such as balances and sweep amounts, use public RPCs with automatic fallback across several providers. To pin a dedicated endpoint, set the chain’s env var:
ETH_RPC_URL, BASE_RPC_URL, ARBITRUM_RPC_URL, OPTIMISM_RPC_URL, POLYGON_RPC_URL, BNB_RPC_URL, ROBINHOOD_RPC_URL, or SOLANA_RPC_URL; it is tried first, with the public endpoints kept as fallback.
Commands
All commands support--json for a single machine-readable object on stdout and --verbose to log HTTP calls to stderr; the Agent skill page covers --json output and what an agent should do on each error code.
Swap
--token-in/--token-out: a token alias likeusdc,virtual,weth,eth,pol,matic,bnb,usdt,usdg, orsol, or a raw token address on that chain. Which alias resolves on which chain is in the alias reference;usdtresolves only on Solana.--chain-in/--chain-out: a chain alias likebase,ethereum,arbitrumorarb,optimismorop,polygon,bnborbsc,robinhoodorrh, orsolana, or a numeric chain id.- Chain notes: on BNB,
usdcis the Binance-Peg token with 18 decimals, handled automatically. Robinhood Chain has no USDC; its stable isusdgand its gas token alias iseth. Both directions are live: the first Robinhood-origin swap runs the usual one-time activation, carried by USDG. --amount-intakes human units for aliased tokens. For a raw token address, pass--amount-rawin the token’s base units instead; decimals are not known for arbitrary tokens.--maxsweeps the entire input-token balance: an EVM token, or an SPL token on Solana origin. A native gas token like ETH or SOL cannot be swept, and--maxcannot be combined with--amount-inor--amount-raw.--recipientoverrides the delivery address, which defaults to the agent’s own wallet on the destination chain.--slippage-bpsoverrides max slippage. The per-route default is tight for stables and wider for volatile tokens.--dry-runprices the swap and returns the quote without signing or submitting anything.- One command does the whole route, including cross-chain. Never chain two swaps yourself unless an error tells you to.
originTxHash / deliveryTxHash. Pass --timeout-s to wait longer.
First swaps are onboarded automatically, and the two wallet profiles behave differently:
- The agent’s own wallet needs no preparation, ever. Its first swap FROM a chain carries a one-time signed authorization inside the swap itself, gasless, and delivery INTO any chain just works: whatever lands there can always swap back out, because the wallet onboards itself whenever it first swaps out of that chain.
- A Virtuals wallet swapping FROM a new chain runs a one-time ~15 second activation first, paid from the wallet’s stable on that chain. Swapping INTO an EVM chain it has never used runs a one-time activation flow first: ~1 unit of the origin chain’s stable is piped over, the chain is activated, and the remainder returns to the origin. Adds about a minute and a few cents, once per chain, and guarantees the delivered assets can always swap back out. Keep ~1 USDC or USDG spare on the origin chain for this. If the swap itself delivers the chain’s stable (
usdc/usdg), there is no pipe: the chain is activated right after settlement instead. - Swapping INTO Solana needs nothing from the Solana wallet: delivery works with zero SOL, and cross-chain swaps back out are gasless. Only a same-chain Solana swap later needs ~0.005 SOL; that swap fails fast with
NEEDS_SOL_TOPUP, and--confirm-pipeon the retry funds it automatically.
Withdraw
--token flag, and at the start of the flow the CLI prints your
stable balance on the origin chain. Same-chain it is a plain transfer; add --chain-out to deliver
on another chain instead.
- The withdrawn token is always the chain’s canonical stable:
usdcon every chain, orusdgon Robinhood Chain where that is the canonical USD token. To move any other token, swap it to USDC first withgeodesics swap. --chain/--chain-out: a chain alias likebase,ethereum,arbitrumorarb,optimismorop,polygon,bnborbsc,robinhoodorrh, orsolana, or a numeric chain id.--amounttakes human units;--amount-rawgives the amount in the stable’s base units instead.--maxsweeps the entire stable balance on the origin chain, and cannot be combined with--amountor--amount-raw.--tois the recipient address, always required. For a same-chain withdrawal it must differ from the agent wallet itself.- Cross-chain withdrawals deliver the destination chain’s canonical stable. A withdrawal from a USDC chain to Robinhood Chain delivers USDG, and slippage can apply as on any bridge.
--dry-run,--slippage-bps,--confirm-pipe, and--timeout-sbehave exactly as they do for swap. Slippage only matters cross-chain; a same-chain transfer cannot slip.
Status
Balance
--chain takes a chain alias, --token a token alias valid on that chain or a raw token address/mint, --wallet overrides the agent wallet for that chain family. --json returns { chainId, chain, wallet, token, symbol?, raw, formatted? } where raw is a base-unit decimal string and formatted is human units; formatted is absent when a raw address’s decimals are unknown.
If every RPC endpoint fails the command exits 1 with an error. Retry; it does not mean a zero balance.
Delegation check / manual activation
Rarely needed;swap does this automatically.
activate is a no-op by design: there is nothing to activate manually, because the first swap from each chain onboards the wallet inside the swap itself. delegation reports the wallet’s per-chain state for either profile, including a wallet that is delegated to another provider; Geodesics never replaces an existing delegation, so such a wallet cannot originate swaps on that chain.
Slippage
The server picks a per-route default, about 3% for volatile outputs and 0.5% for stables, so most swaps need nothing. Override for one swap with--slippage-bps <bps>, or set a persistent default:
--slippage-bps beats config set slippage, which beats the server default. When a non-default slippage is in effect the swap prints a slippage: <bps> line. Setting 1000 bps or higher needs interactive confirmation, or --yes in a script. Raising slippage is the usual fix for a refunded swap: the price moved past tolerance, common on volatile or small cross-chain swaps.
Errors
Every error comes back with a code and a plain-language message. Exit codes:0 is success; 1 is an error, with the reason in JSON error.code; 2 means the swap ended failed or refunded, with the input returned to the origin wallet. The full code table with the action to take on each lives on the Agent skill page.
Safety notes
- Swaps move real funds. Use
--dry-runto price a swap without executing it. - An interrupted command does NOT cancel a submitted swap. Re-running the command gets a fresh quote and can create a second swap, so check
geodesics statusfirst to find out what the interrupted run did.
