Skip to content

Repository files navigation

alphafi-skills

Portable Agent Skills for the AlphaFi protocols on Sui — AlphaLend (lending), AlphaFi vaults and stSUI (liquid staking) — built over the public @alphafi/* JavaScript SDKs. Version 1.0.0 (see CHANGELOG.md).

What this is

Four skills in the Agent Skills format (skills/<name>/SKILL.md + references/ + scripts/), loadable by Claude Code, opencode and Kilo, covering 14 journeys with seventeen .mjs scripts:

Skill Wraps Journeys
alphafi-sui-setup @mysten/sui (shared runtime) environment probe (check-env.mjs), the shared execution runtime and safety layer every other script imports, the portfolio-composition recipe
alphafi-alphalend @alphafi/alphalend-sdk R2 markets, R1 positions, R3 health factor, W1 supply, W2 withdraw, W3 borrow, W4 repay, W5 claim rewards
alphafi-vaults @alphafi/alphafi-sdk R4 vault pools, R1 vault positions, W6 deposit, W7 withdraw (incl. the AlphaVault two-step initiate/claim)
alphafi-stsui @alphafi/stsui-sdk (called direct) R5 stSUI rate/APR/APY/TVL/fees, R1 stSUI balances, W8 stake, W9 instant unstake

Every write script builds an unsigned transaction with the SDK, simulates it over gRPC, runs guardrails and prints a dry-run summary; signing is an explicit opt-in (see Execution modes). Every script prints one JSON envelope with --json and uses a fixed exit-code contract (skills/alphafi-sui-setup/references/output-contract.md).

v1 non-goals are listed at the end (Non-goals): no cross-SDK script, no swaps/looping/zaps, no MCP server, no key management.

Prerequisites

  • Node.js ≥ 22.14 (tested on 24.x) and npm. Nothing under skills/ runs without the root node_modulesnpm install (or npm ci) once in the repository root is mandatory on every install path.
  • Network access, per skill (the same list every skill's compatibility field and skills/alphafi-sui-setup/SKILL.md carry — there is no degraded mode when a host is blocked; reads report status: "unknown" and exit 4, writes fail):
Skill Hosts
alphafi-sui-setup Sui mainnet gRPC fullnode (fullnode.mainnet.sui.io:443)
alphafi-alphalend gRPC fullnode, Sui GraphQL (graphql.mainnet.sui.io), api.alphalend.xyz (reads + Lazer price updates for withdraw/borrow), api.alphafi.xyz, ws.stsui.com (best-effort stSUI staking APR on markets.mjs; unreachable ⇒ stakingApr 0)
alphafi-vaults gRPC fullnode, Sui GraphQL, api.alphalend.xyz, api.alphafi.xyz, hermes.pyth.network (only for Lending/Navi deposits)
alphafi-stsui gRPC fullnode, Sui GraphQL, api.alphafi.xyz (USD TVL only)
  • Mainnet supported, testnet best-effort: SUI_NETWORK=testnet is accepted (with an explicit SUI_RPC_URL) and mapped into the SDKs, but v1 targets mainnet and testnet behaviour is unverified.
  • The RPC endpoint is gRPC-only: public Sui fullnodes no longer answer JSON-RPC, and a JSON-RPC URL in SUI_RPC_URL makes every script exit 3 E_RPC_NOT_GRPC.

Run node skills/alphafi-sui-setup/scripts/check-env.mjs after installing to probe the endpoint and print the host list.

Install

Three recipes. The first works on every harness and is the one to use whenever the scripts must run; the other two are discovery paths.

1. Clone + symlink (primary — Claude Code, opencode, Kilo)

git clone https://github.com/AlphaFiTech/alphafi-skills.git
cd alphafi-skills && npm ci
# in the project that should see the skills:
for s in alphafi-sui-setup alphafi-alphalend alphafi-vaults alphafi-stsui; do
  ln -s "$PWD/skills/$s" "<project>/.claude/skills/$s"
done

.claude/skills/ is read by all three harnesses. Alternates: .opencode/skills/ (opencode), .kilo/skills/ (Kilo), .agents/skills/ (opencode and Kilo), and the global ~/.claude/skills/ for every project. The scripts locate the repository root and its node_modules from their own real path, so a symlinked skill directory works from any working directory. Skills surface as alphafi-<x>.

2. npx skills add AlphaFiTech/alphafi-skills

Discovery-compatible: the four skill directories are found by the Kilo catalogue layout. In the T46 spike (npx skills add <local clone> --agent claude-code -y, skills CLI of 2026-08-30) the CLI copied each skill directory into .claude/skills/<name> (reported (copied)) and recorded it in skills-lock.json. A copied skill directory has no package.json marker above it and no node_modules, so its scripts stop with E_REPO_ROOT (exit 3) — the copied SKILL.md and references/ still work as instructions. To run the scripts, use recipe 1 (a clone with npm ci); should your harness receive symlinks instead, the scripts resolve the clone through them and work once npm ci has run there.

3. Claude Code plugin marketplace

/plugin marketplace add AlphaFiTech/alphafi-skills
/plugin install alphafi-skills@alphafi-skills

Then install the dependencies inside the installed plugin directory — Claude Code may not run npm install for a plugin (older versions leave the cache copy with package.json but no node_modules; 2.1.251 installed them itself), so run it anyway — it is idempotent — and every script refuses to run until the directory has its node_modules:

cd ~/.claude/plugins/cache/alphafi-skills/alphafi-skills/<version>   # the versioned cache dir
npm install

Skills surface as alphafi-skills:alphafi-<x>. Optional Claude Code-only bootstrap: you may instead install the dependencies once into the plugin's persistent data directory (npm install --prefix "${CLAUDE_PLUGIN_DATA}") and symlink ${CLAUDE_PLUGIN_DATA}/node_modules into the cache directory after each plugin update — the scripts only require that <plugin dir>/node_modules/@mysten/sui resolves. Neither the plugin path nor the symlink path writes into the other's files.

Environment variables

All scripts read the same variables (--help on any script prints this table; the full contract is skills/alphafi-sui-setup/references/environment.md).

Variable Semantics
SUI_NETWORK mainnet (default) or testnet. Any other value → exit 2 E_USAGE. testnet maps to "testnet" for AlphalendClient/AlphaFiSDK and setConf("testing") for stsui-sdk; documented as unverified/best-effort (REQ-ASK-050).
SUI_RPC_URL gRPC endpoint. Default when SUI_NETWORK=mainnet: https://fullnode.mainnet.sui.io:443. No default for testnet — absence with SUI_NETWORK=testnet → exit 2 E_USAGE: SUI_RPC_URL is required when SUI_NETWORK=testnet, before any network call. The setup skill and README state that JSON-RPC URLs no longer work on public fullnodes.
SUI_GRAPHQL_URL Optional. Propagated to AlphalendClient(network, graphqlUrl), AlphaFiSDK({graphqlUrl}), stsui setGraphQLUrl() (REQ-ASK-044). Not used by the script client.
ALPHAFI_API_URL Optional. Propagated to AlphaFiSDK({apiBaseUrl}) only — the alphalend GraphQL URL is hard-coded in the SDK (G-A4) and references/sdk-knobs.md says so.
SUI_ADDRESS Sender when --address is absent. In --execute mode the key-derived address wins and any explicit address must equal it (SPEC-ASK-003 §D3).
SUI_PRIVATE_KEY bech32 suiprivkey…; read only inside keys.mjs in --execute mode; never copied into RuntimeEnv (SPEC-ASK-003 §D2).
SUI_RPC_TOKEN Passed through to the SDK constructors as grpcToken (the HEAD-derived SDKs' knob); accepted but inert at the v1 pins, never printed (REQ-ASK-044; SDK-release dependency per SPEC-ASK-007 §D3).

SUI_RPC_URL is a gRPC endpoint and governs the script client only (build, simulate, execute, balances, the endpoint probe); at the pinned SDK versions the SDKs keep their own transports (see Known dependency issues). Sender resolution: --address > SUI_ADDRESS; in --execute mode the key-derived address is used when neither is given. Dry-run and emit-tx never read the key.

Execution modes

Every write script has exactly three mutually exclusive modes; passing two mode flags is a usage error (exit 2) before any network call.

Mode What happens Key needed
--dry-run (default when no mode flag is given) build → simulateTransaction → guardrails → dry-run summary; nothing is signed, written or executed no
--emit-tx dry-run first; then write the unsigned transaction bytes (txBytes and txKindBytes) to --out or ./alphafi-tx-<journey>-<UTC ts>.json for an external signer, with a --gas-margin (default 20 %) budget no (a set key is ignored with W_KEY_IGNORED_IN_EMIT)
--execute dry-run first; then the confirmation gate (--yes or a typed yes on a TTY); then a second simulation, sign in-process with SUI_PRIVATE_KEY and execute yes, Ed25519 only

Recommendation: an autonomous agent acting for a human should use --emit-tx and hand the bytes to the human's wallet or signer; --execute with an in-process key is an opt-in for an operator at their own terminal. Even when a key is present the default is --dry-run. A failed simulation (exit 6) or a guardrail refusal (exit 5) stops every mode before anything is signed, written or executed. The full sequence, the emitted file format and the confirmation gate are in skills/alphafi-sui-setup/references/execution-modes.md. Emitted bytes usually pin one gas coin (gasPaymentPinned: true — observed for every sender that owns Coin<SUI> objects; only address-balance-only senders get an unpinned payment), so any other transaction from the sender invalidates them: sign promptly or re-emit.

Safety

In brief — the normative rules, every guardrail default and the refusal codes live in skills/alphafi-sui-setup/SKILL.md and its references/safety-rules.md:

  • The private key is read from SUI_PRIVATE_KEY only, only in --execute, only after the dry-run passed; no script accepts key material as a flag; every output is redacted; the key's address must equal the address the transaction was built for.
  • Guardrails run in every mode, refuse (never clamp) and report every reason: simulation status, sender outflow bounded by the expected debits plus gas, no debit from another address, AlphaLend projected health factor ≥ --min-hf (default 1.2) on withdraw/borrow, expected-vs-simulated deviation ≤ --max-deviation-bps (10 bps stake/unstake, 100 bps vault deposit/withdraw), gas budget ≤ --max-gas (default 0.1 SUI).
  • An agent must never, on its own initiative, add --yes, move a key into arguments/files/transcripts, raise a limit flag to force a pass, or chain a dry-run into --execute without the human confirming the exact action.
  • Proceeds of withdraw/borrow/claim/unstake land in the address balance (0x2::coin::send_funds), not as a new Coin object — check the total balance via gRPC getBalance.

Support matrix

Filled by the release-evidence procedure (docs/evidence/2026-08-30-portability.md, Claude Code CLI 2.1.251); rows not exercised locally stay documented, not verified.

Harness / path Status Notes
Claude Code — symlinked .claude/skills verified primary recipe; symlinks followed, the four skills list as alphafi-<x>
Claude Code — plugin marketplace verified versioned cache dir …/alphafi-skills/<version>/, skills list as alphafi-skills:alphafi-<x>; 2.1.251 installed node_modules itself — run npm install there anyway (idempotent; older versions do not)
opencode — .claude/skills symlink verified (opencode 1.18.25) also .opencode/skills/ (both verified: opencode debug skill lists the four alphafi-* skills from either directory), .agents/skills/
Kilo — .claude/skills symlink documented-not-verified also .kilo/skills/, .agents/skills/; npx skills add copies; CLI not installed on the evidence machine
Mysten-partner deploy agent documented-not-verified unknown harness; the primary recipe and host list are the stated default

Known dependency issues

v1 pins the published @alphafi/alphalend-sdk 4.1.0, @alphafi/alphafi-sdk 2.2.0, @alphafi/stsui-sdk 2.0.3 and @mysten/sui 2.27.1 (exact). Until the HEAD-derived SDK releases land (tracked in docs/sdk-gaps.md, G-A7 / G-V11):

  1. No grpcUrl / grpcToken knobs in the pinned alphalend and vaults SDKs — SUI_RPC_URL governs only the script client; the SDKs read through their own default transports (SUI_GRAPHQL_URL is the one override that reaches all three). Functional; may be flagged by supply-chain scanners. See skills/alphafi-sui-setup/references/sdk-knobs.md.
  2. Nested @alphafi/alphalend-sdk@3.1.1 inside the pinned @alphafi/alphafi-sdk 2.2.0, which pulls two @mysten/sui@1.45.2 copies and the deprecated @mysten/sui.js into the tree. Functional; may be flagged by supply-chain scanners.
  3. npm ls reports an invalid peer (the nested tree's @mysten/sui peer range). Functional; may be flagged by supply-chain scanners.

Re-pinning to the fixed releases is a version bump with a CHANGELOG.md entry (the procedure is in the setup skill's sdk-knobs.md).

Troubleshooting

Start with node skills/alphafi-sui-setup/scripts/check-env.mjs (add --json). Entries are keyed by the exact error codes the scripts emit; the quoted text is the runtime message template.

  • E_DEPS_MISSING (exit 3) — the root node_modules is missing (fresh clone, copied skill directory, or a plugin install without the npm install step). Message: E_DEPS_MISSING: dependencies not installed; run "npm install" (or "npm ci") in <root> — run exactly that in the named directory.
  • E_REPO_ROOT (exit 3) — the script is not inside a clone or the installed plugin directory (typically a copied skill directory, recipe 2): E_REPO_ROOT: could not find the alphafi-skills repository root above <start>; run the scripts from a clone or the installed plugin directory.
  • E_RPC_NOT_GRPC (exit 3) — SUI_RPC_URL points at a JSON-RPC or plain HTTP endpoint. Message: E_RPC_NOT_GRPC: <url> answered as JSON-RPC or HTTP; SUI_RPC_URL must be a gRPC endpoint (public fullnode JSON-RPC is deprecated) — <detail> — set SUI_RPC_URL to a gRPC endpoint (default https://fullnode.mainnet.sui.io:443).
  • E_RPC_UNREACHABLE (exit 3) — DNS, connection or timeout failure on SUI_RPC_URL. Messages: E_RPC_UNREACHABLE: <url> could not be reached (<message>) or E_RPC_UNREACHABLE: <url> probe failed (<message>) — check the URL, your network and any proxy.
  • E_UPSTREAM (exit 4) — an AlphaFi API, Sui GraphQL, Lazer or Hermes host gave no usable answer (blocked host, outage, or an SDK returning undefined/"0"). Messages: E_UPSTREAM: <host> gave no usable answer for <name> or E_UPSTREAM: unexpected failure — <cause> — the message names the dependency and carries the cause; retry later and never treat the affected value as zero. The blocked-host list is in Prerequisites.
  • E_USAGE: SUI_RPC_URL is required when SUI_NETWORK=testnet (exit 2) — testnet has no default endpoint.
  • E_CONFIRM_REQUIRED (exit 7) — --execute without a TTY and without --yes; the human runs the printed --execute --yes command themselves.
  • E_GUARD_<NAME> (exit 5) / E_SIM_FAILED (exit 6) — the action is not safe as specified; read the summary, do not raise limits to pass.

Non-goals

v1 deliberately does not include:

  • a cross-SDK "portfolio" script (compose the three --json reads per the setup skill's recipe instead);
  • swaps, zaps, looping / leveraged strategies, LP-collateral journeys;
  • an MCP server or any harness-specific runtime — the skills are files;
  • key management: no keystore, no wallet integration, no key generation; --execute is an opt-in with a key the operator already holds;
  • fixing the SDK gaps recorded in docs/sdk-gaps.md — they are handed to the SDK workstream, and this repository only works around them;
  • testnet verification (best-effort only) and any degraded mode when an AlphaFi host is unreachable.

Development and CI

  • npm test — the offline unit suite (node:test, SDK and client stubbed; no network); npm run test:coverage adds the coverage summary and writes coverage/lcov.info; npm run lint — ESLint, Prettier and tsc --noEmit over the JSDoc-typed .mjs files.
  • Repo checks (also run by CI): npm run validate:skills, check:frontmatter, check:skill-size, check:sdk-map, validate:plugin (the claude CLI when on PATH, else an offline JSON-schema check — the log says which), check:test-names (every SPEC-ASK-007 matrix row and REQ id has a named test; with --lcov coverage/lcov.info every lib/ module is in the coverage report) and check:versions (the lockstep; on a pull request that touches skills/ all five version fields must change together with a new CHANGELOG.md entry).
  • CI (.github/workflows/ci.yml, every push and pull request, GitHub-hosted Ubuntu, Node 22): install, lint, unit (behind an HTTP-proxy sinkhole so the offline suite cannot reach the network), skills, plugin, versions and secrets (gitleaks over the whole history with .gitleaks.toml, the same rules as the pre-commit hook). CI holds no secrets, never signs and never executes a transaction.
  • npm run test:integration — on demand, from a networked machine, with no key in the environment (the suite aborts if one is set): read-only calls and simulateTransaction dry-runs against mainnet public endpoints for the fixed public address in test/integration/config.json and a funded public sender selected at run time; about 1–2 minutes; a script over 60 s warns and over 120 s fails; set INTEGRATION_LOG=<file> to save the run as JSON. If your environment routes egress through a proxy, set NODE_USE_ENV_PROXY=1 so Node's fetch honours https_proxy; if egress is denied altogether, dispatch the integration workflow instead (gh workflow run integration.yml) and read the run log — it is the same suite on a GitHub-hosted runner. Runs are recorded under docs/evidence/.
  • docs/evidence/scripts/ — the read-only probe scripts behind the recorded evidence (hf-compare.mjs for the health-factor cross-check, gas-probe.mjs for the gasData.payment test); they need no key and are run from the repository root (node docs/evidence/scripts/<name>.mjs …).

License

MIT — see LICENSE.

About

AlphaFi DeFi skills: AlphaLend, vaults, stSUI

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages