Compass
Use when a user wants on-chain DeFi actions through Compass Labs — supply or borrow on Aave, earn yield in Morpho/ERC-4626 vaults, swap tokens, open perps, trade tokenized equities/stocks, or send gas-sponsored transactions on Ethereum, Arbitrum, or Base — or when they invoke /compass or mention the compass CLI or MCP server. Also use to install or set up the compass CLI or connect the Compass MCP server.From its SKILL.md
npx -y skills add CompassLabs/compass-agent-skill --skill compassAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
18.7 KB, as published. Nobody here has run it
Compass — on-chain DeFi via the compass CLI or MCP server
Overview
Compass Labs exposes a non-custodial DeFi API through two equally-supported surfaces: the compass CLI (a shell binary) and a hosted MCP server (native agent tools over one URL). Whichever you use, action commands/tools return an unsigned transaction ({to, data, value, chainId}) or EIP-712 typed data — Compass never holds keys, signs, or broadcasts.
This skill is the "delegate to Compass" flow: set up whichever backend fits the client, translate the user's plain-English DeFi intent into the right command or tool call, preview it, run it, and hand any returned transaction to the user's wallet to sign. Everything below — the workflow, product-account rules, goal-bundling, and signing — is identical on both backends; only the surface differs (shell flags vs JSON params). Backend-specific mechanics are tagged [CLI] or [MCP].
Two ways to use Compass — CLI or MCP
Compass is reachable two ways, and the concepts in this skill — create the product account first, prepare→sign→submit, bundle multi-step goals, sign with the user's own key — apply to both. Let the user pick which one to use:
- CLI. Install the
compassbinary and drive it from a shell — any shell-capable agent, with--dry-run,--jq,-o toon, and full flag control. See "Setup" below. - Hosted MCP server. If the client speaks MCP (Claude Code/Desktop, Cursor, …), connect the Compass MCP server at
https://api.compasslabs.ai/mcp— no binary to install; the Compass tools appear natively and take JSON arguments. Auth is the same Compass API key as the CLI, sent as anX-API-Keyheader — e.g. for Claude Code:claude mcp add --transport http compass https://api.compasslabs.ai/mcp --header "X-API-Key: YOUR_API_KEY"; setup for other clients: https://docs.compasslabs.ai/v2/Agents/MCP-Server. On connect the server returns its own instructions, and each tool ships a schema — those, not this skill, are the source of truth for MCP tool names and arguments.
Ask the user which backend to use the first time you act on a Compass request, then use that for the rest of the session — don't re-ask per command. Only ask when both are genuinely available; if only one is set up (CLI installed, or MCP tools connected), just use that one and mention the other exists. If the user would rather not be asked (e.g. "just do it", "don't ask me"), skip the question — default to the MCP tools when connected, else the CLI — do the action, and tell them which you used (they can switch anytime). The CLI-only mechanics here — --dry-run, --jq, -o toon, nested --a.b.c flags — don't apply on the MCP path (you pass JSON params and read JSON back), but either way you get back an unsigned tx / EIP-712 to sign with the user's own key (see "Signing & hand-off"), and neither the CLI nor the server holds keys.
When to use
- User wants a DeFi action: "supply USDC to Aave", "find the best USDC vault and deposit", "borrow against my ETH", "swap X for Y", "open a 2x long on ETH", "buy tokenized TSLA", "withdraw my position".
- User invokes
/compass <intent>or mentions thecompassCLI or the Compass MCP tools. - User asks portfolio / risk questions answerable from Compass market data (see
compass risk-recipes). - Not for: custodying keys (the user's key signs — see Signing & hand-off), price charts, or chains/protocols Compass doesn't support.
Workflow
digraph compass_flow {
"Backend ready?\n(CLI installed or MCP connected)" [shape=diamond];
"Set up a backend\n(install CLI / add MCP server)" [shape=box];
"Map intent -> command / tool\n([CLI] --usage/--help [MCP] tool schemas)" [shape=box];
"Read the params\n([CLI] --help flags [MCP] JSON schema)" [shape=box];
"credit/earn/equities?\nensure account exists first" [shape=box];
"Preview\n([CLI] --dry-run [MCP] inspect built tx)" [shape=box];
"Execute" [shape=box];
"Output is unsigned tx / EIP-712?" [shape=diamond];
"Sign with the user's key\n(see Signing & hand-off)" [shape=box];
"Show the result" [shape=box];
"Backend ready?\n(CLI installed or MCP connected)" -> "Set up a backend\n(install CLI / add MCP server)" [label="no"];
"Backend ready?\n(CLI installed or MCP connected)" -> "Map intent -> command / tool\n([CLI] --usage/--help [MCP] tool schemas)" [label="yes"];
"Set up a backend\n(install CLI / add MCP server)" -> "Map intent -> command / tool\n([CLI] --usage/--help [MCP] tool schemas)";
"Map intent -> command / tool\n([CLI] --usage/--help [MCP] tool schemas)" -> "Read the params\n([CLI] --help flags [MCP] JSON schema)";
"Read the params\n([CLI] --help flags [MCP] JSON schema)" -> "credit/earn/equities?\nensure account exists first";
"credit/earn/equities?\nensure account exists first" -> "Preview\n([CLI] --dry-run [MCP] inspect built tx)";
"Preview\n([CLI] --dry-run [MCP] inspect built tx)" -> "Execute";
"Execute" -> "Output is unsigned tx / EIP-712?";
"Output is unsigned tx / EIP-712?" -> "Sign with the user's key\n(see Signing & hand-off)" [label="yes (action)"];
"Output is unsigned tx / EIP-712?" -> "Show the result" [label="no (read-only)"];
}
🖼️ Prefer a picture? A human-friendly version of this flow is in
workflow.excalidraw(this folder) — open it with VS Code's Excalidraw extension or at excalidraw.com.
0. Ensure a backend is ready. Either the compass CLI is installed or the Compass MCP tools are connected — see "Setup" below. If both are available, pick one (per "Two ways" above) and stay on it for the session.
1. Map intent → command / tool. The live surface is the only source of truth for names — they change between versions, so never rely on hardcoded names (including any in this skill). Use references/command-catalog.md only to know which capability area to look in, then confirm the exact spelling against the live surface.
- [CLI]
compass --usage(every command + flag in one shot) orcompass <group> --help. - [MCP] the connected tool list and each tool's schema (tool names mirror the API operation ids, e.g.
v2_earn_vaults,v2_credit_borrow).
Prefer the single highest-level command/tool (or one bundle) that achieves the user's whole goal — see "Delegate the whole goal" below.
2. Read the params before composing. Never infer names from the endpoint or API URL — the #1 cause of failed first runs on either backend.
- [CLI]
compass <group> <command> --help(or in the mono repocli-sdk/docs/compass_<group>_<command>.md). Flags are often nested:--venue.vault.vault-address, not--vault-address. - [MCP] the tool's JSON schema. Objects nest the same way:
"venue": {"type":"VAULT","vault_address":"0x…"}.
3. Preview before you spend a call.
- [CLI]
--dry-runprints the exact request (URL, headers, body) to stderr without calling the API. - [MCP] there's no dry-run, but action tools return the unsigned tx / EIP-712 without broadcasting — inspect what came back and confirm it matches intent before signing. Same safety, different mechanism.
4. Execute, then sign. Run the command/tool. Read-only results (markets, positions, balances) you show or summarize directly. If the result is unsigned — a transaction or EIP-712 typed data — complete it with the user's own key; see Signing & hand-off below. Compass never signs or broadcasts, on either backend.
Account-based products — ensure the account exists first
credit, earn, and tokenized-equities each act through a per-product smart account (a Safe) owned by the user. That account must exist (and, for credit/earn, be funded) before the main action, or it fails. So before any credit / earn / equities action:
- Check whether it's deployed on-chain. These accounts have a deterministic (counterfactual) address the CLI returns even when nothing is deployed there — so an address in the output (or a
balancesresult) does not prove the account exists. Verify deployment:cast code <account-address> --rpc-url "$RPC_URL"→ empty (0x) means it isn't created yet. - If not deployed, create it — run the group's
create-account, then fund it via the group'stransferwhere the group has one. - Then run the action.
One-time per owner per product per chain — skip if it's already deployed. ⚠️ Never equate "the CLI returned an …_account_address" with "the account exists": that address is predicted from the owner and returned regardless of deployment (it can even hold pre-funded tokens while undeployed). Confirm exact command names via --help; pure read-only commands (markets, quotes, positions) need no account.
Perps (global-markets-perps) is different — no product account. It trades on Hyperliquid, so its one-time setup is enable-unified-account + deposit USDC (plus approve-builder-fee / ensure-leverage if needed) — not a create-account. See the perps recipe in references/recipes.md.
Delegate the whole goal — one command, one transaction
Compass is for delegating execution, not hand-orchestrating low-level steps. Map the user's goal to the single highest-level command that achieves it, and prefer one atomic transaction:
- One command does it (a single deposit / borrow / order command) → use that.
- Goal needs several actions (rebalance a portfolio, move funds between vaults, swap-then-deposit) → combine them into one bundle (each product exposes a
bundle-style command — confirm its exact name via--help): a single atomic, all-or-nothing transaction the user signs once. - Anti-pattern — do NOT do this: a chain of separate signed transactions — withdraw (sign) → swap (sign) → deposit (sign) — when one
bundledoes it in a single signature. "Rebalance across 3 vaults" is one bundle tx, not ~20 transactions.
Why: one signature, atomic execution (no half-done state if a later step fails), far less gas. There is no rebalance command — a rebalance is a bundle of withdraw/swap/deposit actions (see references/recipes.md recipe 2). If unsure a single command exists, check compass --usage before falling back to multiple steps.
Signing & hand-off — completing an action
Action commands and MCP action tools both return something unsigned — Compass never signs, holds keys, or broadcasts on either surface. Complete it with the user's own key via cast — full guide in references/signing.md. The two cases are the same whichever backend produced the payload:
- Unsigned transaction
{to, data, value, chainId}(deposit, borrow, manage, bundle…) → sign + broadcast. Pass thedatahex in the[SIG]slot —casttakes raw calldata there:
Default to sign-only (cast send <to> <data> --value <value> --rpc-url "$RPC_URL" --account <keystore>cast mktx→ hand back the signed tx, orcast publishit) and broadcast only after the user confirms — it spends funds irreversibly. - EIP-712 typed data (perps/equities orders, gas-sponsorship) → sign off-chain, feed the signature to the second compass command/tool (e.g. the perps
…_executeor tokenized…_order_submittool on MCP):cast wallet sign --data --from-file td.json --account <keystore> # → 0x<sig>, then: compass … execute --signature 0x<sig>
Keys stay with the user: sign from an encrypted keystore (cast wallet import <name>) or --ledger/--trezor — never --private-key inline (it leaks to shell history and ps).
Setup (do once) — pick a backend
Both backends use the same Compass API key (get one at https://compasslabs.ai/login). If the client speaks MCP, the server is the zero-install path; otherwise use the CLI. Set up one.
[MCP] Connect the hosted server (nothing to install)
The Compass API hosts an MCP server at https://api.compasslabs.ai/mcp (Streamable HTTP). Auth is the API key as an X-API-Key header — no env var, no binary. For Claude Code:
claude mcp add --transport http compass https://api.compasslabs.ai/mcp \
--header "X-API-Key: YOUR_API_KEY"
Per-client setup (Cursor, Claude Desktop, any Streamable-HTTP client): https://docs.compasslabs.ai/v2/Agents/MCP-Server. On connect the server returns its own usage instructions and each tool ships a schema — those are the source of truth for MCP tool names/args, not this skill. If the tools are already connected there's nothing to do; a 401 means the X-API-Key header is missing or wrong.
[CLI] Install the binary
Check first: compass version. If it's missing, tell the user the exact command and confirm before running it (install modifies their system):
- Homebrew (macOS / Linux, if
brewis available):brew install compasslabs/tap/compass— non-interactive; update later withbrew upgrade compass. - In the mono repo: use the local
cli-sdk/compassbinary directly, orgo install github.com/CompassLabs/cli/cmd/compass@latest. - Standalone (recommended for agents — non-interactive):
Installs tocurl -fsSL https://compasslabs.ai/install.sh | bash # macOS / Linux iwr -useb https://compasslabs.ai/install.ps1 | iex # Windows (PowerShell)/usr/local/bin, auto-falling back to$HOME/.local/binif that isn't writable; setCOMPASS_INSTALL_DIRto force a directory (ensure it's onPATH). - Manual: binaries on the releases page.
Check it's current — this CLI changes fast. Command names and flags have changed across versions (groups renamed, subcommands restructured), so a stale binary is a top cause of "unknown command/flag" errors. Don't memorize names — read them from the installed binary (step 1), and keep it reasonably current:
compass version # installed
curl -fsSL https://api.github.com/repos/CompassLabs/cli/releases/latest | grep -o '"tag_name": *"[^"]*"' # latest
If it's behind, offer to update (brew upgrade compass if installed via Homebrew, otherwise re-run the installer — it fetches latest — or go install …@latest); confirm before installing.
Then authenticate (env var is the most reliable for agents):
export COMPASS_API_KEY_AUTH=ck_... # note the _AUTH suffix — NOT COMPASS_API_KEY
compass whoami # verify auth + connectivity
Do not run compass configure non-interactively — it opens a TUI. Agent-mode (structured errors + default TOON output) auto-enables when CLAUDE_CODE / CURSOR_AGENT is detected; no flag needed.
Critical rules — internalize before composing any command
Universal (both backends):
| Rule | Why it matters |
|---|---|
| A Compass API key is required | [CLI] env var COMPASS_API_KEY_AUTH (the _AUTH suffix matters — plain COMPASS_API_KEY is silently ignored). [MCP] the X-API-Key header on the server registration. Either way, missing/wrong → 401 |
| Compass never signs / holds keys / broadcasts | Action output is unsigned (tx / EIP-712) → complete it with the user's key via cast (see "Signing & hand-off"); broadcast only after the user confirms |
| Product account first (credit / earn / equities) | The account has a deterministic address Compass returns even when undeployed — check it's actually deployed (cast code <addr> → 0x = not created), don't just trust that an address came back; if undeployed, create-account + fund, then act. Perps has no product account — one-time enable-unified-account + deposit |
| Amounts are decimal token units | "1.5" = 1.5 USDC, never wei; "ALL" is unsupported — pass an explicit amount |
Surface 4xx bodies to the user | They're actionable (Unknown token symbol, Slippage exceeded — raise slippage, …); a 5xx is safe to retry once |
[CLI] only — shell-surface mechanics; ignore on MCP, where you pass JSON and read JSON:
| Rule | Why it matters |
|---|---|
Pass plain values; read enum options from --help (e.g. --chain base) | Recent builds accept plain values. Only if an optional string flag errors with unmarshalling json response body (older CLI) do you JSON-quote that one flag: --chain '"base"' |
| Never quote required/enum flags | --borrow-token '"USDC"' sends literal "USDC" → "Unknown token symbol" 422 |
| Read the flag Description, ignore the metavar | Metavars like --amount from_token are generator noise, not syntax |
-o table does not unwrap list envelopes | Use --jq '.vaults' to drill into {total, …, vaults:[…]} |
Prefer -o toon or --jq for results you feed back to yourself | 30–60% fewer tokens than JSON |
| Never put a raw private key on the CLI | --private-key 0x… leaks to shell history + ps → use cast's --account (encrypted keystore) or --ledger/--trezor |
[MCP] only:
| Rule | Why it matters |
|---|---|
| Scope big read tools — some return very large payloads | Unfiltered list/balance reads (e.g. the full tokenized-assets market list, or credit/earn balances on a spam-airdropped account) can exceed the client's tool-result token cap. Pass the tool's filters (limit/offset, provider, chain, asset_symbol, search) — don't fetch the whole catalog to read one row |
| Tool schemas + on-connect instructions are the source of truth | They mirror the live API — follow them over any tool name written in this skill |
Full error-recovery table: references/error-recovery.md. Worked end-to-end recipes: references/recipes.md. Signing & broadcasting: references/signing.md.
Quick reference — [CLI] flags
These are CLI-surface conveniences. On [MCP] you pass JSON params and read JSON back, so they don't apply — the equivalent of --dry-run/--jq/-o toon is simply reading (and filtering your request to) the tool's JSON result.
| Goal | Flag |
|---|---|
| Preview without calling the API | --dry-run |
| Extract one field/array for the next step | --jq '.path' |
| Compact output for your own context | -o toon |
| Human-readable result for the user | default (pretty) |
| Verbose request/response diagnostics | --debug |
| Risk math (LLTV cascade, JTD, correlation) | compass risk-recipes |