npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mysten-incubation/sui-agent-pass

v0.1.27

Published

AI builds transactions. A session signer signs. Your pass enforces the rules.

Readme

Sui Agent Pass

Your money. Your rules. AI at work.

Sui Agent Pass lets an AI agent run your onchain finance under a policy you write once. The agent pays, trades, lends and stakes; Sui checks every transaction against the policy at settlement. A policy is more than a spending limit: it names who the agent can pay, which markets it can trade on and at what price, how much lending risk it can take, which validators it can stake with, and how long its access lasts. Each new protocol plugs in as a new policy module.

An owner authorizes a new agent key with Slush. The agent builds its own programmable transactions, a local MCP signer holds the agent key on the owner's machine and signs complete transaction bytes, and the chain decides what executes. No hosted service ever holds a key.

One pass per agent, and the agent never owns anything:

  • Your coins stay in your own address. Setup issues two allowances (sui::allowance) bound to the pass, one per coin. Every agent action draws from your address balance through an allowance, is checked by the pass's policies, and returns its proceeds to your address. The pass never holds a coin.
  • The pass holds the rules and the objects the agent operates. A NAVI lending position is an object that can only be used under its owner's signature, so it sits in the pass where the agent can run it. Only you can take it out, and taking it out hands you the position directly.
  • A receipt in your wallet points at each pass, so from any device you can find your passes, read their positions, and reclaim them. Authority stays with your address, never the receipt.

The pass is an account, not a typed container: each action names its coin. The owner installs one policy per kind of action and coin. Transfers go to recipients the owner named; the agent never supplies an address. Swaps run on the DeepBook and Cetus pools the owner listed, within per-trade and daily caps and above a price floor. Lending supplies collateral to NAVI and, if enabled, borrows against it while keeping the health factor above the owner's floor. Staking puts SUI with the validators the owner listed (or any active one), within per-stake and daily caps; the stake object stays in the pass and unstaking returns the SUI to the owner. An action with no policy for its coin is refused. Revocation ends the agent's term and deletes the allowances. The package references sui::allowance, so it needs protocol 137 or later, which testnet, devnet and mainnet all run. The demo stays on localnet, testnet and devnet; mainnet serves compatibility tests with small sums until launch.

The agent pays its own gas from the session address. Setup seeds an initial gas stipend and issues a separate small SUI allowance for gas; when the session's balance runs low the agent tops it up from that allowance, within its own lifetime cap and a limit per 24 hours from its first top-up, so gas spend is bounded apart from the asset rules, whose daily limits reset at 00:00 UTC (docs/ARCHITECTURE.md §7). Owners cannot bill an agent's transaction gas to the wallet directly yet, because gas is authorized by a signature and sui::allowance cannot authorize it.

Transfers and staking are the real thing on every network. DeepBook, Cetus and NAVI are called through their mainnet interfaces; off mainnet the demo publishes local stand-ins with the same signatures over small mock markets, and the Move manifest lists the real packages as mainnet replacements. See move/protocols/README.md.

This repository is fully self-contained. There is no broker, authorization database, intent adapter, or transaction builder inside MCP.

Install

The package is on npm as @mysten-incubation/sui-agent-pass (the incubation scope, for the dogfood; the launch release will follow). A user needs no clone, no build, and no toolchain. The client ships the per-network deployment IDs (deployments/<network>.json):

npm install -g @mysten-incubation/sui-agent-pass
agent-pass connect   # connect all detected agents, or choose specific ones

That is the only command. For each agent you pick it registers the MCP server and links the agent-pass skill, the playbook built into the package, into the agent's skills folder (Claude Code, Codex, Cursor, Hermes and OpenClaw), so the agent has the tools and the guidance for them. A link follows upgrades; rerun connect if you installed through npx. Then open the agent and tell it what to do with your money. It proposes a pass (propose_authorization) and opens the review page with the proposal in its URL. Connect a wallet, check the rules the agent quoted to you, and sign once; the session key stays local, and the agent sees your signature land on chain and acts within the rules. Claude Code starts the signer when it needs it. In production the page is our site at a fixed origin, so the agent cannot change what you see or sign; in development the same build is served from the local port (see "The site" in docs/ARCHITECTURE.md). There is no setup wizard: the agent composes the rules from your words and the facts the server gives it (coins, pools, balances, quotes), and the review page is where you check them.

On a machine that reaches the internet only through a proxy (a hosted agent's VM such as Meta Muse), the signer and the SDK send every request through HTTPS_PROXY/HTTP_PROXY. A client that starts agent-pass mcp itself must pass those variables on: the MCP SDK's stdio transport hands the server only a small default environment.

For a private publish:

agent-pass connect                          # asks which agents; or --client <name>

Publishing the Move package and installing the Sui toolchain are maintainer steps, never on a user's machine. See the release checklist below.

Use it with your agent

The signer speaks MCP, so any agent that can load an MCP server can use it. The protocol is the same for every client; where each one keeps its server list is not, so connect --client writes or prints the entry in the right place:

| --client | What it does | | ---------------- | ----------------------------------------------------------- | | claude-code | claude mcp add in user scope | | claude-desktop | Writes into claude_desktop_config.json | | cursor | Writes into ~/.cursor/mcp.json | | hermes | Uses hermes mcp add; prints configuration for --session | | codex | Uses codex mcp add; prints configuration for --session | | openclaw | Uses openclaw mcp set in the active OpenClaw profile | | json | Prints a generic mcpServers entry |

The entry is agent-pass mcp, a stdio server the client starts when it needs it and stops with it. It covers every pass on this machine, exposes session_info and sign_transaction, and adds the owner tools (list_passes, propose_authorization, revoke_pass), so the agent can also set a pass up. While it runs it also serves each pass's HTTP signer, which the SDK uses. connect --session <directory> instead points a client at one session's foreground signer (agent-pass serve), for agents that cannot start a process themselves.

OpenClaw needs a release with native openclaw mcp set support. Stop its gateway before connecting (openclaw gateway stop when running as a service), then run agent-pass connect --client openclaw. Restart OpenClaw and start a new chat session afterward. Registration uses OpenClaw's own CLI and its reported managed skills directory, so custom state directories and profiles stay aligned. For a named profile, use OPENCLAW_PROFILE=<name> agent-pass connect --client openclaw; OPENCLAW_HOME and OPENCLAW_STATE_DIR are passed through to OpenClaw. OpenClaw must run on the machine where Agent Pass is installed and have access to a local Node runtime for SDK scripts; remote gateways need their own installation.

Acting is a Node script against the SDK. session_info.sdk.install is the install command (npm install <this checkout> after npm run build while the package is unpublished), then:

import { Agent, pickValidator, send, stake, swap } from '@mysten-incubation/sui-agent-pass/agent';
import { SUI, units } from '@mysten-incubation/sui-agent-pass/domain';

const agent = await Agent.open(directory); // from session_info
const usdc = agent.identity.deployment.coins.find((c) => c.symbol === 'USDC')!;
const out = await agent.submit(
	swap(agent.identity, { coinIn: SUI, coinOut: usdc.type }, units('0.01', 9), units('0.019', 6)),
);
// out.success, out.reason (the owner's rule on a refusal), out.balanceChanges

submit signs through the session signer, submits to Sui and returns the persisted outcome; it throws when nothing executed, so a dry-run refusal is never mistaken for enforcement. docs/AGENT.md documents the SDK and the contract for hand-built PTBs. Agents that do not speak MCP get the same two operations as plain HTTP with the bearer from mcp.token: GET /v1/session and POST /v1/sign with { "transactionBytes": "<base64>" }.

Run the rehearsal

Clone the repository with your authorized GitHub account:

gh repo clone MystenLabs/sui-agent-pass ~/github/sui-agent-pass

Requires Node 22+, npm, and Sui 1.81.1 (mainnet-v1.81.1, the release mainnet runs; npm run toolchain installs it with mvr). The project checks SUI_BIN, then ~/.cache/sui-agent-pass/toolchain/sui, then sui on PATH. Older installations are not used if the project toolchain is present. The single Move package references sui::allowance, so it builds and publishes only with a chain that has it enabled: localnet from this toolchain, testnet, devnet, or mainnet (protocol 138).

cd ~/github/sui-agent-vault
npm ci
npm run toolchain
npm run build
npm run demo

The command starts its own fresh local Sui network, publishes immutable demo contracts, creates separate owner/publisher/session identities, authorizes the session, starts MCP, and prints an owner dashboard URL and Claude connection command. It keeps the chain and signer alive until quit or Ctrl-C. Keys stay in ignored private directories.

Commands in the rehearsal: status, send (5 USDC to the recipient named owner), swap (0.01 SUI on DeepBook), cetus (0.01 SUI on Cetus), supply (0.2 SUI to NAVI), borrow (0.15 USDC from NAVI), stake (1 SUI with the localnet validator), unstake (the held stake, back to the owner), over (11 USDC against a 10 per-transfer limit), revoke, quit. npm run demo -- --smoke runs the sequence automatically and exits. After revocation the allowance objects no longer exist, so a transaction that names one is refused before execution rather than recorded as a chain failure.

The default rehearsal uses a generated test owner, not Slush. It proves chain execution and MCP signing. For the wallet connection/signature flow use the flow below.

Slush + Claude Code

Use a deployed configuration, or npm run devnet -- --owner <address>, which publishes to devnet with a faucet-funded publisher, funds your wallet address from the faucet and writes the deployment to .local/devnet/deployment.json. Tell the agent to pass that file's absolute path as deployment when proposing a pass. Slush offers mainnet, testnet and devnet only. npm run demo -- --wallet keeps a localnet alive and prints a funded throwaway owner key for a wallet that accepts a custom RPC URL; not verified with any.

# Prepare valueless testnet contracts using a separate deployment identity (testnet is the
# default network):
npm run deploy -- create --directory .local/testnet
# If the faucet cannot provide enough funds, the command prints the deployment address.
# Fund it with at least 11 test SUI, then:
npm run deploy -- resume --directory .local/testnet

# Select a private deployment explicitly for each new pass:
node dist/cli.js connect   # then ask the agent; it passes deployment: .local/testnet/deployment.json
# devnet works the same way:
npm run deploy -- create --network devnet --directory .local/devnet

The agent asks what the pass is for and proposes the rules: recipients with per-transfer and daily caps for each coin; for each trade direction the pools, per-trade and daily caps and a price floor; for each lent coin per-action and daily caps, whether borrowing is allowed and a health-factor floor; the validators it may stake with and per-stake and daily caps (a stake is at least 1 SUI, the system's minimum); a lifetime cap per coin and the gas terms. It quotes the exact rules text the page will show, generates a key and opens the review page. Connect Slush; allowances draw only from your address balance, never from coin objects, so the page reads what you hold on both sides and shows how much of your coins the signature converts into that balance to cover the caps, with a faucet link if your wallet is short. Gas for your own signature comes from either side. Sign. One PTB creates the pass and hands you its receipt, converts the coins, issues the allowances over your own balance, installs the policies, opens the pass's NAVI account when lending is allowed, and sends SUI to the session's address balance for gas. The service re-reads everything that landed on chain and compares it with what you reviewed before the signer serves the key.

Register the agents that may use your passes once with connect. It shows the detected agents and offers to connect them all, or choose specific ones. Other / manual setup offers undetected clients, Cursor and a generic MCP configuration; Cursor is excluded from detection and bulk setup. You can also select a client directly with --client <name>. After connecting, restart each connected agent and start a new chat session. The terminal shows a compact status for each agent: green for connected, yellow for manual or incomplete setup, and red for failure. Colors are disabled for redirected output and NO_COLOR. Use agent-pass connect --verbose to see native setup output and configuration/skill paths. Claude Desktop receives the playbook through MCP; optionally add the packaged skill in its settings (the path is shown with --verbose). Then start Claude anywhere:

claude

The registration is agent-pass mcp in Claude Code's user scope, a stdio server Claude starts when it needs it. It contains no key and no token. If that MCP name already exists, remove the old entry with claude mcp remove agent-pass before reconnecting.

node dist/cli.js status --session /absolute/session/directory
node dist/cli.js serve --session /absolute/session/directory    # advanced: a foreground HTTP signer

Closing Claude does not revoke the chain session; the owner page's Stop the agent now button does, and Close the pass returns everything. Your coins never left your address. If the agent opened a NAVI position, Reclaim NAVI position on the owner page takes the account cap into your wallet: the position is then yours to manage on NAVI directly and the agent has nothing to lend on. Each stake the agent opened has a Reclaim button of its own, which moves that StakedSui into your wallet. The pass also provides owner-only policy edits, documented in the agent API guide.

Claude Code plugin

The plugin runs the whole owner flow from inside Claude Code. You describe what the agent may do; Claude proposes rules; the plugin renders them, opens the review page, and you sign once in Slush. After that Claude acts through the same session, with no connect step and no second terminal.

cd ~/github/sui-agent-vault
npm ci && npm run toolchain && npm run build
# Publish with a faucet-funded key, fund your Slush address from the faucet, and write
# .local/devnet/deployment.json (the command prints its absolute path):
npm run devnet -- --owner <your Slush address>
cd ~/anywhere && claude --plugin-dir ~/github/sui-agent-vault/plugin

Then tell Claude Code to use the printed deployment path for this rehearsal, and ask:

Manage 1 SUI and 100 USDC for me. Sell at most 0.1 SUI a day on DeepBook, never below 1.8 USDC. You may pay alice (0x…) up to 10 USDC a time and 20 a day. One week.

Claude calls propose_authorization, prints the rules text the tool returned, and the review page opens. Connect Slush, check that the page shows the same rules, sign. Claude waits on session_info until the pass is confirmed and its policies match, then works within the rules with scripts against the SDK (@mysten-incubation/sui-agent-pass/agent), or with its own PTBs and sign_transaction. /agent-pass:pass-status shows balances and today's usage; /agent-pass:pass-revoke reopens the owner page for the revocation signature. The guidance Claude follows is docs/PLAYBOOK.md, which the MCP serves to every client as the agent-pass://playbook resource; the plugin skills only point at it.

The MCP is node dist/cli.js mcp. It keeps sessions under ~/.sui-agent-pass/sessions/ and uses the deployments bundled with npm. Custom deployments require an explicit deployment path on propose_authorization, or agent-pass mcp --deployment /absolute/path/deployment.json. For development, use --root /absolute/path/development-sessions to keep sessions separate. If a network and custom file are both selected, their networks must match.

An old ~/.sui-agent-pass/deployment.json is no longer loaded automatically. If one remains, list_passes reports a migration message, and proposals without an explicit network or custom deployment stop rather than silently choosing another network. Archive the old file if it is obsolete, or select it explicitly if it is still needed. Existing sessions keep their own deployment; upgrades can refresh addresses only within the same network and original package.

The plugin and Claude Code run as the same OS user: the session key is not hidden from Claude by the operating system, and the on-chain rules are the boundary.

The site

npm run build produces web-dist/, one static site that reads the chain directly and needs no signer or session. #/authorize/<proposal> is the review page setup and the plugin open: the rules come from the URL, the page builds the authorization against the package IDs it was built with, your wallet signs, and the local signer finds the result on chain. Paste a pass id or an owner address, or connect a wallet, and see the pass's rules, the owner's balances and allowances, what the pass holds, and every transaction the agent sent with the chain's verdict and the rule behind each refusal. Owner actions (revoke, reclaim a position or a stake, close the pass) are wallet signatures from the same page. Closing deletes the pass, its policies, its receipt and any remaining allowances in one transaction and hands back anything it still holds; the storage deposits of everything deleted return with that transaction's gas. #/booth is the event view: the latest passes on the package and a live feed of every call into it, refreshing every four seconds.

The pages use the Sui brand fonts, which are licensed and not in git: put the brand kit under .local/brand/ and run npm run brand before building, or the pages fall back to system fonts. The build bundles deployments/<network>.json; ?network=testnet picks one, otherwise the first of mainnet, testnet, devnet, localnet that exists. #/ is the home page with the setup steps, #/guide the longer guide, #/explorer the search and the wallet's own passes. To host it, serve web-dist/ as static files at a fixed origin and set siteUrl in the deployment file. To run it locally against any deployment:

npm run explorer -- --deployment .local/devnet/deployment.json

Basecamp film and slides

Every word of the film (voiceover and on-screen text) and of the two slides lives in presentation/copy.md. Edit it, then run npm run slides (seconds) or npm run demo:film (about six minutes, since the voice paces the recording).

npm run demo:film records the three-minute cut on a fresh localnet and writes scripts/film/out/basecamp-silent.mp4 (picture only, for the presenter's voiceover), basecamp-scratch-vo.mp4 (the same cut read by a scratch voice, for pacing) and basecamp-script.md (the voiceover with a timecode per line). The voice paces the recording, and quiet waits on the agent are cut. On a published network: npm run film:record -- --deployment <deployment.json> --funder <key file>, then npm run film:edit. There the owner signs in the real Slush extension, copied from the local Chrome profile (or SLUSH_EXTENSION) into a throwaway browser profile with a fresh key; the stage shows Slush's own screens as a docked panel, and what the key has left goes back to the funder afterwards. Localnet keeps the page's dev wallet, since Slush has no localnet. node --import tsx scripts/slides/render.ts renders the two concept slides to .local/basecamp/. Both need the brand kit (npm run brand) and Codex on the PATH. Drafts use the free edge-tts voice. npm run film:final (with ELEVENLABS_API_KEY set) reads the lines in the account's ElevenLabs voice (ELEVENLABS_VOICE, default Tech); clips are cached under .local/tts-cache/, so an unchanged line costs no credits on a re-recording.

Changing the voice or the words

The voice paces the recording, so a new voice or a new line means a new recording. To re-record the testnet cut as it was made for Basecamp, with the owner signing in Slush:

  1. Have Codex (codex) on the PATH and Slush installed in Chrome, then npm install, npm run brand and npx playwright install chromium.

  2. Put a funded testnet key (the suiprivkey… string, a few SUI; each run uses about 2) in a file, for example .local/testnet/funder.key. Get testnet SUI at https://faucet.sui.io.

  3. Change the words in presentation/copy.md if you want to. [tone] tags and ... shape the ElevenLabs reading; the free draft voice ignores them.

  4. Record with your own ElevenLabs voice:

    export ELEVENLABS_API_KEY=… ELEVENLABS_VOICE="Your voice name"
    npm run film:record -- --final --deployment deployments/testnet.json --funder .local/testnet/funder.key
    npm run film:edit

    Leave out --final for a free draft first. The cut lands in scripts/film/out/: basecamp-scratch-vo.mp4 is the voiced film and basecamp-silent.mp4 the same picture with no sound, for recording a human voiceover over it with basecamp-script.md as the timecoded script.

Show it to someone

Checks

npm run check
npm test
npm run test:move
npm run build
AGENT_PASS_BROWSER_TEST=1 npm run test:integration
# Optional live model check, using fresh localnet funds and your Claude login:
npm run test:claude

Browser verification uses installed Google Chrome and a wallet-standard test wallet. It runs with a Chinese browser locale to verify the demo still displays English dates and copy. It is not evidence of a live Slush extension signature. Integration tests submit signed invalid transactions and inspect persisted failures; ordinary SDK simulations are not counted as chain refusals. Each test owns and stops its localnet process.

Release checklist

Publishing is a maintainer step, done once per network and once per npm release. None of it runs on a user's machine.

Publish the contracts to a network:

  1. npm run toolchain and npm run build.
  2. npm run deploy -- create --network testnet --directory .local/testnet. Testnet is the default. Mainnet needs a manually funded publisher (no faucet): create --network mainnet prints the address, resume publishes once it holds 2 SUI.
  3. Commit the resulting deployment.json here as deployments/<network>.json.

Publish the npm client:

  1. Confirm npm run check, npm test, npm run test:move, npm run build, and AGENT_PASS_BROWSER_TEST=1 npm run test:integration pass.
  2. npm pack --dry-run to confirm the tarball holds dist/, web-dist/ and deployments/.
  3. Finalize the package name and version, remove "private": true, then npm publish; prepublishOnly rebuilds first.

Scope

Demo only, localnet/testnet/devnet, SUI and a test USDC that the demo faucet mints (not Circle's USDC). Off mainnet DeepBook, Cetus and NAVI are exercised through local stand-ins that keep the mainnet function signatures over constant-product pools and a principal-only lending market. The package also builds against the real protocols (sui move build -e mainnet) and npm run deploy -- create --network mainnet publishes it there with Circle's USDC and the real pools, for compatibility tests; no mainnet publication is claimed yet. The demo packages are made immutable when published; the mainnet package keeps its upgrade cap.

Policies. Each rule set is one on-chain policy object for one coin type, installed by the owner and metered per UTC calendar day. Transfers reach only named recipients. Swaps run only on listed pools, within input caps, above a static price floor and the agent's own min_out; proceeds return to the owner's address. Lending pins the NAVI pool and asset index, caps each action, and refuses a withdraw or borrow that would leave the position below the owner's health-factor floor; the floor sits on the collateral policy too, so a withdraw cannot breach it. Positions belong to the pass's own NAVI account cap, never to the agent. Owners edit policies by removing and reinstalling them, which keeps the meters.

Allowances. sui::allowance draws from address balances only, so setup moves the chosen coins from the owner's coin objects into the owner's own address balance. Anything the owner spends from that balance later simply reduces what the agent can withdraw; a spend above the live balance is refused at signing. A session's allowances, the two asset allowances and the separate SUI gas allowance, share one expiry and are deleted together on revocation. The pass accepts only allowances funded by its owner for its agent, and only it can spend them. A repayment to NAVI is charged to the allowance in full before NAVI runs, so an over-payment returns to the owner but still counts against the allowance; the agent should size repayments from the live debt.

Staking. Real on every network. The policy lists validators (empty means any active one) and caps each stake and the day. The StakedSui the agent opens is held by the pass; the agent may unstake it, which sends principal and rewards to the owner's address, and the owner may reclaim it as an object. The system's own 1 SUI minimum per stake applies.

Objects. The pass holds objects under typed keys: a protocol account under its adapter's key, a stake under its ID, anything else under its own ID. Only the owner deposits or withdraws them. Withdrawing the NAVI account cap moves the position with it, into the owner's wallet, where NAVI's own UI shows it; withdrawing a stake makes it an ordinary StakedSui there. An emptied pass (no policies, no objects) can be destroyed by the owner.

The gas stipend belongs to the session address and is freely spendable. A local service and Claude running under the same OS user are not a private-key isolation boundary: the chain rules survive key theft, while key confidentiality needs a separate identity or container. The private owner/publisher fixture keys never enter the signing service.