Repository navigation
feat: let a one-line agent prompt set up Zerion via init + the skill - #128
Merged
Merged
Conversation
Agent prompts that use the CLI currently have to spell out setup and the rules for on-chain work. This moves that knowledge into the CLI and the skill, so a prompt can be the user's request plus `npx -y zerion-cli@latest init -y`, and work the same in Claude Code, Codex, Cursor and Gemini CLI. init, when run by an agent: - Installs the CLI globally from npx. Under npx the temp copy is first on PATH, so the old `zerion --version` check always passed and init never installed anything. It now reads the global copy via `npm root -g`. - Upgrades a global copy older than the running one, instead of skipping. - Detects Codex by CODEX_SANDBOX / CODEX_CI / CODEX_THREAD_ID (as @vercel/detect-agent does), not CODEX_HOME, and uses `gemini-cli`, the id `skills add -a` accepts. - Installs the skill for every agent on the machine, running agent first. - Still never blocks on browser login without a TTY. Inside an agent it names `zerion login --browser` (also as `next` in the JSON) for the agent to run in the background; the key fallback hint now says `--browser` too, since plain `zerion login` needs a TTY. - Prints the packaged SKILL.md path (and adds `skill` to the JSON), for agents that only load skills at session start. Skill: - SKILL.md: a setup check that skips finished steps, rules for every on-chain task (exact balances, gas vs. proceeds, swaps only via swap/bridge/send, signing-link handling, scope), routing for compound requests. Fixes the claim that every trade needs an agent token. - New capabilities/defi-exit.md for withdraw/unstake/redeem/claim/repay. - bundle.md: rules for hand-built groups (protocol legs only). Docs and help use `npx zerion-cli@latest init`: a bare name runs whatever global copy is installed, so returning users would never get new code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
evgeth
force-pushed
the
claude/zerion-ai-version-update-68a699
branch
from
October 3, 2026 08:56
f161d79 to
5bef2f2
Compare
…emver - defi-exit.md, SKILL.md: the user's request sets the scope, and CLI reads only confirm what exists inside it. `positions --defi --chain` returns every protocol on the chain, so treating the request as a hint could exit positions the user never asked about. Those now only come up as suggestions after the exit. - A swap that spends tokens an earlier leg brings in can't share its bundle: `swap --prepare` rejects an insufficient balance, and `bundle` checks current balances, not future inflows. The protocol leg goes alone unless the wallet already holds enough to cover the swap. - init: isOlderVersion follows semver precedence instead of dropping prerelease tags, so a `next` build upgrades to its release and to newer `next` builds. A release is still never replaced by its own prerelease. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found by running an agent against the new skill end to end. - `zerion swap … --quote` prints the price and stops, skipping the balance check. An exit's gas-vs-proceeds check needs to price tokens a claim or unstake hasn't delivered yet, and `--prepare` rejects those, so agents improvised by importing CLI internals and quoting with another holder's address. When the balance is short the price is marked indicative (`enoughBalance: false`, no network gas or protocol fee), and the insufficient-funds error now points to `--quote`. SKILL.md, trading.md and defi-exit.md use it for pricing. - SKILL.md: a signing link belongs to the run that printed it. Once that run ends, don't re-share it: the CLI no longer gets the result, and the transaction rides in the link, so signing it and a fresh one could execute twice. Check the chain, then generate a new link if needed. - init: decide "already installed globally" by comparing this package's real path with the global install, not by looking for `_npx` in argv. Run from a project's node_modules, init used to claim a global install that didn't exist; it now installs or upgrades one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In an agent test run, the agent wrote its viem script to a temp file:
`require('viem')` failed there (resolution follows the script's location,
not the cwd), and copying the script into the CLI's own folder failed too
(the package is ESM, so `.js` files there can't `require`). Point agents
at `NODE_PATH="$(npm root -g)/zerion-cli/node_modules" node script.js`
instead of writing files into the install.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- `zerion bridge … --quote` lists every route and its price, then stops. Plain `bridge` lists routes only when there are several and executes a single one, and it refuses a short balance; `--quote` always lists, never executes, and prices tokens the wallet doesn't hold yet (marked `enoughBalance: false`, indicative). An agent in a test run reached for `bridge --quote` and the flag was silently ignored. The insufficient- funds error suggests it, and `--quote --prepare` is rejected. The listing and the balance check move into tested helpers; plain `bridge` behaves as before. - SKILL.md: when sharing a signing link, tell the user what to expect — app.zerion.io shows the full review first, then asks them to connect a wallet if none is connected, and it must be the wallet that owns the signing address. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts were doc text where both sides edited the same lines: - SKILL.md: kept this branch's setup check and took main's new Node minimum (22.12, or 20.19 on Node 20). Added one setup-check line for main's new `unsupported_node` error: tell the user to upgrade instead of patching dependencies. - capabilities/bundle.md: took main's removal of the per-file Node minimum (stated only in SKILL.md now) and kept this branch's corrected auth sentence (read-only wallets need no agent token). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The skill is installed from main while the CLI comes from npm releases, so an agent can read these docs on a CLI that predates `--quote`. 1.10.0 silently ignores the flag and runs the swap or bridge instead of pricing it: a read-only wallet gets a signing link, and a wallet with an agent token would execute immediately. Raise the setup check's minimum from 1.7.0 to 1.11.0, the release this branch lands in, so an older CLI is upgraded through `init` first, and note the requirement next to `--quote` in trading.md and defi-exit.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ckscout - `zerion chains` prints each EVM chain's `chainId` (decimal) and `chainIdHex`, from the `external_id` the chains API already returns. Agents need the number for ABI lookups and the hex form for a hand-built envelope's `chainId`. Solana gets none (its external id isn't an EVM chain id). The table view gains a Chain ID column. - defi-exit.md: fetch ABIs from Sourcify's keyless v2 API by chain id, following `proxyResolution` to implementations. The `<chain>.blockscout.com` pattern didn't exist for many chains and its API started returning Cloudflare challenges under light use; Sourcify found all 16 DeFi contracts tested across Ethereum and Base. Etherscan's V2 API is a fallback only when the user has ETHERSCAN_API_KEY set, since it rejects keyless requests. No verified ABI means stop, not scrape or guess. - bundle.md and SKILL.md point at the new chain id fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`zerion chains --json` now prints each chain's `rpcUrls`: the public HTTPS endpoints listed in the chains API's `rpc.public_servers_url`, in catalog order, WebSocket URLs dropped. None needs a key. In a keyless test, 134 of the 177 listed HTTPS URLs answered with the right chain id, covering 55 of 65 EVM chains, a superset of the 46 that the `<chain>.drpc.org` naming pattern reached. SKILL.md: for exact balances and test calls, use $ETH_RPC_URL if set, otherwise try `rpcUrls` in order, skipping any that errors or answers with a different chain id; if none answers, say so instead of picking an RPC. This replaces the hard-coded dRPC pattern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
For an agent to do on-chain work with the Zerion CLI today, the prompt has to spell out a lot: how to install and log in, which version is needed, how to register a read-only wallet, and the rules for building and signing transactions safely. That makes prompts long, hard to read, and out of date as soon as the CLI changes.
This PR moves that knowledge into
zerion initand thezerionskill, so a prompt can be just the request plus one fixed line:The agent runs
init, which installs or upgrades the CLI and the skill, then readsSKILL.mdand works out which capability docs the request needs. Nothing here is exit-specific, and it should behave the same in Claude Code, Codex, Cursor and Gemini CLI.What changed
zerion init(cli/commands/init.js)PATH, sozerion --versionalways succeeded.initreported "already installed" and never rannpm install -g, even on a fresh machine. Run from a project'snode_modules, it made the same false claim, because it only looked for_npxin the path. It now finds the global copy via`npm root -g`/zerion-cliand compares real paths: if this process is the global copy (including annpm linked checkout) it skips, otherwise it installs or upgrades.CODEX_SANDBOX/CODEX_CI/CODEX_THREAD_ID, the markers@vercel/detect-agentuses and thatnpx skillsrelies on, instead ofCODEX_HOME.CODEX_HOMEstill relocates~/.codex.gemini-cli.skills add -a geminiwas rejected as an invalid agent.~/.claude,~/.cursor,~/.codex, so a prompt pasted into Codex on a machine that also had Claude Code installed the skill into Claude Code only.initwould leave no skill installed. Instead:initprintszerion login --browserwith instructions to run it in the background and show the user the URL."next": "zerion login --browser".zerion login --browsertoo, because plainzerion loginexits withnot_interactivewhen there's no TTY.SKILL.md.initprints the path of the skill shipped in the package and addsskillto the JSON. Agents load skills at session start, so a skill installed mid-session may not be visible yet.Skill
SKILL.md:swap/bridge/send(never hand-encoded), signing-link handling, scope discipline.capabilities/defi-exit.md: find positions, pick the way out (including selling the receipt token vs. waiting out a cooldown), research the contract (ABIs from Sourcify, plus viem from the CLI install), build the protocol step, and the "after the exit" review that stops and waits.capabilities/bundle.md:parsePreparedGroupanddecideBundleRoute;routealone decides the signing path.bundleignores--walletand takes the signer from each envelope. The docs now say so instead of telling agents to pass it.--quoteonswapandbridgePrints the price and stops, skipping the balance check. An exit's gas-vs-proceeds check has to price tokens that a claim or unstake hasn't delivered yet, and
--preparerejects those withinsufficient_funds. In an agent test run, the agent worked around this by importing CLI internals and quoting with another holder's address.enoughBalance: falsewith a note that the price is indicative, since the API leaves out network gas and the protocol fee until the tokens are there.--quoteand--prepareare rejected together (conflicting_flags).insufficient_fundserror now suggests--quote.bridge … --quotelists every route and its price, then stops. Plainbridgelists routes only when there are several, executes a single one, and refuses a short balance.--quotealways lists, never executes, and prices tokens the wallet doesn't hold yet. An agent in a test run triedbridge --quotebefore it existed and the flag was silently ignored. The route listing and balance check moved into tested helpers; plainbridgebehaves as before.SKILL.md,trading.mdanddefi-exit.mduse--quotefor pricing, and the CLI help lists it for both commands.Signing links are one-time
SKILL.mdnow says a link belongs to the run that printed it. Once that run ends, the agent shouldn't re-share it: the CLI no longer receives the result, and because the transaction travels inside the link, signing it and a fresh one could execute the action twice. The agent checks the chain first, then generates a new link if nothing went through. An agent in the same test run had re-shared an expired link.Chain ids and public RPCs in
zerion chains; ABIs from Sourcifyzerion chainsprints each EVM chain'schainId(decimal) andchainIdHex, taken from theexternal_idthe chains API already returns. Agents need the number for ABI lookups and the hex form for a hand-built envelope'schainId. Solana gets none. The table view gains a Chain ID column.zerion chains --jsonalso prints each chain'srpcUrls: the public HTTPS endpoints from the chains API'srpc.public_servers_url, in catalog order, without WebSocket URLs. None needs a key. In a keyless test, 134 of the 177 listed HTTPS URLs answered with the right chain ID, covering 55 of 65 EVM chains. The<chain>.drpc.orgpattern the docs used before reached 46, all of which the catalog also covers.SKILL.mdnow says to use$ETH_RPC_URLif set, otherwise tryrpcUrlsin order, skipping any that errors or answers with a different chain ID, and to say so if none answers.defi-exit.mdgets ABIs from Sourcify's keyless v2 API by chain ID, followingproxyResolutionto implementation contracts. Blockscout's<chain>.blockscout.comdidn't exist for many chains we tried, and its API started returning Cloudflare challenges after a few requests; Sourcify found all 16 DeFi contracts tested across Ethereum and Base. Etherscan's V2 API is a fallback only when the user already hasETHERSCAN_API_KEYset, since it rejects keyless requests. With no verified ABI, agents stop rather than scrape explorer pages or guess.Telling users which wallet signs
When sharing a signing link,
SKILL.mdnow has the agent tell the user what to expect. app.zerion.io shows the full review first: signing address, balance changes, fee, and a security check. If no wallet is connected, it then asks them to connect one, and it must be the wallet that owns the signing address. I confirmed the page's behavior in a browser with no wallet connected.npx zerion-cli@latest initin docs and helpA bare
npx zerion-cliruns whatever global copy is installed. With zerion-cli 1.6.0 installed globally, barenpx zerion-cli --versionprinted 1.6.0, and@latestprinted 1.9.1. Becauseinitinstalls globally, returning users would otherwise never run new code. The README, the router'ssetup.inithelp, theinitHELP examples and two partner docs now use@latest.Testing
main), including 17 newinittests, 6 for--quoteonswapandbridge, and 5 for chain IDs and RPC URLs:skillpathnode_modules, and from the global copy itself, using a fakenpmnextprereleases)npm test's**pattern needs Node 21+; on 20, list the test files explicitly. CI uses Node 24.npm pack, thennpx -y file:<tgz> init -ywith a tempHOMEcontaining~/.claudeand~/.codex,CODEX_THREAD_IDset and no API key. Result:nextwere printed~/.agents/skills/zerion("universal: Codex") and linked into Claude CodeSKILL.mdpath was printedReviewer notes
Merge this, then release right away.
npx skills addinstalls the skill frommain, but the CLI comes from npm. The skill now requires CLI 1.11.0 (the release this lands in) before using--quote. 1.10.0 silently ignores--quoteand runs the swap or bridge: with a read-only wallet that produces a signing link, and with an agent token it would execute. Until 1.11.0 is on npm, agents following the new skill stop at the version check, which is safe but blocks them, so merge the release PR soon after this one.JSON output change: the skills step's JSON now reports
agents: [...]instead ofagent.Not in this PR: three CLI follow-ups that would remove more rules from the docs:
bundlechoosing the web-app route on its own for read-only wallets--no-waitflag that prints the signing link and exitsbundlerefusing hand-built swap/approve/transfer calls🤖 Generated with Claude Code