Claude Skill

solana-dev

Unified skill hub for Solana development. Routes to external submodule skills (solana-foundation, sendai, solana-game, trailofbits, cloudflare, qedgen, colosseum, solana-new, ghostsecurity, defending-code) and local skills. Progressive disclosure — read only what you need.

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download solanabr-solana-ai-kit-.claude_skills-102887b.zip · 56 KB
Part of solanabr/solana-ai-kit — 2 skills

Install

skills CLI npx skills add https://github.com/solanabr/solana-ai-kit/tree/main/.claude/skills
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install solanabr-solana-ai-kit@llmmart
Git git clone https://github.com/solanabr/solana-ai-kit.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole solanabr/solana-ai-kit collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Solana skill hub

Find the task, read the linked file, and follow further links only as needed. Paths are relative to this file.

Every install carries the core packs, solana-dev and safe-solana-builder. The other ext/ packs are extensions: the kit pins them, and a project installs one when a task needs it. A row that links into an extension gives its install command; run it when the linked folder is missing (/update keeps what you install). The Extensions table at the end lists each one with when to use it.

When sources overlap: the program-code house rules in the project instruction file (CLAUDE.md, or AGENTS.md in --agents installs) win; a protocol's official skill wins for its own SDK (Jupiter, Metaplex, Helius, MagicBlock, Alchemy); ext/solana-dev wins for general Solana work; sendai and community skills fill gaps only.

Programs

Task Read
Any program, client or test work (entry point) solana-dev SKILL.md
Anchor programs/anchor.md; upgrading to 1.x: migrating-v0.32-to-v1.md
Pinocchio, CU optimization programs/pinocchio.md
Account and PDA design programs/design-patterns.md
Tests: LiteSVM, Mollusk, Surfpool testing.md, surfpool/overview.md
Error codes, failing transactions common-errors.md
Toolchain version pairing compatibility-matrix.md
Security review security.md, safe-solana-builder (security-first scaffolding, Anchor/native/Pinocchio)
Financial math, Quasar zero-copy RUST.md, ANCHOR.md, QUASAR.md from quicknode-anchor; reference files only, skip that repo's SKILL.md workflow layer (install: bash .claude/bin/skills.sh add quicknode-anchor)
Formal verification (Lean 4) qedgen from QEDGen; needs the qedgen CLI and MISTRAL_API_KEY (install: bash .claude/bin/skills.sh add qedgen)
Port from Solidity/EVM eth-to-sol from eth-to-sol: type-mapping, pattern-mapping, stdlib-mapping, mental-model, translation/, security/, optimization/; concept map: solana-vs-evm.md (install: bash .claude/bin/skills.sh add eth-to-sol solana-new)

Anchor 1.x defaults this kit uses (not all spelled out upstream): SPL transfers through token_interface::transfer_checked, account space T::DISCRIMINATOR.len() + T::INIT_SPACE, Rust LiteSVM tests under programs/<name>/tests/ (anchor test runs Surfpool).

Clients and frontend

Task Read
Wallet connection, React hooks, @solana/kit UI frontend.md
Transactions, Kit and web3.js boundary kit-web3-interop.md
web3.js to Kit migration solana-kit-migration/, solana-kit/ (install: bash .claude/bin/skills.sh add sendai)
Clients generated from an IDL (Codama, Shank) idl-codegen.md
Payments, Solana Pay, Kora payments.md
Official doc links resources.md
Vercel, Next.js, AI SDK, v0 ext/vercel/skills/ from Vercel (install: bash .claude/bin/skills.sh add vercel)
UI design direction; Playwright tests of a local dApp Anthropic's frontend-design/SKILL.md and webapp-testing/SKILL.md (install: bash .claude/bin/skills.sh add anthropic-skills; later sessions load them by description)

Tokens and NFTs

Task Read
Token-2022 extensions: pick, combine and create them (CLI, Kit, Anchor); fees, hooks, metadata, pausable, soulbound token-extensions
Confidential transfers confidential-transfers.md
NFTs: Core, Token Metadata, Bubblegum, Candy Machine, Umi metaplex (official; install: bash .claude/bin/skills.sh add metaplex)

DeFi, RPC and data

Task Read
Jupiter swap, lend, perps, trigger, recurring integrating-jupiter (official); also jupiter-lend, jupiter-swap-migration, jupiter-vrfd (install: bash .claude/bin/skills.sh add jupiter)
Helius RPC, DAS, webhooks, Sender, priority fees helius (official; install: bash .claude/bin/skills.sh add helius)
SVM internals, consensus, validators, SIMDs svm (install: bash .claude/bin/skills.sh add helius)
Alchemy RPC, DAS, Yellowstone gRPC; keyless x402 access alchemy-api (official), agentic-gateway (install: bash .claude/bin/skills.sh add alchemy)
MagicBlock Ephemeral Rollups: delegated state, real-time apps and games, private payments, VRF, cranks magicblock (official; install: bash .claude/bin/skills.sh add magicblock)

Other protocols from SendAI (install: bash .claude/bin/skills.sh add sendai): perps phoenix and leverage lavarage; AMMs raydium, meteora, orca; lending kamino, marginfi; LSTs sanctum; launches pumpfun; oracles pyth, switchboard; multisig squads; bridging debridge, lifi; encrypted compute arcium; ZK compression light-protocol; data birdeye, wallet-analysis; RPC carbium, quicknode; order book manifest; order flow dflow; account cleanup sol-incinerator; agents solana-agent-kit; wallets phantom-connect; scanning vulnhunter. SendAI's own jupiter, metaplex, helius and magicblock folders are older copies; the official skills above supersede them.

Security tooling

Deploy, infra, backend

Games and mobile

Ideas, pitch, go-to-market

Extensions

Pinned by the kit, installed on demand. bash .claude/bin/skills.sh list shows what this project has.

Extension Install when the task involves Install
trailofbits Security audits: vulnerability scans, audit prep, code maturity, token integration review bash .claude/bin/skills.sh add trailofbits
ghostsecurity AppSec scans of app and infra code: SAST, dependencies, secrets bash .claude/bin/skills.sh add ghostsecurity
defending-code Threat models, vulnerability triage, security patches bash .claude/bin/skills.sh add defending-code
qedgen Formal verification with Lean 4 (needs the qedgen CLI and MISTRAL_API_KEY) bash .claude/bin/skills.sh add qedgen
sendai DeFi and other protocols (Raydium, Orca, Meteora, Kamino, marginfi, Sanctum, Pyth, Switchboard, Squads, pump.fun, bridges), web3.js to Kit migration bash .claude/bin/skills.sh add sendai
jupiter Jupiter swap, lend, perps, trigger and recurring orders bash .claude/bin/skills.sh add jupiter
metaplex NFTs: Core, Token Metadata, Bubblegum, Candy Machine, Umi bash .claude/bin/skills.sh add metaplex
magicblock MagicBlock Ephemeral Rollups, real-time apps and games, private payments bash .claude/bin/skills.sh add magicblock
helius Helius RPC, DAS, webhooks, Laserstream, Sender, priority fees, SVM internals bash .claude/bin/skills.sh add helius
alchemy Alchemy RPC, DAS, Yellowstone gRPC, x402 gateway (ALCHEMY_API_KEY for the API skill) bash .claude/bin/skills.sh add alchemy
quicknode-anchor Financial math, fixed-point arithmetic, Quasar zero-copy bash .claude/bin/skills.sh add quicknode-anchor
eth-to-sol Porting Solidity or other EVM contracts bash .claude/bin/skills.sh add eth-to-sol
solana-game Unity, C#, games, PlaySolana, PSG1 bash .claude/bin/skills.sh add solana-game
solana-mobile React Native, Expo, Mobile Wallet Adapter, Seeker, dApp Store bash .claude/bin/skills.sh add solana-mobile
cloudflare Cloudflare Workers, wrangler, Durable Objects, Agents SDK bash .claude/bin/skills.sh add cloudflare
vercel Vercel deploys, Next.js and React performance, web design review bash .claude/bin/skills.sh add vercel
solana-new Go-to-market references: marketing video, brand design, tokenomics, DefiLlama research, ecosystem catalogs; idea-sprint, pitch-deck and hackathon link it bash .claude/bin/skills.sh add solana-new
colosseum Colosseum hackathon archives, idea validation, competitive research (needs COLOSSEUM_COPILOT_PAT) bash .claude/bin/skills.sh add colosseum
anthropic-skills UI design direction, Playwright tests of a local web app, building an MCP server (Anthropic's Apache-2.0 frontend-design, webapp-testing and mcp-builder, installed as top-level skills in skills/<name>/) bash .claude/bin/skills.sh add anthropic-skills

Add-ons

skill-registry.json records each pack's tier, triggers, license and source. Its entries without a tier are opt-in tools the kit doesn't pin; install one only when the user asks and safe-ai-skill add skill|mcp <source> returns proceed: true. Wider ecosystem catalogs: ext/solana-new/cli/data/ (install: bash .claude/bin/skills.sh add solana-new).

Files (solana-ai-kit)
  • hackathon
    • SKILL.md 4 KB
      ---
      name: hackathon
      description: Prepare a winning hackathon submission. Use when the user says "hackathon submission", "submit to hackathon", "demo script", "demo video", "which track should I enter", "Colosseum", "help me win the hackathon", or asks about hackathon grants and Superteam Earn.
      user-invocable: true
      ---
      
      <!-- Adapted from sendaifun/solana-new (submit-to-hackathon, apply-grant), MIT © 2026 SendAI and Superteam. Telemetry removed. -->
      
      # Hackathon Submission
      
      Track choice → scannable description → <3-min demo script → checklist. Optimize for a judge who has 90 seconds, not a reader who has 10 minutes.
      
      ## Context handoff
      
      At start, read `.claude/context/idea.md` and `.claude/context/build.md` if present — pull the pitch, wedge, and what actually works from them instead of asking again.
      
      ## Workflow
      
      ### 1. Pick the least-crowded track
      
      Winning a thin track beats placing in a fat one. Per candidate track: estimate entry volume, fit with what's actually built, and judge appetite (sponsor tracks often have the fewest serious entries).
      
      - Winner patterns + track history: [hackathon-winners.md](../ext/solana-new/skills/data/colosseum/hackathon-winners.md) — every Colosseum grand champion and track winner, with what they built (install first: `bash .claude/bin/skills.sh add solana-new`)
      - Live crowdedness check: [ext/colosseum](../ext/colosseum/skills/colosseum-copilot/SKILL.md) — query 5,400+ past submissions for cluster density and gaps (requires `COLOSSEUM_COPILOT_PAT`; install first: `bash .claude/bin/skills.sh add colosseum`)
      
      ### 2. Write a scannable description
      
      **Judges read 100+ submissions.** Yours gets one skim deciding whether it gets a real read:
      
      - Tagline: what it does, one sentence, no jargon
      - First paragraph: problem + who has it
      - Bold the one thing that's novel
      - "What works today" list — demo-able claims only, never roadmap dressed as product
      - Why Solana (one concrete reason: speed, fees, composability with X)
      
      Full structure (200–500 words, paragraph-by-paragraph): [hackathon-submission-guide.md](../ext/solana-new/skills/launch/submit-to-hackathon/references/hackathon-submission-guide.md). Score the draft against [judging-criteria.md](../ext/solana-new/skills/launch/submit-to-hackathon/references/judging-criteria.md) before submitting (install first: `bash .claude/bin/skills.sh add solana-new`).
      
      ### 3. Demo script (<3 minutes)
      
      | Time | Beat |
      |------|------|
      | 0:00–0:20 | Problem — one user, one pain, no market-size slides |
      | 0:20–0:40 | What you built, one sentence + UI first appears |
      | 0:40–2:10 | The demo — one happy path, real data, on-chain proof (explorer tx) |
      | 2:10–2:40 | The novel part — the thing competitors don't have |
      | 2:40–3:00 | Traction/team one-liner + the ask |
      
      Shot-by-shot template and recording tips: [demo-video-script.md](../ext/solana-new/skills/launch/submit-to-hackathon/references/demo-video-script.md) (install first: `bash .claude/bin/skills.sh add solana-new`). Rule: if the demo can fail live, record it.
      
      ### 4. Submission checklist
      
      - [ ] Track chosen by crowdedness, not vanity
      - [ ] Tagline passes the "non-crypto friend" test
      - [ ] Description scannable in 90 seconds (bold claims, short paragraphs)
      - [ ] Demo video <3 min, real transaction shown
      - [ ] Repo public, README quickstart actually works from clone
      - [ ] Deployed link (devnet OK) + program ID listed
      - [ ] Team and contact info complete
      - [ ] Pitch deck attached if track requires one — use [pitch-deck](../pitch-deck/SKILL.md)
      
      ## After the hackathon: grants
      
      Losing the track doesn't mean losing the funding. Same artifacts (description, demo, deck) feed grant applications:
      
      - **Superteam Earn** (earn.superteam.fun) — bounties + grants up to ~$10k USDC equivalent, fast cycles, regional Superteams
      - **Solana Foundation grants** — milestone-based, public-good angle; reuse the scannable description with an ecosystem-benefit paragraph
      - Grant-shaped ideas dataset: [superteam-ideas.json](../ext/solana-new/skills/data/ideas/superteam-ideas.json) (install first: `bash .claude/bin/skills.sh add solana-new`)
      
  • idea-sprint
    • SKILL.md 5.9 KB
      ---
      name: idea-sprint
      description: Find and validate what to build in crypto. Use when the user asks "what should I build", "validate this idea", "is this worth building", "find me a startup idea", "crypto idea", or wants blunt feedback on a project concept before writing code.
      user-invocable: true
      ---
      
      <!-- Adapted from sendaifun/solana-new (find-next-crypto-idea, validate-idea), MIT © 2026 SendAI and Superteam. Telemetry removed. -->
      
      # Idea Sprint
      
      Interview → necessity gate → 3 candidates → score → go/no-go. Output is a decision, not a brainstorm.
      
      ## Context handoff
      
      - At start: read `.claude/context/idea.md` and `.claude/context/build.md` if present — resume from prior state instead of re-interviewing.
      - On completion: write/update `.claude/context/idea.md` with the chosen idea, scores, validation evidence, and open risks. Downstream skills (pitch-deck, hackathon) read it.
      
      ## Workflow
      
      ### 1. Blunt interview
      
      No flattery. Short, pointed questions, one at a time, until three things are explicit:
      
      - **Edge** — what the founder knows/can do that most can't (domain, distribution, tech)
      - **Constraint** — time, money, team, chain commitments
      - **Wedge** — the niche entry point, not the end-state vision
      
      Push back on vague answers. "DeFi for everyone" is not a wedge. Full question bank: [interview-framework.md](../ext/solana-new/skills/idea/find-next-crypto-idea/references/interview-framework.md) (install first: `bash .claude/bin/skills.sh add solana-new`).
      
      ### 2. Crypto-necessity gate
      
      Kill question: **"What gets worse if I remove the blockchain?"** If the answer is vague, aesthetic, or marketing-driven — redirect the idea before scoring it. Pass criteria and redirect patterns: [crypto-necessity-test.md](../ext/solana-new/skills/idea/find-next-crypto-idea/references/crypto-necessity-test.md) (install first: `bash .claude/bin/skills.sh add solana-new`).
      
      ### 3. Exactly 3 candidates
      
      Generate three **diverse** candidates (different mechanisms/markets, not three flavors of one idea). For each:
      
      - One-line pitch + target user
      - **Winner case** — what's true in 18 months if it works
      - **Bear case** — the most likely way it dies
      
      Seed from datasets + live landscape (below), then combine with fresh research. Datasets are inspiration, not constraints.
      
      ### 4. Score /15
      
      Each candidate, 0–3 per dimension (full anchors: [scoring-rubric.md](../ext/solana-new/skills/idea/find-next-crypto-idea/references/scoring-rubric.md); install first: `bash .claude/bin/skills.sh add solana-new`):
      
      | Dimension | 3 means |
      |-----------|---------|
      | Founder fit | unfair advantage |
      | MVP speed | shippable in under a week |
      | Distribution | first ten users are obvious |
      | Market pull | people already paying for bad alternatives |
      | Revenue path | clear monetization story |
      
      ### 5. Validate + go/no-go
      
      Check demand signals against [customer-signal-rubric.md](../ext/solana-new/skills/idea/validate-idea/references/customer-signal-rubric.md) — manual workarounds, active forks, bounties, on-chain activity = real; likes and "cool idea" replies = noise. Sprint structure: [validation-framework.md](../ext/solana-new/skills/idea/validate-idea/references/validation-framework.md) (install first: `bash .claude/bin/skills.sh add solana-new`).
      
      - **≥ 8/15** → go. Write `idea.md`, suggest `/scaffold` next.
      - **6–7** → conditional: name the one dimension to de-risk first.
      - **< 6** → strong no-go. **Every no-go gets a pivot suggestion** — use [pivot-or-persist.md](../ext/solana-new/skills/idea/validate-idea/references/pivot-or-persist.md) (install first: `bash .claude/bin/skills.sh add solana-new`).
      
      ### 6. Write `.claude/context/idea.md`
      
      Chosen idea, wedge, scores table, demand evidence, bear case, next step.
      
      ## Idea datasets (inert JSON, ~515 entries)
      
      In [../ext/solana-new/skills/data/ideas/](../ext/solana-new/skills/data/ideas/) (install first: `bash .claude/bin/skills.sh add solana-new`):
      
      - [web3-ideas-combined.json](../ext/solana-new/skills/data/ideas/web3-ideas-combined.json) — master list ([summary](../ext/solana-new/skills/data/ideas/web3-ideas-summary.json)) (`bash .claude/bin/skills.sh add solana-new`)
      - [a16z-big-ideas-2025.json](../ext/solana-new/skills/data/ideas/a16z-big-ideas-2025.json), [a16z-state-of-crypto-2025.json](../ext/solana-new/skills/data/ideas/a16z-state-of-crypto-2025.json) (`bash .claude/bin/skills.sh add solana-new`)
      - [yc-requests-for-startups.json](../ext/solana-new/skills/data/ideas/yc-requests-for-startups.json), [yc-crypto-companies.json](../ext/solana-new/skills/data/ideas/yc-crypto-companies.json) (`bash .claude/bin/skills.sh add solana-new`)
      - [alliance-ideas.json](../ext/solana-new/skills/data/ideas/alliance-ideas.json), [superteam-ideas.json](../ext/solana-new/skills/data/ideas/superteam-ideas.json) (`bash .claude/bin/skills.sh add solana-new`)
      - [rwa-defi-2026-ideas.json](../ext/solana-new/skills/data/ideas/rwa-defi-2026-ideas.json), [yash-defi-2024-ideas.json](../ext/solana-new/skills/data/ideas/yash-defi-2024-ideas.json) (`bash .claude/bin/skills.sh add solana-new`)
      
      Idea-source guides (markdown commentary on the same sources): [../ext/solana-new/skills/data/guides/](../ext/solana-new/skills/data/guides/) — plus [source-map.md](../ext/solana-new/skills/idea/find-next-crypto-idea/references/source-map.md) and [research-playbook.md](../ext/solana-new/skills/idea/find-next-crypto-idea/references/research-playbook.md) for where/how to research live (install first: `bash .claude/bin/skills.sh add solana-new`).
      
      ## Live hackathon landscape
      
      [ext/colosseum](../ext/colosseum/skills/colosseum-copilot/SKILL.md) — 5,400+ Colosseum submissions for crowdedness checks, winner patterns, and gap analysis (requires `COLOSSEUM_COPILOT_PAT`; install first: `bash .claude/bin/skills.sh add colosseum`).
      
      ## Output format
      
      Report spec (3 ranked candidates, scores, decision): [output-spec.md](../ext/solana-new/skills/idea/find-next-crypto-idea/references/output-spec.md) (install first: `bash .claude/bin/skills.sh add solana-new`).
      
  • pitch-deck
    • SKILL.md 4.5 KB
      ---
      name: pitch-deck
      description: Build a pitch deck for a crypto project. Use when the user says "pitch deck", "demo day", "investor presentation", "grant application slides", "accelerator application", "help me pitch", or needs slides for a hackathon final.
      user-invocable: true
      ---
      
      <!-- Adapted from sendaifun/solana-new (create-pitch-deck), MIT © 2026 SendAI and Superteam. Telemetry removed. -->
      
      # Pitch Deck
      
      Interview → detect audience → pick narrative → build slides with speaking notes → self-score → objection prep.
      
      ## Context handoff
      
      At start, read `.claude/context/idea.md` and `.claude/context/build.md` if present — pre-fill problem, wedge, traction, and stack from them; only ask what's missing.
      
      ## Workflow
      
      ### 1. 12-question interview
      
      Blunt, one at a time, skipping anything already answered by context files:
      
      1. What does it do, in one sentence a non-crypto person understands?
      2. Who exactly has the problem, and how painful is it (evidence)?
      3. Why does this need a blockchain?
      4. Why Solana specifically?
      5. What works *today* (demo-able) vs. roadmap?
      6. Traction numbers — users, volume, TVL, signups, waitlist?
      7. Who is the team and what's the unfair edge?
      8. Competitors and your moat?
      9. Business model — who pays, when?
      10. Who is the audience for this deck (judges, VCs, grant committee, accelerator)?
      11. The ask — prize, check size, grant amount, admission?
      12. Biggest weakness you're afraid they'll ask about?
      
      ### 2. Audience detection → slide set
      
      Q10 decides the slide set — full breakdown in [investor-audience-guide.md](../ext/solana-new/skills/launch/create-pitch-deck/references/investor-audience-guide.md) (install first: `bash .claude/bin/skills.sh add solana-new`):
      
      | Audience | Emphasis | Length |
      |----------|----------|--------|
      | Hackathon judges | working demo, technical novelty, why-Solana | 5–7 slides |
      | VC | market size, traction slope, team, moat, ask | 10–12 |
      | Grant committee | ecosystem benefit, public-good angle, milestones, budget | 8–10 |
      | Accelerator | team velocity, learning rate, wedge → expansion path | 8–10 |
      
      Slide-by-slide order per audience: [pitch-structure.md](../ext/solana-new/skills/launch/create-pitch-deck/references/pitch-structure.md) (install first: `bash .claude/bin/skills.sh add solana-new`).
      
      ### 3. Narrative framework
      
      Pick one backbone and state why — PAS (obvious pain, hackathons), 6-Part Investor Arc (VC), BAB (before/after/bridge), Hero's Journey (founder-story-driven), Pixar (narrative momentum). Definitions, slide mappings, and crypto examples: [storytelling-frameworks.md](../ext/solana-new/skills/launch/create-pitch-deck/references/storytelling-frameworks.md) (install first: `bash .claude/bin/skills.sh add solana-new`).
      
      ### 4. Build slides + speaking notes
      
      For each slide: headline (a claim, not a label), 3–5 supporting points, visual suggestion, and 30–60s speaking notes. Use:
      
      - [slide-templates.md](../ext/solana-new/skills/launch/create-pitch-deck/references/slide-templates.md) — per-slide-type templates (install first: `bash .claude/bin/skills.sh add solana-new`)
      - [deck-design-system.md](../ext/solana-new/skills/launch/create-pitch-deck/references/deck-design-system.md) — typography, layout, color rules (`bash .claude/bin/skills.sh add solana-new`)
      - [crypto-pitch-examples.md](../ext/solana-new/skills/launch/create-pitch-deck/references/crypto-pitch-examples.md) — real decks that worked (`bash .claude/bin/skills.sh add solana-new`)
      - [pitch-reference-sources.md](../ext/solana-new/skills/launch/create-pitch-deck/references/pitch-reference-sources.md) — primary sources (`bash .claude/bin/skills.sh add solana-new`)
      
      ### 5. Self-score vs audience rubric
      
      Score the draft against the audience's actual criteria (clarity, credibility, demo strength, ask specificity) and against [crypto-pitch-mistakes.md](../ext/solana-new/skills/launch/create-pitch-deck/references/crypto-pitch-mistakes.md) (install first: `bash .claude/bin/skills.sh add solana-new`) — flag every mistake the deck still commits, fix, re-score. Don't present a deck you'd score below 8/10.
      
      ### 6. Objection-prep Q&A
      
      From Q12 + the weakest scored dimension, draft the 8–10 hardest questions this audience will ask, each with a tight 30-second answer. Hostile-question drilling beats slide polish.
      
      ## Output
      
      - Deck outline (markdown, one section per slide: headline / points / visual / speaking notes)
      - Framework choice + one-line rationale
      - Self-score with the fixes applied
      - Objection Q&A sheet
      
      Need an actual rendered deck file (.pptx)? Hand the outline to the pptx skill if available.
      
  • token-extensions
    • references
      • account-extensions.md 5.7 KB
        # Token-account extensions and sizing
        
        ImmutableOwner, MemoTransfer and CpiGuard live on token accounts and protect the holder. The other account extensions (TransferFeeAmount, TransferHookAccount, NonTransferableAccount, PausableAccount) come from the mint, and the program initializes them itself when the account is created, provided the account has room.
        
        ## Sizing a token account
        
        - Required account extensions per mint extension: TransferFeeConfig → TransferFeeAmount; TransferHook → TransferHookAccount; NonTransferable → NonTransferableAccount and ImmutableOwner; Pausable → PausableAccount. Confidential accounts opt in later.
        - `InitializeAccount` fails with `InvalidAccountData` if the account is too small for those.
        - Associated token accounts: the associated token account program sizes them and adds ImmutableOwner, so Token-2022 associated token accounts always have it. Kit `getCreateAssociatedTokenIdempotentInstructionAsync({ payer, owner, mint, tokenProgram })`; `tokenProgram` defaults to Token-2022 there, while web3.js 1.x helpers default to the classic Token program.
        - Anchor 1.2.0: `init` with `associated_token::` constraints goes through that program. `init` with `token::` constraints allocates exactly the mint's required extensions, which leaves no room for MemoTransfer or CpiGuard and no ImmutableOwner unless the mint is NonTransferable.
        - Manual accounts: Rust `ExtensionType::try_calculate_account_len::<Account>(&types)`, or `extension::account_len::try_calculate_account_len_from_mint_data(&mint_data, &extra_types)`, which exists only in interface 3.x and takes 3.x `ExtensionType`s (next to anchor-spl, add 3.x as in [programs](programs.md)). Kit `getTokenSize(extensions)` counts only the extensions you pass, so include the mint's required ones (for example `extension('TransferFeeAmount', { withheldAmount: 0n })`). Kit's `getCreateTokenInstructionPlan` never sends `InitializeImmutableOwner`, even when you list it. web3.js 1.x `getAccountLenForMint` misses ImmutableOwner for NonTransferable mints.
        - The on-chain `GetAccountDataSize` instruction returns the size for the mint's required extensions plus the ones you list (Rust builder `get_account_data_size(program, mint, &types)`, Anchor `anchor_spl::token_2022::get_account_data_size`); Kit's builder takes no extension list.
        
        ## ImmutableOwner
        
        - The account's owner can never change: SetAuthority `AccountOwner` fails with `ImmutableOwner`.
        - On a manual account, `InitializeImmutableOwner` has to run before `InitializeAccount`; afterwards it fails with `AlreadyInUse`, so it can't be added later.
        - CLI: `spl-token create-account <MINT> <ACCOUNT_KEYPAIR> --immutable` (without a keypair it creates the associated token account, which already has it). Kit: `getInitializeImmutableOwnerInstruction({ account })`. Anchor: `immutable_owner_initialize(ctx)`.
        
        ## MemoTransfer (required memos)
        
        - When enabled, every incoming transfer to the account (including confidential transfers, and self-transfers from it) needs a memo instruction immediately before the transfer, from the SPL Memo program (v1 or v3), or it fails with `NoMemo`. Only the program id is checked, not the memo text. Outgoing transfers need no memo.
        - For a transfer made by CPI, the calling program must invoke the memo program right before its transfer CPI, at the same level; a memo at the top of the transaction doesn't count.
        - The owner enables and disables it. On an account created without room, `Reallocate` first.
        - CLI: `spl-token enable-required-transfer-memos <ACCOUNT>` / `disable-required-transfer-memos` (they reallocate if needed); send with `spl-token transfer ... --with-memo <TEXT>`. Kit: `getEnableMemoTransfersInstruction({ token, owner })` / `getDisableMemoTransfersInstruction(...)`. Anchor: `memo_transfer_initialize(ctx)` enables it, despite the name; `memo_transfer_disable(ctx)`.
        
        ## CpiGuard
        
        - The owner turns it on and off only at the top level of a transaction; inside a CPI both fail with `CpiGuardSettingsLocked`.
        - While on, inside a CPI:
          - transfers and burns signed by the owner fail (`CpiGuardTransferBlocked`, `CpiGuardBurnBlocked`); a delegate, including the permanent delegate, still can;
          - approve fails (`CpiGuardApproveBlocked`);
          - closing the account to anyone but the owner fails (`CpiGuardCloseAccountBlocked`);
          - setting a close authority fails (`CpiGuardSetAuthorityBlocked`);
          - unwrapping lamports fails for any signer.
        - Changing the account owner fails outside a CPI too (`CpiGuardOwnerChangeBlocked`; inside one the error is `CpiGuardSetAuthorityBlocked`).
        - Consequence for protocols: a program that moves a user's tokens with the user's own signature in a CPI fails for these users. Have the user approve the program's PDA as delegate in a top-level instruction, then transfer as that delegate.
        - CLI: `spl-token enable-cpi-guard <ACCOUNT>` / `disable-cpi-guard` (they reallocate if needed). Kit: `getEnableCpiGuardInstruction({ token, owner })` / `getDisableCpiGuardInstruction(...)`. anchor-spl 1.2.0's `cpi_guard_enable` and `cpi_guard_disable` are deprecated, because a program can't toggle the guard through a CPI.
        
        ## Adding extensions to an existing account
        
        `Reallocate` grows the account for the listed account extension types, with the owner signing and a payer covering the extra rent; it doesn't enable anything, so send the enable instruction after it. Kit `getReallocateInstruction({ token, payer, owner, newExtensionTypes: [ExtensionType.MemoTransfer] })`, Anchor `anchor_spl::token_2022::reallocate(ctx, &types)`. For a new account, `getPostInitializeInstructionsForTokenExtensions(token, owner, [extension('MemoTransfer', { requireIncomingTransferMemos: true })])` returns the enable instructions to send after `InitializeAccount`.
        
      • confidential.md 7.1 KB
        # Confidential transfers: prerequisites and decisions
        
        Balances and transfer amounts encrypted with ElGamal, with zero-knowledge proofs checked on-chain. This page covers what to decide and set up. The step-by-step flow (keys, deposit, apply, transfer, withdraw) is in the solana-dev reference [confidential-transfers.md](../../ext/solana-dev/skills/solana-dev/references/confidential-transfers.md) and in the solana.com guides: https://solana.com/docs/tokens/extensions/confidential-transfer
        
        ## Network
        
        - Proofs are verified by the ZK ElGamal Proof program (`ZkE1Gama1Proof11111111111111111111111111111`). After a proof-forgery bug ([post-mortem](https://solana.com/news/post-mortem-june-25-2025)), mainnet disabled it at epoch 805 (feature `zkdoVwnSFnSLtGJG7irJPEYUpmb4i7sGMGcnN6T9rnC`) and re-enabled it at epoch 982 (feature `zkexuyPRdyTVbZqEAREueqL2xvvoBhRgth9xGSc1tMN`). Devnet has both (epochs 899 and 1055). On any other cluster, local validators included, run `solana feature status zkdoVwnSFnSLtGJG7irJPEYUpmb4i7sGMGcnN6T9rnC zkexuyPRdyTVbZqEAREueqL2xvvoBhRgth9xGSc1tMN -u <URL>`: the program is off when the first is active and the second isn't.
        
        ## Mint extensions
        
        All three are initialized before `InitializeMint` and can't be added later.
        
        - **ConfidentialTransferMint** `{ authority, auto_approve_new_accounts, auditor_elgamal_pubkey }`.
          - With `auto_approve_new_accounts` true, an account can use confidential transfers as soon as it is configured. With false, the confidential transfer authority must send `ApproveAccount` for each account (compliance or KYC gating). Changing the policy later doesn't touch configured accounts, and an approval can't be revoked.
          - The optional auditor key receives every transfer amount, encrypted to it (and the mint and burn amounts on a ConfidentialMintBurn mint), but not the balances. Rotating it only affects later transfers.
          - The authority approves accounts and changes the policy and auditor (`UpdateMint`). A multisig can't hold it. Rotate it with SetAuthority `ConfidentialTransferMint` (CLI `confidential-transfer-mint`).
        - **ConfidentialTransferFeeConfig**: required once the mint has both TransferFeeConfig and ConfidentialTransferMint, and not allowed without them. It holds the ElGamal key that withheld confidential fees are encrypted to. Withdrawing them is signed by the TransferFeeConfig withdraw authority; this extension's own authority only turns harvest-to-mint on or off.
        - **ConfidentialMintBurn**: the supply is encrypted as well. The mint authority signs confidential mints and `ApplyPendingBurn`, which folds pending burns into the encrypted supply; token owners sign their own confidential burns. Such a mint rejects public `MintTo`, `Burn`, deposit and withdraw (`IllegalMintBurnConversion`). NonTransferable together with ConfidentialTransferMint requires it.
        
        ## Account setup
        
        - Opt-in per token account. `Reallocate` to add ConfidentialTransferAccount (plus ConfidentialTransferFeeAmount on a fee mint), then `ConfigureAccount` with a public-key validity proof, signed by the owner. `ConfigureAccountWithRegistry` replaces the proof and the owner's signature with an ElGamal registry account.
        - Incoming confidential credits land in a pending balance. The owner moves them to the available balance with `ApplyPendingBalance`. After the maximum number of pending credits (65,536 by default, set when configuring) further credits fail until the owner applies.
        - Each deposit or transfer amount must be below 2^48. Closing an account needs `EmptyAccount` (a zero-balance proof) first.
        - Derive the ElGamal and AES keys the standard way: one signature from the wallet over a fixed message, the same keys for all of its accounts. Kit's `deriveConfidentialKeys({ signer })` does this and documents its keys as byte-identical to the CLI's and `solana-zk-sdk`'s. It needs a signer that produces deterministic Ed25519 signatures. Seed-scoped derivations produce different keys, and balances encrypted under one set can't be read with the other.
        
        ## How other extensions interact
        
        - Transfer hooks run on confidential transfers, with `amount = u64::MAX`.
        - Pausable blocks deposit, withdraw, transfer and confidential mint and burn.
        - Frozen accounts (for example under DefaultAccountState `Frozen`) can be configured but can't deposit, withdraw, send or receive until thawed.
        - The permanent delegate has no power over encrypted balances, only over the public balance.
        - A public transfer into a configured account needs the account's non-confidential credits enabled. A fee mint needs the confidential transfer-with-fee instruction and its extra proofs.
        - CpiGuard blocks owner-signed confidential transfers and burns inside a CPI. MemoTransfer applies to confidential transfers too.
        
        ## Tooling
        
        - CLI 5.6.1: `spl-token --program-2022 create-token --enable-confidential-transfers auto|manual` (with a transfer fee it also adds ConfidentialTransferFeeConfig), `configure-confidential-transfer-account`, `deposit-confidential-tokens`, `apply-pending-balance`, `transfer --confidential`, `withdraw-confidential-tokens`, `update-confidential-transfer-settings`, `enable-confidential-credits` / `disable-confidential-credits` and the non-confidential pair. It has no commands for approving or emptying accounts or for confidential mint and burn, and `transfer --confidential` on a fee mint isn't supported.
        - Kit 0.19.0: create the mint with `extension('ConfidentialTransferMint', { authority, autoApproveNewAccounts, auditorElgamalPubkey })` in `createMint` (`auditorElgamalPubkey: null` for no auditor). The account and transfer helpers live under `@solana-program/token-2022/confidential` and need the peer dependency `@solana/zk-sdk` ^0.5.1: `deriveConfidentialKeys`, `getCreateConfidentialTransferAccountInstructionPlan`, `fetchConfidentialTransferBalance`, `getApplyConfidentialPendingBalanceInstructionFromToken`, `getConfidentialTransferInstructionPlan`, `getConfidentialTransferWithFeeInstructionPlan`, `getConfidentialWithdrawInstructionPlan`, `getConfidentialMintInstructionPlan`, `getConfidentialBurnInstructionPlan`, `getEmptyConfidentialTransferAccountInstructionPlan`. Single instructions such as `getApproveConfidentialTransferAccountInstruction` come from the package root.
        - Anchor 1.2.0: anchor-spl has no confidential helpers; its confidential modules are empty placeholders.
        
        ## Reading the solana-dev reference
        
        Its Rust walkthrough of configure, deposit, apply, transfer and withdraw is the useful part. Four things in it predate the current releases:
        
        - Its "Current Network Availability" section says confidential transfers run only on a ZK-Edge test cluster. The mainnet feature above is active.
        - Its "Privacy Levels" (Disabled, Whitelisted, OptIn, Required) aren't program settings. The mint has only the authority, the auto-approve flag and the auditor, and each account has its credit flags.
        - It pins spl-token-2022 10.0.0 and imports paths that 11.0.0 doesn't have (`spl_token_2022::solana_zk_sdk`, `confidential_transfer::account_info`); the CLI 5.6.1 source imports those account-info types from `spl_token_client::zk_proofs`.
        - It derives keys per token account (`new_from_signer(authority, token_account)`), which won't match keys from the standard derivation above.
        
      • display-amounts.md 4.7 KB
        # Display amounts: InterestBearingConfig, ScaledUiAmount
        
        Both change only how a raw amount converts to a UI amount. Balances, supply, transfers, mints and burns stay in raw units; nothing on-chain rescales them. A mint can have one of the two, not both (`InvalidExtensionCombination`). Both live on the mint and add nothing to token accounts.
        
        ## InterestBearingConfig
        
        - Rate in basis points as an `i16`, so negative rates are allowed. Interest compounds continuously on the cluster clock, so the effective APY is higher than the stated rate.
        - The rate authority changes the rate with `UpdateRate`. The history collapses into one time-weighted average rate, stored as whole basis points, so UI amounts after several rate changes are approximate. Rotate the authority with SetAuthority `InterestRate` (CLI `interest-rate`).
        - CLI: `spl-token --program-2022 create-token --interest-rate <RATE_BPS>` (the rate authority is the mint authority), then `spl-token set-interest-rate <MINT> <RATE> [--rate-authority <SIGNER>]`.
        - Kit: `extension('InterestBearingConfig', { rateAuthority, initializationTimestamp: 0n, preUpdateAverageRate: rate, lastUpdateTimestamp: 0n, currentRate: rate })`; only `rateAuthority` and `currentRate` reach the initialize instruction. Later: `getUpdateRateInterestBearingMintInstruction({ mint, rateAuthority, rate })`.
        - Anchor 1.2.0: `interest_bearing_mint_initialize(ctx, rate_authority: Option<Pubkey>, rate: i16)` before `initialize_mint2`, and `interest_bearing_mint_update_rate(ctx, rate)`.
        
        ## ScaledUiAmount
        
        - UI amount = raw × multiplier (an `f64`), truncated to the mint's decimals. For stock splits, dividends paid as more units, and rebasing tokens.
        - The multiplier authority calls `UpdateMultiplier { multiplier, effective_timestamp }`. A timestamp at or before now applies immediately; a future one waits in a single pending slot, so a second update before it takes effect replaces the pending one. The multiplier must be a positive, finite, normal float, or the update fails with `InvalidScale`. Rotate the authority with SetAuthority `ScaledUiAmount` (CLI `scaled-ui-amount`).
        - CLI: `spl-token --program-2022 create-token --ui-amount-multiplier <MULTIPLIER>`, then `spl-token update-ui-amount-multiplier <MINT> <MULTIPLIER> [<UNIX_TIMESTAMP>]`. Without a timestamp the CLI uses the local clock.
        - Kit: `extension('ScaledUiAmountConfig', { authority, multiplier, newMultiplierEffectiveTimestamp: 0n, newMultiplier: multiplier })`. The Kit name is `ScaledUiAmountConfig`; in Rust the ExtensionType variant is `ScaledUiAmount` and the state struct is `ScaledUiAmountConfig`. Later: `getUpdateMultiplierScaledUiMintInstruction({ mint, authority, multiplier, effectiveTimestamp })`.
        - Anchor 1.2.0 has no helper for it. Build the instruction with `anchor_spl::token_interface::spl_token_2022::extension::scaled_ui_amount::instruction::initialize` or `update_multiplier`, then invoke it yourself.
        
        ## Showing amounts
        
        - Kit, no simulation: `amountToUiAmountForMintWithoutSimulation(rpc, mint, amount)` and `uiAmountToAmountForMintWithoutSimulation(rpc, mint, uiAmount)`. They read the mint and the Clock sysvar, so they use cluster time and pick the active multiplier. Pure variants take the parameters directly: `amountToUiAmountForInterestBearingMintWithoutSimulation(...)`, `amountToUiAmountForScaledUiAmountMintWithoutSimulation(amount, decimals, multiplier)`.
        - Kit 0.19.0's scaled raw-to-UI helper rounds at the last decimal where the program truncates, so it can show one unit more at the last decimal. For exact parity, use the on-chain `AmountToUiAmount` instruction (Kit `getAmountToUiAmountInstruction`, simulated), which returns the UI string as return data. `UiAmountToAmount` goes the other way.
        - web3.js 1.x has `...WithoutSimulation` helpers with the same names, but they truncate in both directions, so on interest-bearing mints their UI-to-raw result can be one unit below the program's rounded one. Its simulated `amountToUiAmount` and `uiAmountToAmount` default to the classic Token program, so pass `TOKEN_2022_PROGRAM_ID`.
        - Users type UI amounts. Going from UI to raw, the scaled conversions (Kit and on-chain) truncate, while the interest-bearing ones round to nearest; floor the result yourself where the raw amount must not exceed what was typed. A "max" button should send the full raw balance.
        - The CLI's `transfer`, `mint` and `burn` read amounts as `ui × 10^decimals` and ignore both extensions.
        - Scaled UI integration, from the solana.com guide: show the scaled price as well as the scaled balance, refresh the multiplier (it can change at a scheduled time), and keep raw amounts internally for accounting and history. https://solana.com/docs/tokens/extensions/scaled-ui-amount/integration-guide
        
      • fees.md 6 KB
        # Transfer fees: TransferFeeConfig, TransferFeeAmount
        
        A fee withheld from every `TransferChecked`. The sender is debited `amount`, the recipient is credited `amount - fee`, and the fee stays withheld in the recipient's token account until anyone harvests it to the mint or the withdraw authority withdraws it.
        
        - **Lives on:** the mint (TransferFeeConfig). Every token account of the mint gets TransferFeeAmount, which holds its withheld fees.
        - **Authorities:** the transfer fee config authority changes the fee; the withdraw withheld authority collects fees. Rotate them with SetAuthority types `TransferFeeConfig` and `WithheldWithdraw` (CLI `spl-token authorize <MINT> transfer-fee-config|withheld-withdraw <NEW>`, or `--disable`). Either can be None, and setting one to None can't be undone.
        
        ## Fee math
        
        - `fee = ceil(amount * basis_points / 10_000)`, capped at `maximum_fee`, and 0 when either is 0. Basis points above 10_000 fail with `TransferFeeExceedsMaximum`.
        - The mint stores an older and a newer fee; the newer one applies from its epoch on. `SetTransferFee` in epoch N makes the new fee apply from epoch N+2, and calling it again before then restarts that delay. Read the fee that applies now with `get_epoch_fee(current_epoch)` (Rust) or `getEpochFee(config, epoch)` (web3.js 1.x), not `newer_transfer_fee`.
        - Kit has no fee calculator. web3.js 1.x has `calculateEpochFee(config, epoch, amount)`; Rust has `TransferFeeConfig::calculate_epoch_fee(epoch, amount)`. For a transfer that must deliver exactly `net`, `calculate_inverse_epoch_fee(epoch, net)` returns the fee, so send `net + fee`; `get_epoch_fee(epoch).calculate_pre_fee_amount(net)` returns that gross amount directly.
        
        ## Create the mint
        
        CLI (the maximum fee is in UI units; the mint authority becomes both fee authorities):
        
        ```sh
        spl-token --program-2022 create-token --decimals 6 \
          --transfer-fee-basis-points 50 --transfer-fee-maximum-fee 5000
        ```
        
        Kit, as one entry in the `extensions` array of `createMint` or `getCreateMintInstructionPlan` (see the SKILL.md creation steps):
        
        ```ts
        extension('TransferFeeConfig', {
          transferFeeConfigAuthority: authority,
          withdrawWithheldAuthority: authority,
          withheldAmount: 0n,
          olderTransferFee: { epoch: 0n, maximumFee: 5_000_000_000n, transferFeeBasisPoints: 50 },
          newerTransferFee: { epoch: 0n, maximumFee: 5_000_000_000n, transferFeeBasisPoints: 50 },
        });
        ```
        
        Only `newerTransferFee`'s basis points and maximum reach the initialize instruction; the program sets both fees to the current epoch. For a None authority, call `getInitializeTransferFeeConfigInstruction({ mint, transferFeeConfigAuthority, withdrawWithheldAuthority, transferFeeBasisPoints, maximumFee })` yourself, since `extension()` requires both addresses.
        
        Anchor 1.2.0 has no `extensions::` constraint for fees. Create the account, then `transfer_fee_initialize(ctx, Some(&config_authority), Some(&withdraw_authority), basis_points, maximum_fee)`, then `initialize_mint2`: see the example in [programs.md](programs.md).
        
        To keep the option of a fee later, create the mint with 0 basis points and keep the fee config authority. The extension can't be added to an existing mint.
        
        ## Transfer
        
        - `TransferChecked` charges the fee. `TransferCheckedWithFee` also asserts the fee you computed and fails with `FeeMismatch` if it differs; use it when a UI has shown the user a fee (Kit `getTransferCheckedWithFeeInstruction({ source, mint, destination, authority, amount, decimals, fee })`, Anchor `transfer_checked_with_fee(ctx, amount, decimals, fee)`, CLI `spl-token transfer <MINT> <AMOUNT> <RECIPIENT> --expected-fee <UI_AMOUNT>`).
        - Plain `Transfer` fails with `MintRequiredForTransfer`.
        - A program that receives these tokens should reload the destination after the CPI and credit the balance change, not `amount`.
        - A transfer to the same account charges no fee.
        
        ## Collect withheld fees
        
        1. `HarvestWithheldTokensToMint` moves withheld fees from token accounts into the mint. Anyone can call it; it skips accounts it can't harvest and works on frozen accounts.
        2. `WithdrawWithheldTokensFromMint` (withdraw authority signs) sends the mint's withheld total to a token account of the same mint that isn't frozen. `WithdrawWithheldTokensFromAccounts` does the same straight from listed token accounts.
        
        | | Harvest to mint | Withdraw from mint | Withdraw from accounts |
        |---|---|---|---|
        | Kit | `getHarvestWithheldTokensToMintInstruction({ mint, sources })` | `getWithdrawWithheldTokensFromMintInstruction({ mint, feeReceiver, withdrawWithheldAuthority })` | `getWithdrawWithheldTokensFromAccountsInstruction({ mint, feeReceiver, withdrawWithheldAuthority, numTokenAccounts, sources })`; set `numTokenAccounts` to `sources.length`, since the program treats the surplus leading accounts as multisig signers and skips them |
        | Anchor 1.2.0 | `harvest_withheld_tokens_to_mint(ctx, sources)` | `withdraw_withheld_tokens_from_mint(ctx)` | `withdraw_withheld_tokens_from_accounts(ctx, sources)` |
        | CLI | `spl-token close` harvests first | `spl-token withdraw-withheld-tokens <RECIPIENT_ACCOUNT> --include-mint` | `spl-token withdraw-withheld-tokens <RECIPIENT_ACCOUNT> <SOURCE_ACCOUNT>...` |
        
        The Anchor wrappers take their program id from the `token_program_id` account and pass no multisig signers, so a multisig authority needs a hand-built instruction.
        
        ## Gotchas
        
        - A token account holding withheld fees can't be closed (`AccountHasWithheldTransferFees`). Harvest it to the mint first.
        - Withheld fees still count in the supply. Closing a mint (MintCloseAuthority) needs a supply of 0, so withdraw and burn them first.
        - TransferFeeConfig together with ConfidentialTransferMint also needs ConfidentialTransferFeeConfig ([confidential.md](confidential.md)); the CLI adds it when you enable both.
        - Test the two-epoch delay by warping epochs: Surfpool's `surfnet_timeTravel` takes `{"absoluteEpoch": n}` ([cheatcodes.md](../../ext/solana-dev/skills/solana-dev/references/surfpool/cheatcodes.md)).
        - Orca's pools accept fee mints without a TokenBadge; other venues set their own rules ([programs.md](programs.md)).
        
      • issuer-controls.md 8.1 KB
        # Issuer controls
        
        PermanentDelegate, DefaultAccountState, Pausable, PermissionedBurn, MintCloseAuthority and NonTransferable. All are mint extensions set before `InitializeMint`. Pausable adds PausableAccount to every token account, and NonTransferable adds NonTransferableAccount and ImmutableOwner.
        
        Each authority below is rotated with SetAuthority, signed by the current holder (CLI `spl-token authorize <MINT> <TYPE> <NEW>`, or `--disable` for None). Setting an extension authority to None is permanent: later SetAuthority calls fail with `AuthorityTypeNotSupported`. A freeze authority set to None can't come back either (`MintCannotFreeze`). Orca, for one, needs a TokenBadge for PermanentDelegate, DefaultAccountState, Pausable and MintCloseAuthority, and rejects NonTransferable ([programs.md](programs.md)).
        
        ## PermanentDelegate
        
        - A delegate that can `TransferChecked` (or `TransferCheckedWithFee`) and `Burn`/`BurnChecked` from any token account of the mint, with no approval and no amount limit. It co-signs permissioned burns too.
        - It can't use plain `Transfer`, approve, revoke, close accounts, change account authorities, or touch confidential balances. It is still stopped by frozen accounts (`AccountFrozen`), a paused mint (`MintPaused`) and NonTransferable (`NonTransferable`, although burning still works there).
        - Rotate with SetAuthority `PermanentDelegate` (CLI `permanent-delegate`). The current delegate signs; the mint authority can't replace it.
        - CLI: `create-token --enable-permanent-delegate` (the delegate is the mint authority). Kit: `extension('PermanentDelegate', { delegate })`. Anchor: `extensions::permanent_delegate::delegate = ...` on `init`, or `permanent_delegate_initialize(ctx, &delegate)`.
        - Every `InitializeAccount` for the mint logs "Warning: Mint has a permanent delegate, so tokens in this account may be seized at any time", which wallets and explorers can surface.
        
        ## DefaultAccountState
        
        - Every new token account starts `Frozen` (or `Initialized`), including associated token accounts that other people create. Only the freeze authority can thaw them.
        - `Frozen` needs a freeze authority at `InitializeMint` (`MintCannotFreeze`). The freeze authority can change the default with `UpdateDefaultAccountState`; existing accounts keep their state.
        - Removing the freeze authority while the default is `Frozen` leaves every future account frozen for good.
        - CLI: `create-token --enable-freeze --default-account-state frozen` (the extension needs `--enable-freeze`), then `spl-token update-default-account-state <MINT> <initialized|frozen>` and `spl-token thaw <ACCOUNT>`. Choosing `initialized` still adds the extension, which keeps the option of switching to frozen later.
        - Kit: `extension('DefaultAccountState', { state: AccountState.Frozen })`, `getUpdateDefaultAccountStateInstruction({ mint, freezeAuthority, state })`, `getThawAccountInstruction({ account, mint, owner: freezeAuthority })`.
        - Anchor: no constraint. `default_account_state_initialize(ctx, &AccountState::Frozen)` before `initialize_mint2`, and `default_account_state_update(ctx, &state)` (`AccountState` from `anchor_spl::token_interface::spl_token_2022::state`).
        
        ## Pausable
        
        - The pause authority stops the mint with `Pause` and restarts it with `Resume`. While paused, these fail with `MintPaused`: `TransferChecked` and `TransferCheckedWithFee`, `MintTo`, burns (standard and permissioned) and the confidential deposit, withdraw, transfer, mint and burn.
        - Still allowed while paused: approve, revoke, freeze and thaw, SetAuthority, closing accounts, creating accounts, and harvesting or withdrawing withheld fees.
        - Plain `Transfer` from any token account of the mint fails with `MintRequiredForTransfer`, paused or not.
        - The authority can't be None at initialize. Rotate it with SetAuthority `Pause` (CLI `pause`). Setting it to None while paused leaves the mint paused forever.
        - CLI: `create-token --enable-pause` (authority = mint authority), `spl-token pause <MINT>`, `spl-token resume <MINT>`. CLI 5.6.1's pause and resume drop multisig signers, so a multisig pause authority needs another client.
        - Kit: `extension('PausableConfig', { authority, paused: false })`, `getPauseInstruction({ mint, authority })`, `getResumeInstruction({ mint, authority })`. These two builders take no multisig signers.
        - Anchor: `extensions::pausable::authority = ...` on `init`, or `pausable_initialize(ctx, authority)`; then `pausable_pause(ctx)` and `pausable_resume(ctx)`.
        
        ## PermissionedBurn
        
        - While it has an authority, standard `Burn` and `BurnChecked` fail (`InvalidInstruction`). Burns go through `PermissionedBurn` or `PermissionedBurnChecked`, which need the burn authority's signature and the usual owner, delegate or permanent-delegate signature.
        - The burn authority must sign directly (no multisig): the program checks `is_signer` and the key.
        - Initialized with a non-null authority. Setting the authority to None (SetAuthority `PermissionedBurn`, CLI `permissioned-burn`) turns standard burns back on permanently.
        - CLI (spl-token-cli 5.6.1): `create-token --enable-permissioned-burn` (authority = mint authority) or `--permissioned-burn <AUTHORITY>`; burn with `spl-token burn <ACCOUNT> <AMOUNT> --permissioned-burn-authority <KEYPAIR>`. The CLI doesn't detect the extension on its own.
        - Kit: `extension('PermissionedBurn', { authority })`, `getPermissionedBurnInstruction({ account, mint, permissionedBurnAuthority, authority, amount })`, `getPermissionedBurnCheckedInstruction({ ..., decimals })`. web3.js 1.x has `createPermissionedBurnInstruction` and `createPermissionedBurnCheckedInstruction`.
        - Anchor 1.2.0: no helper, and anchor-spl's interface 2.x predates the extension. Add the 3.x interface under another name, `spl-token-2022-interface-3 = { package = "spl-token-2022-interface", version = "3.1" }`, which compiles next to anchor-spl 1.2.0. Then `invoke` its builders: `extension::permissioned_burn::instruction::initialize(&token_program, &mint, &authority)` before `initialize_mint2`, and `burn_checked(&token_program, &account, &mint, &burn_authority, &owner, &[], amount, decimals)` with those four accounts.
        - It is live on mainnet (program v11.0.0).
        
        ## MintCloseAuthority
        
        - Lets the close authority close the mint and reclaim its rent once supply is 0: `CloseAccount` with the mint as the account. Fails with `MintHasSupply` while any supply remains, including withheld transfer fees. Pausing doesn't block it.
        - A mint initialized with a None close authority can never be closed. Rotate with SetAuthority `CloseMint` (CLI `close-mint`).
        - CLI: `create-token --enable-close`, then `spl-token close-mint <MINT> [--recipient <ADDRESS>]`. Kit: `extension('MintCloseAuthority', { closeAuthority })`, then `getCloseAccountInstruction({ account: mint, destination, owner: closeAuthority })`. Anchor: `extensions::close_authority::authority = ...` on `init`, or `mint_close_authority_initialize(ctx, Some(&authority))`; close with `close_account`.
        - A closed mint address can be created again with different extensions while old token accounts still point at it. Integrations that cache mint data should re-check it; see the Token-2022 section of [security.md](../../ext/solana-dev/skills/solana-dev/references/security.md#token-2022-extension-security).
        
        ## NonTransferable (soulbound)
        
        - Every transfer fails with `NonTransferable`, whoever signs, the permanent delegate included. Burning works (owner, delegate or permanent delegate), approve works (the delegate can only burn), and an empty account can close.
        - `InitializeAccount` adds NonTransferableAccount and ImmutableOwner to every token account of the mint, so the account must have room for both; a smaller one fails at initialize with `InvalidAccountData`. Associated token accounts and Anchor's `init` are sized for them. web3.js 1.x `getAccountLenForMint` leaves out ImmutableOwner, so an account sized with it fails.
        - Adding TransferFeeConfig or TransferHook does nothing, since no transfer ever runs. With ConfidentialTransferMint it also needs ConfidentialMintBurn.
        - CLI: `create-token --enable-non-transferable`. Kit: `extension('NonTransferable', {})`. Anchor: no constraint; `non_transferable_mint_initialize(ctx)` before `initialize_mint2`.
        
      • metadata-groups.md 9.1 KB
        # Metadata and groups
        
        MetadataPointer, TokenMetadata, GroupPointer, TokenGroup, GroupMemberPointer and TokenGroupMember all live on the mint. A pointer says which account holds the data. Token-2022 itself stores metadata, group and member data only inside the mint, so the usual setup points each pointer at the mint.
        
        ## Metadata
        
        - **MetadataPointer** `{ authority, metadata_address }`, initialized before `InitializeMint`. The program doesn't check the target; point it at the mint unless another program holds the metadata. The pointer's `Update` instruction, signed by the pointer authority, changes the address (CLI `update-metadata-address`, Kit `getUpdateMetadataPointerInstruction`); SetAuthority `MetadataPointer` (CLI `authorize <MINT> metadata-pointer`) only rotates the authority.
        - **TokenMetadata** `{ update_authority, mint, name, symbol, uri, additional_metadata }`, variable length. Initialize it after `InitializeMint`:
          - The metadata account must be the mint itself (`MintMismatch`), and the mint needs a MetadataPointer (`InvalidExtensionCombination`).
          - The mint authority signs initialize. The update authority is just an address there; it signs everything after.
        - **Updates** (update authority signs; the mint authority has no say): `UpdateField` with `Name`, `Symbol`, `Uri` or `Key(custom)`; `RemoveKey` for custom keys (optionally idempotent); `UpdateAuthority`, where None makes the metadata permanently immutable (`ImmutableMetadata` afterwards); `Emit` returns the Borsh-encoded metadata as return data. Rotate the update authority with `UpdateAuthority` (CLI `spl-token authorize <MINT> metadata <NEW>`), not SetAuthority.
        - **Rent:** initialize, and any `UpdateField` or `RemoveKey` that changes the length, resize the mint but move no lamports, and the mint must stay rent-exempt at its new size. Send the lamports in an earlier instruction of the same transaction, or top up from your program in the same instruction. Shrinking leaves the extra lamports in the mint (the mint authority can reclaim them with `WithdrawExcessLamports`).
        - Readers should check that the pointer and `metadata.mint` both refer to this mint, since pointers can name any account.
        
        ### CLI
        
        ```sh
        spl-token --program-2022 create-token --enable-metadata      # pointer at the mint, authority = mint authority
        spl-token initialize-metadata <MINT> <NAME> <SYMBOL> <URI> [--update-authority <ADDRESS>]
        spl-token update-metadata <MINT> <name|symbol|uri|CUSTOM_KEY> <VALUE>   # --remove deletes a custom key
        spl-token update-metadata-address <MINT> <ADDRESS>            # or --disable
        ```
        
        The CLI's metadata commands fund the extra rent themselves.
        
        ### Kit
        
        - Create: `extension('MetadataPointer', { authority, metadataAddress: mint })` plus `extension('TokenMetadata', { updateAuthority, mint, name, symbol, uri, additionalMetadata: new Map() })` in `createMint` (see SKILL.md). It funds rent for the full metadata but initializes only name, symbol and URI; set extra fields with update instructions afterwards. With `updateAuthority: null` it skips the metadata initialize entirely.
        - Update: `getUpdateTokenMetadataFieldInstruction({ metadata: mint, updateAuthority, field: tokenMetadataField('Key', ['tier']), value: 'gold' })` (or `tokenMetadataField('Name' | 'Symbol' | 'Uri')`). No Kit helper tops up rent for a growing field: before the update, transfer the difference between `await client.getMinimumBalance(getMintSize(updatedExtensions))` (or `rpc.getMinimumBalanceForRentExemption`) and the mint's current lamports.
        - Also: `getRemoveTokenMetadataKeyInstruction({ metadata, updateAuthority, key, idempotent })`, `getUpdateTokenMetadataUpdateAuthorityInstruction({ metadata, updateAuthority, newUpdateAuthority })`, `getEmitTokenMetadataInstruction({ metadata })`, `getUpdateMetadataPointerInstruction({ mint, metadataPointerAuthority, metadataAddress })`.
        
        web3.js 1.x: `tokenMetadataInitializeWithRentTransfer` and `tokenMetadataUpdateFieldWithRentTransfer` add the rent; `getTokenMetadata(connection, mint)` reads the mint's own metadata and doesn't follow the pointer.
        
        ### Anchor 1.2.0
        
        `init` takes `extensions::metadata_pointer::{authority, metadata_address}`; TokenMetadata is a CPI after that. anchor-spl's metadata helpers never move lamports, so top up in the same instruction (Anchor's own tests top up later in the same handler):
        
        ```rust
        use anchor_lang::prelude::*;
        use anchor_lang::system_program::{transfer, Transfer};
        use anchor_spl::token_interface::{token_metadata_initialize, Mint, Token2022, TokenMetadataInitialize};
        
        #[derive(Accounts)]
        pub struct CreateMint<'info> {
            #[account(mut)]
            pub payer: Signer<'info>,
            #[account(
                init,
                signer,
                payer = payer,
                mint::decimals = 6,
                mint::authority = payer,
                mint::token_program = token_program,
                extensions::metadata_pointer::authority = payer,
                extensions::metadata_pointer::metadata_address = mint,
            )]
            pub mint: InterfaceAccount<'info, Mint>,
            pub token_program: Program<'info, Token2022>,
            pub system_program: Program<'info, System>,
        }
        
        pub fn create_mint(ctx: Context<CreateMint>, name: String, symbol: String, uri: String) -> Result<()> {
            let accounts = TokenMetadataInitialize {
                program_id: ctx.accounts.token_program.to_account_info(),
                mint: ctx.accounts.mint.to_account_info(),
                metadata: ctx.accounts.mint.to_account_info(), // the metadata lives in the mint
                mint_authority: ctx.accounts.payer.to_account_info(),
                update_authority: ctx.accounts.payer.to_account_info(),
            };
            token_metadata_initialize(CpiContext::new(ctx.accounts.token_program.key(), accounts), name, symbol, uri)?;
        
            // Token-2022 grew the mint but moved no lamports: top it up to rent-exempt
            let mint = ctx.accounts.mint.to_account_info();
            let shortfall = Rent::get()?.minimum_balance(mint.data_len()).saturating_sub(mint.lamports());
            if shortfall > 0 {
                let from = ctx.accounts.payer.to_account_info();
                transfer(CpiContext::new(ctx.accounts.system_program.key(), Transfer { from, to: mint }), shortfall)?;
            }
            Ok(())
        }
        ```
        
        Other helpers: `token_metadata_update_field(ctx, Field::Key("tier".into()), value)`, `token_metadata_remove_key(ctx, key, idempotent)`, `token_metadata_update_authority(ctx, new_authority)` (an `OptionalNonZeroPubkey`). `Field` comes from `anchor_spl::token_interface::spl_token_metadata_interface::state`. anchor-spl 1.2.0 has no `metadata_pointer_update`. Read metadata with `StateWithExtensions::<Mint>::unpack(&data)?.get_variable_len_extension::<TokenMetadata>()`.
        
        ## Groups (collections)
        
        - The collection mint carries **GroupPointer** `{ authority, group_address }` and **TokenGroup** `{ update_authority, mint, size, max_size }`. Each member mint carries **GroupMemberPointer** `{ authority, member_address }` and **TokenGroupMember** `{ mint, group, member_number }`. As with metadata, the group and member data must sit in their own mints and need their pointer.
        - `InitializeGroup`: the collection's mint authority signs and sets the update authority (may be None) and `max_size`.
        - `InitializeMember`: both the member mint's authority and the group update authority sign, and the group must be a Token-2022 mint. `member_number` becomes the new size, so the first member is 1. A mint can join one group, and can't be a member of itself.
        - A group whose update authority is None can never add members (`ImmutableGroup`). Past `max_size`, adding fails with `SizeExceedsMaxSize`. `UpdateGroupMaxSize` can't go below the current size (`SizeExceedsNewMaxSize`). Rotate the group update authority with `UpdateGroupAuthority` (CLI `spl-token authorize <MINT> group <NEW>`); the pointers use SetAuthority `GroupPointer` / `GroupMemberPointer`.
        - Group and member initializers grow the mint like metadata does and move no lamports either.
        
        | | Collection mint | Member mint |
        |---|---|---|
        | CLI | `create-token --enable-group`, then `initialize-group <MINT> <MAX_SIZE>`; `update-group-max-size`, `update-group-address` | `create-token --enable-member`, then `initialize-member <MEMBER_MINT> <GROUP_MINT> [--group-update-authority <KEYPAIR>]`; `update-member-address` |
        | Kit | `extension('GroupPointer', { authority, groupAddress: mint })`, `extension('TokenGroup', { updateAuthority, mint, size: 0n, maxSize })` in `createMint` | `extension('GroupMemberPointer', { authority, memberAddress: mint })`; `createMint` funds `extension('TokenGroupMember', ...)` but doesn't initialize it, so add `getInitializeTokenGroupMemberInstruction({ member: mint, memberMint: mint, memberMintAuthority, group, groupUpdateAuthority })` |
        | Anchor 1.2.0 | `extensions::group_pointer::{authority, group_address}` on `init`; `token_group_initialize(ctx, update_authority, max_size)`; `group_pointer_update` | `extensions::group_member_pointer::{authority, member_address}` on `init`; `token_member_initialize(ctx)`; `group_member_pointer_update` |
        
        Kit also has `getUpdateTokenGroupMaxSizeInstruction` and `getUpdateTokenGroupUpdateAuthorityInstruction`; anchor-spl 1.2.0 has neither.
        
        Orca's pools reject group and member mints. For NFT collections, the skills hub also routes to the Metaplex skill (install first: `bash .claude/bin/skills.sh add metaplex`).
        
      • programs.md 8.7 KB
        # Token-2022 in programs
        
        Checked against anchor-lang and anchor-spl 1.2.0. anchor-spl re-exports spl-token-2022-interface 2.x as `anchor_spl::token_interface::spl_token_2022` (and `anchor_spl::token_2022::spl_token_2022`). Depend on that re-export, or on `spl-token-2022-interface = "2"`, rather than on the `spl-token-2022` program crate, so one version of the types is in play. Only the 3.x interface has PermissionedBurn, the `UnwrapLamports` and `Batch` instructions, `extension::account_len` and `sync_native_with_rent_sysvar`. When you need one, add 3.x under another name next to anchor-spl's 2.x, as in [PermissionedBurn](issuer-controls.md#permissionedburn).
        
        ## Accept both token programs
        
        ```rust
        use anchor_lang::prelude::*;
        use anchor_spl::token_interface::{self, Mint, TokenAccount, TokenInterface, TransferChecked};
        
        #[derive(Accounts)]
        pub struct Pay<'info> {
            #[account(mut, token::mint = mint, token::authority = authority, token::token_program = token_program)]
            pub from: InterfaceAccount<'info, TokenAccount>,
            #[account(mut, token::mint = mint, token::token_program = token_program)]
            pub to: InterfaceAccount<'info, TokenAccount>,
            #[account(mint::token_program = token_program)]
            pub mint: InterfaceAccount<'info, Mint>,
            pub authority: Signer<'info>,
            pub token_program: Interface<'info, TokenInterface>, // Token or Token-2022
        }
        
        pub fn pay(ctx: Context<Pay>, amount: u64) -> Result<u64> {
            let before = ctx.accounts.to.amount;
            let accounts = TransferChecked {
                from: ctx.accounts.from.to_account_info(),
                mint: ctx.accounts.mint.to_account_info(),
                to: ctx.accounts.to.to_account_info(),
                authority: ctx.accounts.authority.to_account_info(),
            };
            // Anchor 1.x: CpiContext takes the program id, not an AccountInfo
            let cpi = CpiContext::new(ctx.accounts.token_program.key(), accounts);
            token_interface::transfer_checked(cpi, amount, ctx.accounts.mint.decimals)?;
            ctx.accounts.to.reload()?;
            // With a transfer fee the recipient gets less than `amount`: credit what arrived
            let received = ctx.accounts.to.amount.checked_sub(before).ok_or(ProgramError::ArithmeticOverflow)?;
            Ok(received)
        }
        ```
        
        - `token::token_program`, `mint::token_program` and `associated_token::token_program` bind each account to the token program that was passed in.
        - `transfer_checked` passes only the four base accounts, so it can't move a hook mint: see [transfer-hooks.md](transfer-hooks.md#cpi-a-transfer-of-a-hook-mint). A PDA authority uses `CpiContext::new_with_signer(program_id, accounts, signer_seeds)`.
        
        ## Allow-list a mint's extensions
        
        Decide which extensions your program supports and reject the rest before accepting a mint:
        
        ```rust
        use anchor_lang::prelude::*;
        use anchor_spl::token_interface::spl_token_2022::{
            extension::{BaseStateWithExtensions, ExtensionType, StateWithExtensions},
            state::Mint as MintState,
        };
        
        #[error_code]
        pub enum PoolError {
            #[msg("Mint is not owned by a token program")]
            NotATokenMint,
            #[msg("Mint has an extension this program does not support")]
            UnsupportedMintExtension,
        }
        
        pub fn check_mint_extensions(mint_info: &AccountInfo) -> Result<()> {
            if *mint_info.owner == anchor_spl::token::ID {
                return Ok(()); // classic Token mint: no extensions
            }
            require_keys_eq!(*mint_info.owner, anchor_spl::token_2022::ID, PoolError::NotATokenMint);
            let data = mint_info.try_borrow_data()?;
            let mint = StateWithExtensions::<MintState>::unpack(&data)?;
            // Interface 2.x fails to parse types it doesn't know (PermissionedBurn): reject those too
            let extensions = mint
                .get_extension_types()
                .map_err(|_| error!(PoolError::UnsupportedMintExtension))?;
            for extension in extensions {
                match extension {
                    ExtensionType::MetadataPointer | ExtensionType::TokenMetadata | ExtensionType::TransferFeeConfig => {}
                    _ => return err!(PoolError::UnsupportedMintExtension),
                }
            }
            Ok(())
        }
        ```
        
        For one fixed-size extension's values use `anchor_spl::token_interface::get_mint_extension_data::<T>(&mint_info)`; for TokenMetadata use `get_variable_len_extension::<TokenMetadata>()` on the unpacked state. The attack patterns behind each extension (fee accounting, permanent delegate, mint close and reinit, hook abuse) are in [security.md, Token-2022 section](../../ext/solana-dev/skills/solana-dev/references/security.md#token-2022-extension-security).
        
        ## Create a mint with extensions that have no constraint
        
        Anchor's `init` handles MetadataPointer, GroupPointer, GroupMemberPointer, TransferHook, MintCloseAuthority, PermanentDelegate and Pausable. For any other fixed-size extension, create the account, run the extension initializers, then `initialize_mint2`, all in one instruction. TokenMetadata, TokenGroup and TokenGroupMember come after `initialize_mint2`, with the rent topped up first: [metadata-groups](metadata-groups.md).
        
        ```rust
        use anchor_lang::prelude::*;
        use anchor_lang::system_program::{create_account, CreateAccount};
        use anchor_spl::token_interface::{
            initialize_mint2, transfer_fee_initialize, InitializeMint2, Token2022, TransferFeeInitialize,
            spl_token_2022::{extension::ExtensionType, state::Mint as MintState},
        };
        
        #[derive(Accounts)]
        pub struct CreateFeeMint<'info> {
            #[account(mut)]
            pub payer: Signer<'info>,
            #[account(mut)]
            pub mint: Signer<'info>,
            pub authority: Signer<'info>,
            pub token_program: Program<'info, Token2022>,
            pub system_program: Program<'info, System>,
        }
        
        pub fn create_fee_mint(ctx: Context<CreateFeeMint>, fee_bps: u16, max_fee: u64) -> Result<()> {
            // Exactly the size of the extensions initialized before initialize_mint2
            let space = ExtensionType::try_calculate_account_len::<MintState>(&[ExtensionType::TransferFeeConfig])?;
            let lamports = Rent::get()?.minimum_balance(space);
            let accounts = CreateAccount { from: ctx.accounts.payer.to_account_info(), to: ctx.accounts.mint.to_account_info() };
            create_account(
                CpiContext::new(ctx.accounts.system_program.key(), accounts),
                lamports,
                space as u64,
                &ctx.accounts.token_program.key(),
            )?;
        
            let authority = ctx.accounts.authority.key();
            let accounts = TransferFeeInitialize {
                token_program_id: ctx.accounts.token_program.to_account_info(),
                mint: ctx.accounts.mint.to_account_info(),
            };
            transfer_fee_initialize(
                CpiContext::new(ctx.accounts.token_program.key(), accounts),
                Some(&authority), // transfer fee config authority
                Some(&authority), // withdraw withheld authority
                fee_bps,
                max_fee,
            )?;
        
            let accounts = InitializeMint2 { mint: ctx.accounts.mint.to_account_info() };
            initialize_mint2(CpiContext::new(ctx.accounts.token_program.key(), accounts), 6, &authority, None)
        }
        ```
        
        - The other initializers follow the same pattern: `default_account_state_initialize`, `interest_bearing_mint_initialize`, `non_transferable_mint_initialize`, `permanent_delegate_initialize`, `mint_close_authority_initialize`, `pausable_initialize`, `transfer_hook_initialize`, `metadata_pointer_initialize`, `group_pointer_initialize`, `group_member_pointer_initialize`. `anchor_spl::token_interface::find_mint_account_size(Some(&vec![...]))` computes the same size as above.
        - These helpers take the token program from their `token_program_id` account and pass no multisig signers.
        - anchor-spl 1.2.0 has no helpers for ScaledUiAmount, PermissionedBurn or the confidential extensions. Build those instructions with the interface crate's builders (3.x for PermissionedBurn) and `invoke` them.
        
        ## Before launch
        
        - Check every target venue's extension policy. Orca Whirlpools, for example, accepts TransferFeeConfig, InterestBearingConfig, MetadataPointer, TokenMetadata and ScaledUiAmount; supports confidential mints for public transfers only; needs a TokenBadge (a Whirlpools account for that config and mint) for PermanentDelegate, TransferHook, MintCloseAuthority, DefaultAccountState, Pausable and for any freeze authority; and rejects NonTransferable and every other extension (https://github.com/orca-so/whirlpools/blob/main/programs/whirlpool/src/util/v2/token.rs, `is_supported_token_mint`).
        - The metadata and group update authorities and the PermissionedBurn authority are checked as direct signers, so an SPL Token multisig can't hold them. Setting an extension authority to None is permanent.
        - Tests: [testing.md](../../ext/solana-dev/skills/solana-dev/references/testing.md) (LiteSVM, Mollusk). On a Surfpool fork, `surfnet_setTokenAccount` takes the token program as an optional last parameter, and `surfnet_timeTravel` with `absoluteEpoch` crosses the two-epoch fee delay ([cheatcodes.md](../../ext/solana-dev/skills/solana-dev/references/surfpool/cheatcodes.md)).
        
      • transfer-hooks.md 10.9 KB
        # Transfer hooks: TransferHook, TransferHookAccount
        
        The mint names a hook program. Every `TransferChecked` or `TransferCheckedWithFee` moves the balances, then CPIs the hook's `Execute` instruction; if the hook fails, the whole transfer fails.
        
        - **Lives on:** the mint (TransferHook: authority and program id). Every token account of the mint gets TransferHookAccount, whose `transferring` flag is true only while the hook runs.
        - **Authority:** the hook authority changes or clears the program id (`UpdateTransferHook`; None disables the hook). Rotate the authority with SetAuthority type `TransferHookProgramId` (CLI `spl-token authorize <MINT> transfer-hook-program-id <NEW>`). Despite the name, that rotates the authority, not the program id.
        
        ## When the hook runs
        
        - On `TransferChecked`, `TransferCheckedWithFee` and confidential transfers. A confidential transfer calls it with `amount = u64::MAX`, because the real amount is encrypted. Mint, burn and confidential deposit or withdraw never call it.
        - Skipped when the mint has no program id, and for a `TransferChecked` or `TransferCheckedWithFee` to the same account; a confidential transfer to the same account still calls it. Zero-amount transfers call it too.
        - Plain `Transfer` fails with `MintRequiredForTransfer`.
        - Execute accounts: 0 source, 1 mint, 2 destination, 3 source owner or delegate, 4 the ExtraAccountMetaList PDA, then the extra accounts in list order. All of them arrive read-only and without signer privileges, even the one that signed the transfer, so anything the hook writes must be an extra account marked writable in its list.
        - If the transaction doesn't carry the ExtraAccountMetaList PDA, Token-2022 still calls the hook, with only the four base accounts. Whether that fails is up to the hook.
        
        ## ExtraAccountMetaList
        
        - A PDA of the hook program with seeds `["extra-account-metas", mint]`: Rust `get_extra_account_metas_address(&mint, &hook_program_id)`, Kit `findExtraAccountMetaListPda({ mint }, { programAddress: hookProgram })`.
        - Entries (spl-tlv-account-resolution 0.11): `ExtraAccountMeta::new_with_pubkey` (fixed address), `new_with_seeds` (PDA of the hook program), `new_external_pda_with_seeds(program_index, ...)` (PDA of another program in the list), `new_with_pubkey_data` (address read from account or instruction data).
        - Seeds: `Seed::Literal { bytes }`, `Seed::AccountKey { index }`, `Seed::AccountData { account_index, data_index, length }`, `Seed::InstructionData { index, length }`; the amount is `index: 8, length: 8`. Account indexes follow the Execute order above, then earlier extras. Packed seeds must fit in 32 bytes.
        - Allocate `ExtraAccountMetaList::size_of(n)` and write it with `ExtraAccountMetaList::init::<ExecuteInstruction>(data, &metas)`. It must exist before the first transfer. The interface's own InitializeExtraAccountMetaList takes `[meta list (writable), mint, mint authority (signer), system program]`; whichever instruction writes the list, the hook program decides who may call it, so check the mint authority.
        - Changing the list later (`UpdateExtraAccountMetaList`) breaks clients and programs that pass the old accounts.
        
        ## Write the hook (Anchor 1.2.0)
        
        Anchor 1.x has no `#[interface]` attribute. Set the handler's discriminator to the interface's Execute discriminator instead. anchor-spl doesn't bring the interface crates: add `spl-transfer-hook-interface` 2.1, `spl-tlv-account-resolution` 0.11 and `spl-discriminator` 0.5. They use the same Solana 3.x crates as anchor-lang 1.2, so `?` converts their errors.
        
        ```rust
        use anchor_lang::prelude::*;
        use anchor_spl::token_interface::{
            spl_token_2022::extension::{transfer_hook::TransferHookAccount, BaseStateWithExtensions, StateWithExtensions},
            spl_token_2022::state::Account as TokenAccountState,
            Mint, TokenAccount,
        };
        use spl_discriminator::SplDiscriminate;
        use spl_tlv_account_resolution::{account::ExtraAccountMeta, seeds::Seed, state::ExtraAccountMetaList};
        use spl_transfer_hook_interface::instruction::ExecuteInstruction;
        
        #[program]
        pub mod allowlist_hook {
            use super::*;
        
            pub fn initialize_extra_account_meta_list(ctx: Context<InitializeExtraAccountMetaList>) -> Result<()> {
                let metas = [ExtraAccountMeta::new_with_seeds(
                    &[Seed::Literal { bytes: b"allow".to_vec() }, Seed::AccountKey { index: 3 }],
                    false, // is_signer
                    false, // is_writable
                )?];
                ExtraAccountMetaList::init::<ExecuteInstruction>(
                    &mut ctx.accounts.extra_account_meta_list.try_borrow_mut_data()?,
                    &metas,
                )?;
                Ok(())
            }
        
            #[instruction(discriminator = ExecuteInstruction::SPL_DISCRIMINATOR_SLICE)]
            pub fn transfer_hook(ctx: Context<TransferHook>, _amount: u64) -> Result<()> {
                // The flag is set only while Token-2022 is mid-transfer, so direct calls fail here
                let info = ctx.accounts.source.to_account_info();
                let data = info.try_borrow_data()?;
                let source = StateWithExtensions::<TokenAccountState>::unpack(&data)?;
                let flag = source.get_extension::<TransferHookAccount>()?;
                require!(bool::from(flag.transferring), HookError::NotTransferring);
                require!(ctx.accounts.allow_entry.data_len() > 0, HookError::NotAllowed);
                Ok(())
            }
        }
        
        #[derive(Accounts)]
        pub struct InitializeExtraAccountMetaList<'info> {
            #[account(mut)]
            pub payer: Signer<'info>,
            #[account(mint::authority = mint_authority)]
            pub mint: InterfaceAccount<'info, Mint>,
            pub mint_authority: Signer<'info>,
            /// CHECK: the ExtraAccountMetaList PDA, written above
            #[account(init, payer = payer, space = ExtraAccountMetaList::size_of(1)?,
                seeds = [b"extra-account-metas", mint.key().as_ref()], bump)]
            pub extra_account_meta_list: UncheckedAccount<'info>,
            pub system_program: Program<'info, System>,
        }
        
        // Field order is fixed by Execute: source, mint, destination, owner, meta list, extras
        #[derive(Accounts)]
        pub struct TransferHook<'info> {
            #[account(token::mint = mint)]
            pub source: InterfaceAccount<'info, TokenAccount>,
            pub mint: InterfaceAccount<'info, Mint>,
            #[account(token::mint = mint)]
            pub destination: InterfaceAccount<'info, TokenAccount>,
            /// CHECK: source owner or delegate, passed without signer privileges
            pub owner: UncheckedAccount<'info>,
            /// CHECK: checked by its seeds
            #[account(seeds = [b"extra-account-metas", mint.key().as_ref()], bump)]
            pub extra_account_meta_list: UncheckedAccount<'info>,
            /// CHECK: this program's allowlist PDA for the transfer authority; empty means not allowed
            #[account(seeds = [b"allow", owner.key().as_ref()], bump)]
            pub allow_entry: UncheckedAccount<'info>,
        }
        
        #[error_code]
        pub enum HookError {
            #[msg("Hook called outside a Token-2022 transfer")]
            NotTransferring,
            #[msg("Transfer authority is not on the allowlist")]
            NotAllowed,
        }
        ```
        
        Account 3 is whoever signed the transfer (owner, delegate or permanent delegate), so this allowlist checks that signer. If the hook also has to accept confidential transfers, handle `amount == u64::MAX`.
        
        ## Create the mint
        
        - CLI: `spl-token --program-2022 create-token --transfer-hook <HOOK_PROGRAM_ID>` (the mint authority becomes the hook authority), or `--enable-transfer-hook` to add the extension with no program yet. Later: `spl-token set-transfer-hook <MINT> <NEW_PROGRAM_ID>`, or `--disable`.
        - Kit: `extension('TransferHook', { authority, programId })`; later `getUpdateTransferHookInstruction({ mint, authority, programId })`.
        - Anchor 1.2.0: `extensions::transfer_hook::authority = ...` and `extensions::transfer_hook::program_id = ...` on `init`; otherwise `transfer_hook_initialize(ctx, authority, program_id)` (both `Option<Pubkey>`) and `transfer_hook_update(ctx, program_id)`.
        - Creating the mint with a hook authority but no program keeps the option of adding a hook later without a new mint.
        
        ## Send a transfer
        
        - Kit: `getTransferCheckedWithTransferHookInstructionAsync(client, { source, mint, destination, authority, amount, decimals })` reads the mint and appends the extras, the hook program and the meta list PDA; for a mint without a hook it returns a plain `transferChecked`. The plugin exposes it as `client.token2022.instructions.transferCheckedWithTransferHook(...)`. The plugin's `transferToATA` does not add hook accounts.
        - web3.js 1.x: `createTransferCheckedWithTransferHookInstruction(connection, source, mint, destination, owner, amount, decimals, multiSigners, commitment, TOKEN_2022_PROGRAM_ID)`. Its program id defaults to the classic Token program, so pass the Token-2022 id.
        - Rust clients: `offchain::create_transfer_checked_instruction_with_extra_metas` from the full `spl-token-2022` crate (anchor-spl's interface re-export has no `offchain` module), or `spl_transfer_hook_interface::offchain::add_extra_account_metas_for_execute`.
        - CLI: `spl-token transfer` resolves the extra accounts when online; `--transfer-hook-account <PUBKEY>:<ROLE>` adds one by hand (roles `readonly`, `writable`, `readonly-signer`, `writable-signer`).
        
        ## CPI a transfer of a hook mint
        
        `anchor_spl::token_interface::transfer_checked` builds the instruction from the four base accounts only and ignores `remaining_accounts`, so it can't move a hook mint. Build the instruction yourself and add the hook's accounts, which the caller passes as remaining accounts (hook program, meta list PDA, extras):
        
        ```rust
        use anchor_lang::solana_program::program::invoke_signed;
        use anchor_spl::token_interface::{get_mint_extension_data, spl_token_2022::{self, extension::transfer_hook::TransferHook}};
        use spl_transfer_hook_interface::onchain::add_extra_accounts_for_execute_cpi;
        
        pub fn send<'info>(ctx: Context<'info, Send<'info>>, amount: u64) -> Result<()> {
            let a = &ctx.accounts;
            let mint_info = a.mint.to_account_info();
            let mut ix = spl_token_2022::instruction::transfer_checked(
                &a.token_program.key(), &a.from.key(), &a.mint.key(), &a.to.key(),
                &a.authority.key(), &[], amount, a.mint.decimals,
            )?;
            let mut infos = vec![a.from.to_account_info(), mint_info.clone(), a.to.to_account_info(), a.authority.to_account_info()];
            if let Ok(hook) = get_mint_extension_data::<TransferHook>(&mint_info) {
                if let Some(hook_program_id) = Option::<Pubkey>::from(hook.program_id) {
                    add_extra_accounts_for_execute_cpi(
                        &mut ix, &mut infos, &hook_program_id,
                        a.from.to_account_info(), mint_info.clone(), a.to.to_account_info(), a.authority.to_account_info(),
                        amount, ctx.remaining_accounts,
                    )?;
                }
            }
            invoke_signed(&ix, &infos, &[]) // add signer seeds when a PDA is the authority
                .map_err(Into::into)
        }
        ```
        
        - Name the `'info` lifetime on `Context` as above; with the elided form, borrowing `ctx.remaining_accounts` next to the account infos doesn't compile.
        - `add_extra_accounts_for_execute_cpi` fails with `IncorrectAccount` if the hook program isn't among the remaining accounts.
        - With the full `spl-token-2022` crate (feature `no-entrypoint`), `spl_token_2022::onchain::invoke_transfer_checked` does the same in one call.
        
    • SKILL.md 12.9 KB
      ---
      name: token-extensions
      description: Token-2022 (Token Extensions) on Solana. Pick, combine and create mint and account extensions with the spl-token CLI, @solana/kit or Anchor, and integrate extension mints. Use for transfer fees, hooks, metadata, groups, pausable, permanent delegate, soulbound, interest-bearing, scaled UI or confidential tokens.
      user-invocable: true
      ---
      
      # Token Extensions (Token-2022)
      
      Program `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`. Checked on 2026-09-30 against the mainnet program (spl-token-2022 v11.0.0, per its verified build), spl-token-2022-interface 3.1.2, spl-token-cli 5.6.1, `@solana-program/token-2022` 0.19.0 on `@solana/kit` 8, and anchor-lang / anchor-spl 1.2.0. Newer releases may rename things; check before relying on a name from memory.
      
      Links into the kit's `ext/` directory, here and in the references, need its full install; in a plugin install, read the same paths in solana-foundation/solana-dev-skill.
      
      ## Pick the extensions
      
      Fixed-size mint extensions can only be set before `InitializeMint`, so pick them up front. TokenMetadata, TokenGroup and TokenGroupMember can be initialized later, but only if their pointer was set at creation. Venues accept different sets; Orca's rules are in [programs](references/programs.md).
      
      | Extension (mint) | Use it for | Authority | Token accounts get | Read |
      |---|---|---|---|---|
      | TransferFeeConfig | A fee withheld on every transfer | fee config, withdraw withheld | TransferFeeAmount | [fees](references/fees.md) |
      | TransferHook | Your program runs on every transfer | hook authority (sets the program id) | TransferHookAccount | [transfer-hooks](references/transfer-hooks.md) |
      | MetadataPointer + TokenMetadata | Name, symbol, URI and fields stored on the mint | pointer authority, metadata update authority | | [metadata-groups](references/metadata-groups.md) |
      | GroupPointer + TokenGroup | A collection parent mint | pointer authority, group update authority | | [metadata-groups](references/metadata-groups.md) |
      | GroupMemberPointer + TokenGroupMember | A mint inside a collection | pointer authority; group update authority co-signs | | [metadata-groups](references/metadata-groups.md) |
      | PermanentDelegate | Issuer can transfer or burn from any account | permanent delegate | | [issuer-controls](references/issuer-controls.md) |
      | DefaultAccountState | New accounts start frozen (KYC gating) | freeze authority | | [issuer-controls](references/issuer-controls.md) |
      | Pausable | Stop transfers, mints and burns | pause authority | PausableAccount | [issuer-controls](references/issuer-controls.md) |
      | PermissionedBurn | Burning needs an extra authority | permissioned-burn authority | | [issuer-controls](references/issuer-controls.md) |
      | NonTransferable | Soulbound: holders can't transfer | none | NonTransferableAccount, ImmutableOwner | [issuer-controls](references/issuer-controls.md) |
      | MintCloseAuthority | Close the mint once supply is 0 | close authority | | [issuer-controls](references/issuer-controls.md) |
      | InterestBearingConfig | Displayed amount accrues interest | rate authority | | [display-amounts](references/display-amounts.md) |
      | ScaledUiAmount | Displayed amount = raw × multiplier | multiplier authority | | [display-amounts](references/display-amounts.md) |
      | ConfidentialTransferMint (+ ConfidentialTransferFeeConfig, ConfidentialMintBurn) | Encrypted balances and amounts | confidential authority, auditor key | ConfidentialTransferAccount, opt-in per account | [confidential](references/confidential.md) |
      
      Holder-side account extensions (ImmutableOwner, MemoTransfer, CpiGuard), account sizing and Reallocate: [account-extensions](references/account-extensions.md). Accepting any Token-2022 mint in a program, and CPIs from Anchor: [programs](references/programs.md).
      
      ## Combinations
      
      | Combination | Result |
      |---|---|
      | ConfidentialTransferFeeConfig without both TransferFeeConfig and ConfidentialTransferMint | Rejected at `InitializeMint`: `InvalidExtensionCombination` |
      | TransferFeeConfig + ConfidentialTransferMint without ConfidentialTransferFeeConfig | Rejected: `InvalidExtensionCombination` |
      | ConfidentialMintBurn without ConfidentialTransferMint | Rejected: `InvalidExtensionCombination` |
      | NonTransferable + ConfidentialTransferMint without ConfidentialMintBurn | Rejected: `InvalidExtensionCombination` |
      | InterestBearingConfig + ScaledUiAmount | Rejected: `InvalidExtensionCombination` |
      | DefaultAccountState `Frozen` without a freeze authority | Rejected: `MintCannotFreeze` |
      | NonTransferable + TransferFeeConfig or TransferHook | Accepted, but pointless: every transfer fails with `NonTransferable` |
      | NonTransferable + PermanentDelegate | The delegate can burn but not transfer |
      | TransferHook + ConfidentialTransferMint | Confidential transfers call the hook with `amount = u64::MAX` |
      | Pausable, while paused | `TransferChecked`, `MintTo` and burns fail with `MintPaused` |
      
      Tooling gaps: anchor-spl 1.2.0 has no helpers for ScaledUiAmount, PermissionedBurn or the confidential extensions (it builds on spl-token-2022-interface 2.x, which has no PermissionedBurn), and spl-token-cli 5.6.1 can't initialize ConfidentialMintBurn.
      
      Confidential transfers need the ZK ElGamal Proof program enabled on the cluster (on mainnet since epoch 982, and on devnet), a per-account opt-in (Reallocate, then ConfigureAccount with a proof), and an owner who applies pending balances. Decisions and what is out of date in the linked Rust walkthrough: [confidential](references/confidential.md).
      
      ## Create a mint
      
      One transaction, in this order:
      
      1. Create the account, owned by Token-2022, with space for the fixed-size extensions only: `getMintSize(extensions)` (Kit), `ExtensionType::try_calculate_account_len::<Mint>(&types)` (Rust), `getMintLen(types)` (web3.js 1.x). `InitializeMint` rejects any other length (`InvalidAccountData`) and a mint below the rent-exempt minimum (`NotRentExempt`).
      2. Each extension's initialize instruction. On an initialized mint these fail with `AlreadyInUse`, so fixed-size extensions can't be added later.
      3. `InitializeMint2` (or `InitializeMint`).
      4. TokenMetadata, TokenGroup and TokenGroupMember. They grow the mint but move no lamports, so fund the mint for its final size in step 1 (Kit's `createMint` does), or transfer the difference to the mint before the initialize, in an earlier instruction of the same transaction (the CLI does) or in your program before the CPI.
      
      Kit: the plugin's `createMint` does the sizing, funding and ordering. It doesn't initialize TokenGroupMember, doesn't write `additionalMetadata` (it only pays rent for it), and skips TokenMetadata when `updateAuthority` is null ([metadata-groups](references/metadata-groups.md)). `client` is a Kit 8 client with an RPC, a payer and transaction planning and sending ([Kit plugins](../ext/solana-dev/skills/solana-dev/references/kit/plugins.md)).
      
      ```ts
      import { generateKeyPairSigner } from '@solana/kit';
      import { extension, token2022Program } from '@solana-program/token-2022';
      
      const token = client.use(token2022Program());
      const mint = await generateKeyPairSigner();
      const authority = client.payer.address;
      await token.token2022.instructions
        .createMint({
          newMint: mint,
          decimals: 6,
          mintAuthority: client.payer,
          extensions: [
            extension('MetadataPointer', { authority, metadataAddress: mint.address }),
            extension('TokenMetadata', {
              updateAuthority: authority, mint: mint.address,
              name: 'Example', symbol: 'EXM', uri: 'https://example.com/exm.json',
              additionalMetadata: new Map(),
            }),
          ],
        })
        .sendTransaction();
      ```
      
      Without the plugin, compose the same steps with `getMintSize`, `getPreInitializeInstructionsForMintExtensions`, `getInitializeMintInstruction` and `getPostInitializeInstructionsForMintExtensions`, or call `getCreateMintInstructionPlan(client, input)`.
      
      CLI: `spl-token --program-2022 create-token --decimals 6 --enable-metadata` then `spl-token initialize-metadata <MINT> Example EXM https://example.com/exm.json`. After creation the CLI infers the program from the account's owner, so later commands don't need `--program-2022`, except with `--sign-only`, where it can't look the account up and defaults to classic Token.
      
      Anchor 1.2.0: `init` on an `InterfaceAccount<'info, Mint>` accepts `extensions::metadata_pointer::{authority, metadata_address}`, `extensions::group_pointer::{authority, group_address}`, `extensions::group_member_pointer::{authority, member_address}`, `extensions::transfer_hook::{authority, program_id}`, `extensions::close_authority::authority`, `extensions::permanent_delegate::delegate` and `extensions::pausable::authority`. The same constraints on an existing mint check the extension's values. TokenMetadata, TokenGroup and TokenGroupMember are CPIs after `init` ([metadata-groups](references/metadata-groups.md)); the other extensions need a manual create-and-initialize sequence ([programs](references/programs.md)).
      
      ## Token accounts and transfers
      
      - Associated token accounts derive from the token program id. Pass the Token-2022 id (`findAssociatedTokenPda({ owner, mint, tokenProgram })`, `getAssociatedTokenAddressSync(mint, owner, false, TOKEN_2022_PROGRAM_ID)`), or you get the address of an account that doesn't exist. web3.js's `createAssociatedTokenAccountIdempotentInstructionWithDerivation` derives with the classic program id even when you pass Token-2022; derive the address yourself.
      - Token accounts need the extensions their mint requires (table above). Associated token accounts and Anchor's `init` get them. For an account you create yourself, note that Kit's `getTokenSize` counts only the extensions you pass it: [account-extensions](references/account-extensions.md).
      - Transfer with `TransferChecked`. Plain `Transfer` fails with `MintRequiredForTransfer` when the source account has TransferFeeAmount, TransferHookAccount or PausableAccount, because the program needs the mint to charge the fee, call the hook or check the pause.
      - With a fee, the recipient gets `amount - fee`: credit the balance delta, not the argument. The fee stays withheld in the recipient's account until anyone harvests it to the mint or the withdraw authority withdraws it; an account holding withheld fees can't close ([fees](references/fees.md)).
      - With a hook, the hook program's ExtraAccountMetaList PDA (seeds `["extra-account-metas", mint]`) must exist before the first transfer, and every transfer appends the hook program, that PDA and the extra accounts it lists (Kit: `getTransferCheckedWithTransferHookInstructionAsync`).
      - A `TransferChecked` to the same account moves nothing, charges no fee and skips the hook. Confidential transfers have no such shortcut and call the hook.
      - In a program, `anchor_spl::token_interface::transfer_checked` passes only the four base accounts, so it can't move a hook mint: [transfer-hooks](references/transfer-hooks.md#cpi-a-transfer-of-a-hook-mint).
      - Destinations with MemoTransfer enabled need a memo instruction right before the transfer. Owners with CpiGuard enabled can't sign transfers inside a CPI.
      
      ## Reading an unknown mint
      
      - Kit: `fetchMint(rpc, address)` then `mint.data.extensions`, an `Option` of an array tagged by `__kind`. web3.js 1.x: `getExtensionTypes(mint.tlvData)` on the result of `getMint(connection, address, undefined, TOKEN_2022_PROGRAM_ID)`. Rust: `StateWithExtensions::<Mint>::unpack(&data)?` then `get_extension_types()` or `get_extension::<T>()`; Anchor: `anchor_spl::token_interface::get_mint_extension_data::<T>(&account_info)`.
      - Match on each tool's own names. Kit's `__kind` is `ScaledUiAmountConfig`, `PausableConfig` and `ConfidentialTransferFee` where Rust says ScaledUiAmount, Pausable and ConfidentialTransferFeeConfig; web3.js uses `ScaledUiAmountConfig` and `PausableConfig`. Under anchor-spl 1.2.0 (interface 2.x), `get_extension_types()` fails with `InvalidAccountData` on a PermissionedBurn mint, while `get_extension::<T>()` still works.
      - Allow-list the extensions you support. PermanentDelegate, TransferHook, Pausable, DefaultAccountState, NonTransferable and TransferFeeConfig each change what your program or UI can rely on; the attack side is in [security.md, Token-2022 section](../ext/solana-dev/skills/solana-dev/references/security.md#token-2022-extension-security).
      - Show balances with the mint's UI conversion when InterestBearingConfig or ScaledUiAmount is present: [display-amounts](references/display-amounts.md).
      
      ## Related
      
      - [kit/programs/token-2022.md](../ext/solana-dev/skills/solana-dev/references/kit/programs/token-2022.md): the Kit client basics. [confidential-transfers.md](../ext/solana-dev/skills/solana-dev/references/confidential-transfers.md): the Rust confidential flow; [confidential](references/confidential.md) lists what in it is out of date. [testing.md](../ext/solana-dev/skills/solana-dev/references/testing.md): LiteSVM and Mollusk.
      - NFTs and collections: the skills hub also routes to the Metaplex skill (install first: `bash .claude/bin/skills.sh add metaplex`).
      - Official guides: https://solana.com/docs/tokens/extensions
      
  • backend-async.md 4.9 KB
    ---
    name: backend-async
    description: "Solana-specific rules for Rust backends and indexers: async RPC client, commitment, RPC limits, stream reconnect and backfill, idempotent indexing, send/confirm with priority fees."
    ---
    
    # Rust backends and indexers
    
    Only the Solana-specific parts; Axum, Tokio and SQLx are used as usual. Helius APIs (Laserstream, Sender, webhooks): [helius skill](ext/helius/helius-skills/helius/SKILL.md) (install first: `bash .claude/bin/skills.sh add helius`).
    
    ## RPC client
    
    - Use the nonblocking `RpcClient` (`solana_rpc_client::nonblocking::rpc_client`) in an `Arc`, with a timeout (`new_with_timeout_and_commitment`). The blocking client runs its own runtime via `block_in_place`, which panics on a current-thread runtime (the `#[tokio::test]` default) and parks a worker otherwise; `anchor-client` needs `features = ["async"]`.
    - Keep `spawn_blocking` for CPU work (bulk signing, proofs), not RPC.
    - Batch reads: `get_multiple_accounts` (100 keys), `data_slice`, memcmp filters. Unfiltered `getProgramAccounts` is slow or disabled on most providers; index instead. `getSignaturesForAddress` pages at 1,000 via `before`/`until`.
    - Retry 429, 5xx and timeouts with jittered backoff and `Retry-After`, not simulation or parameter errors. Public endpoints are for development.
    - Transaction v1 is live on mainnet: pass `max_supported_transaction_version: Some(1)` to `get_transaction`/`get_block`, or a single v1 transaction fails the whole block. Geyser detection and 4.x crates: [transactions-v1.md](ext/solana-dev/skills/solana-dev/references/transactions-v1.md).
    
    ## Commitment
    
    - `confirmed` for API reads and blockhashes; `processed` only if you handle forks yourself.
    - `finalized` before irreversible off-chain effects (crediting deposits, payouts), or treat `confirmed` as provisional and reconcile at finalized.
    - Fetch the blockhash and run preflight at the same commitment; a blockhash newer than the preflight bank fails with `BlockhashNotFound`.
    - Read your own writes with `min_context_slot` set to the write's slot; load-balanced RPCs otherwise answer from a lagging node.
    
    ## Streams
    
    - Subscriptions drop silently and never replay. Run a watchdog (a slot subscription as heartbeat) and resubscribe with backoff.
    - On reconnect, backfill the gap: page `getSignaturesForAddress(program, until = last_processed_signature)` backward, then process oldest first through the same idempotent path. Laserstream/Yellowstone take `from_slot = last_processed_slot` ([Laserstream](ext/helius/helius-skills/helius/references/laserstream.md) replays about 24 h; install first: `bash .claude/bin/skills.sh add helius`).
    - Yellowstone gRPC: answer server pings with a ping `SubscribeRequest` or load balancers drop the stream; pin `yellowstone-grpc-proto >= 12.6.0` so v1 message config decodes.
    - Decode events from `emit_cpi!` inner-instruction data or from instructions, not logs: logs truncate, and `logsSubscribe` carries no account data.
    
    ## Indexer rules
    
    - Idempotent writes keyed by `signature` for transactions and `(signature, instruction path)` for events (one transaction can emit several); `ON CONFLICT DO NOTHING`.
    - Stamp rows with `slot` (plus Geyser `write_version` for accounts) and upsert account state only when `(slot, write_version)` is newer: backfill and live data interleave.
    - Ingest at `confirmed`, mark rows provisional, promote once the slot finalizes, delete rows from slots that never do. At `processed`, also handle Geyser dead-slot status.
    - Commit the checkpoint (last slot or signature) in the same DB transaction as its rows.
    - Failed transactions (`meta.err`) pay fees and appear in signature lists; skip their state changes.
    - Decode with the IDL version live at that slot; upgrades change layouts.
    - Alert on ingestion lag (tip slot minus last processed slot).
    
    ## Sending transactions
    
    - `get_latest_blockhash_with_commitment(confirmed)` also returns `last_valid_block_height`; expiry is by block height, not time.
    - Simulate once to size the compute limit (consumed plus 10-20%); the v0 fee is limit x price, so overshooting wastes lamports. Price from `getRecentPrioritizationFees` over the writable accounts you lock (capped percentile) or [a provider estimate](ext/helius/helius-skills/helius/references/priority-fees.md) (install first: `bash .claude/bin/skills.sh add helius`). In v1 transactions the priority fee is a lamport total, and unset compute and data limits are zero, not defaults.
    - Send with `skip_preflight: true` (already simulated) and `max_retries: Some(0)`; rebroadcast the same signed bytes every ~2 s while polling `get_signature_statuses`, until confirmed or the block height passes `last_valid_block_height`.
    - Re-sign with a fresh blockhash only after the old one expired, or both can land. Durable nonces for slow or multi-party signing.
    - Landing services (Helius Sender, Jito) add tip and preflight rules: [sender.md](ext/helius/helius-skills/helius/references/sender.md) (install first: `bash .claude/bin/skills.sh add helius`).
    
  • deployment.md 8.1 KB
    ---
    name: deployment
    description: "Program deployment runbook: devnet then mainnet, verifiable builds, Squads v4 multisig upgrades, upgrade-authority staging, rollback, and cost estimation."
    ---
    
    # Deployment
    
    The runbook behind `/deploy`; `/setup-ci-cd` owns the CI workflow. Kit policy: devnet first, and mainnet only with the user's explicit go-ahead. Get that go-ahead yourself; do not rely on a tool gate to stop you. Claude Code adds one: every command below that writes a program, buffer or authority (`solana program`, `anchor deploy|upgrade`, `anchor program`) stops for the user's approval on any cluster, with the cluster it resolved in the prompt, and `--final`, `close --bypass-warning` and `program-v4 finalize` are blocked, so the user runs them. Runtimes that do not read `settings.json` (Codex, opencode) have no gate at all, so every mainnet command needs explicit confirmation first.
    
    ## Anchor 1.x changes that affect deploys
    
    - `anchor deploy` also uploads the IDL to Program Metadata (`--no-idl` skips it). `anchor idl init|upgrade --filepath target/idl/<name>.json` republishes it; the program ID comes from the IDL's `address`.
    - A program deployed with Anchor 0.32 or older that has a legacy IDL account: close it with the 0.32 CLI (`anchor idl close <PROGRAM_ID>`) while the 0.32 binary is still deployed, then deploy the 1.x binary, or that rent is stranded. See [migrating-v0.32-to-v1.md](ext/solana-dev/skills/solana-dev/references/anchor/migrating-v0.32-to-v1.md), sections 5 and 10.
    - Anchor no longer shells out to the `solana` CLI. Loader flags go after `--`: `anchor deploy -- --with-compute-unit-price 50000`. `anchor program deploy|upgrade|write-buffer|set-buffer-authority|set-upgrade-authority|show|dump|close` mirror the `solana program` commands used below, and newer CLIs deprecate top-level `anchor deploy`/`anchor upgrade` in their favor.
    - `anchor verify <PROGRAM_ID>` wraps `solana-verify` since 0.32; binaries built with older Anchor will not verify with it.
    
    ## Build once, deploy that artifact
    
    1. `/test-rust` green, `/audit-solana` for code that holds funds, `/profile-cu` baseline recorded.
    2. `anchor build` for the IDL and types, then `solana-verify build --library-name <lib>` last. It rebuilds `target/deploy/<lib>.so` in Docker, and it is the build that `solana-verify verify-from-repo` and `anchor verify` reproduce. Any later `anchor build` or `cargo build-sbf` overwrites that file with a non-deterministic binary.
    3. Record `solana-verify get-executable-hash target/deploy/<lib>.so` next to the release commit.
    4. Back up `target/deploy/<name>-keypair.json` (it is the program address) outside the repo before the first deploy.
    
    ## Devnet
    
    ```bash
    anchor deploy -p <name> --provider.cluster devnet          # first deploy
    anchor upgrade target/deploy/<lib>.so --program-id <PROGRAM_ID> --provider.cluster devnet
    solana program show <PROGRAM_ID> -u devnet
    solana logs <PROGRAM_ID> -u devnet                         # while exercising each instruction
    ```
    
    Rehearse the exact mainnet flow here, including a multisig upgrade through a devnet Squad.
    
    ## Cost estimation
    
    - Program rent: `solana rent $(( $(wc -c < target/deploy/<lib>.so) + 45 ))` (ProgramData has a 45-byte header). With `--max-len <N>` to reserve growth room, use N + 45.
    - A buffer holding about the same rent exists while writing; the deploy or upgrade instruction drains it to the payer (first deploy) or the spill account (upgrade).
    - Writing takes many transactions (roughly one per KB of program). On mainnet add `--with-compute-unit-price <micro-lamports>`, use `--use-rpc` to send writes through the RPC instead of directly to leaders (more reliable from CI or behind NAT), and `--max-sign-attempts` for blockhash expiry. Use a paid RPC; public endpoints rate-limit the writes.
    - A failed deploy leaves a funded buffer: list with `solana program show --buffers` and reclaim with `solana program close --buffers`, or resume with the printed seed phrase via `solana-keygen recover -o buffer.json` and `solana program deploy --buffer buffer.json ...`.
    
    ## Mainnet first deploy
    
    ```bash
    anchor deploy -p <name> --provider.cluster mainnet -- --with-compute-unit-price <N>
    solana program show <PROGRAM_ID> -u mainnet-beta
    anchor idl fetch <PROGRAM_ID> --provider.cluster mainnet    # diff against target/idl/<name>.json
    solana-verify verify-from-repo -um --program-id <PROGRAM_ID> <REPO_URL> --commit-hash <SHA> \
      --library-name <lib> --mount-path <program dir> --remote  # accept the verify-PDA upload
    ```
    
    ## Upgrade-authority staging
    
    1. Launch to about 3 months: authority on a hardware-wallet deployer key, so fixes ship fast while bugs surface.
    2. Once stable (about 3 months, or earlier when meaningful value is at stake): move it to the Squads v4 vault PDA (`getVaultPda({ multisigPda, index: 0 })`, the "vault" address in the Squads app). The multisig account itself cannot sign, so authority given to it is lost.
       `solana program set-upgrade-authority <PROGRAM_ID> --new-upgrade-authority <VAULT_PDA> --skip-new-upgrade-authority-signer-check -u mainnet-beta`
       The skip flag is needed because a PDA cannot co-sign; verify the address first, a wrong one is unrecoverable.
    3. After an audit and a long mainnet history: `solana program set-upgrade-authority <PROGRAM_ID> --final`. Irreversible, and it removes every rollback path, so the user runs it (the kit blocks it for Claude).
    
    ## Mainnet upgrade through Squads v4
    
    ```bash
    solana program write-buffer target/deploy/<lib>.so -u mainnet-beta --with-compute-unit-price <N> --use-rpc
    solana program set-buffer-authority <BUFFER> --new-buffer-authority <VAULT_PDA> -u mainnet-beta
    solana-verify get-buffer-hash -um <BUFFER>                  # must equal the executable hash; reviewers check it
    solana program extend <PROGRAM_ID> <BYTES> -u mainnet-beta  # only if the .so outgrew the current Data Length
    ```
    
    `write-buffer` needs the buffer authority to sign each write, so write with the deployer key and hand the buffer to the vault afterwards. `extend` is permissionless, so the deployer key can pay for it. Then create the upgrade proposal in the Squads app's program manager (buffer plus a spill address for the refund), collect approvals, and execute. Afterwards:
    
    - `solana-verify get-program-hash -um <PROGRAM_ID>` equals the executable hash.
    - Refresh verification through the multisig: `solana-verify export-pda-tx <REPO_URL> --program-id <PROGRAM_ID> --uploader <VAULT_PDA> --encoding base58 --compute-unit-price 0`, import it into the Squads transaction builder, execute, then `solana-verify remote submit-job --program-id <PROGRAM_ID> --uploader <VAULT_PDA>`.
    
    Squads SDK details (vault PDA, proposals): [squads skill](ext/sendai/skills/squads/SKILL.md) (install first: `bash .claude/bin/skills.sh add sendai`).
    
    ## Rollback
    
    - Before every upgrade: `solana program dump <PROGRAM_ID> backup-<version>.so -u mainnet-beta`, and keep each release's verified `.so` and hash.
    - Rolling back is another upgrade to the previous binary through the same buffer and multisig flow (devnet: `anchor upgrade <old>.so --program-id <PROGRAM_ID> --provider.cluster devnet`).
    - The previous binary must still read current account layouts. Ship layout changes additively (version field, `realloc`) so rollback stays possible; strategies in [program-upgrade-guide.md](ext/solana-new/skills/launch/deploy-to-mainnet/references/program-upgrade-guide.md) (install first: `bash .claude/bin/skills.sh add solana-new`).
    - An emergency pause exists only if every instruction already checks a pause flag; design it in before launch. A `--final` program cannot be rolled back.
    
    ## CI jobs
    
    The workflow file comes from `/setup-ci-cd`; it needs these jobs:
    
    - build: pinned Anchor (avm) and Agave versions, `anchor build` then `solana-verify build`, publish the `.so`, IDL and executable hash as artifacts.
    - test: `cargo test` / `anchor test` (LiteSVM, Surfpool), `cargo clippy -- -D warnings`, `cargo audit`.
    - deploy-devnet: on the integration branch, with a devnet-only key from CI secrets.
    - mainnet-buffer: write the buffer and move its authority to the Squads vault. CI never holds the mainnet upgrade authority.
    - verify: `solana-verify verify-from-repo --remote` against the release commit after the multisig executes.
    
  • skill-registry.json 51.4 KB
    {
      "version": "1.1",
      "updated": "2026-09-30",
      "tiers": {
        "core": "Pinned by the kit as a git submodule under .claude/skills/ext/ and installed by default.",
        "extension": "Pinned by the kit the same way and installed on demand: bash .claude/bin/skills.sh add <id>. An entry with a commit is not a submodule: skills.sh fetches the skills it lists from its source at that commit into .claude/skills/<name>/.",
        "add-on": "Entries without a tier are opt-in tools the kit does not pin. Install one only when the user asks."
      },
      "entries": [
        {
          "id": "solana-dev",
          "name": "Solana Dev Skill",
          "type": "skill",
          "tier": "core",
          "domain": "solana-core",
          "path": ".claude/skills/ext/solana-dev",
          "description": "Solana Foundation development skill: Anchor 1.x and Pinocchio programs, @solana/kit clients, LiteSVM, Mollusk and Surfpool testing, security, Token-2022, payments. The hub's entry point for general Solana work; most agents and commands read it.",
          "triggers": ["Solana programs", "Anchor", "Pinocchio", "@solana/kit", "program tests", "security review"],
          "source": "https://github.com/solana-foundation/solana-dev-skill",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add solana-dev", "env": [] },
          "license": "MIT",
          "maintainer": "solana-foundation",
          "signal": { "stars": 559, "last_commit": "2026-09-21", "reputability": "official" },
          "default_installed": true,
          "safety": "clean",
          "tags": ["solana", "anchor", "pinocchio", "kit", "testing", "security", "official"]
        },
        {
          "id": "safe-solana-builder",
          "name": "Safe Solana Builder",
          "type": "skill",
          "tier": "core",
          "domain": "security",
          "path": ".claude/skills/ext/safe-solana-builder",
          "description": "Security-first program scaffolding for Anchor, native and Pinocchio with 70+ audit-derived rules. Read by the Anchor and Pinocchio agents and by /audit-solana.",
          "triggers": ["new program", "security-first scaffolding", "audit-derived rules"],
          "source": "https://github.com/Frankcastleauditor/safe-solana-builder",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add safe-solana-builder", "env": [] },
          "license": "MIT (stated in README; no LICENSE file)",
          "maintainer": "Frankcastleauditor",
          "signal": { "stars": 142, "last_commit": "2026-04-20", "reputability": "individual" },
          "default_installed": true,
          "safety": "clean; single maintainer with no commits since 2026-04, so recheck the core tier if it stays inactive",
          "tags": ["security", "anchor", "pinocchio", "native", "scaffolding"]
        },
        {
          "id": "trailofbits",
          "name": "Trail of Bits Skills",
          "type": "skill",
          "tier": "extension",
          "domain": "security",
          "path": ".claude/skills/ext/trailofbits",
          "description": "Trail of Bits security skills. The Solana-relevant ones live in plugins/building-secure-contracts: solana-vulnerability-scanner, audit-prep-assistant, code-maturity-assessor, token-integration-analyzer, guidelines-advisor. The other ~80 cover general security research.",
          "triggers": ["security audit", "vulnerability scan", "audit prep", "code maturity", "token integration review"],
          "source": "https://github.com/trailofbits/skills",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add trailofbits", "env": [] },
          "license": "CC-BY-SA-4.0",
          "maintainer": "trailofbits",
          "signal": { "stars": 7236, "last_commit": "2026-09-24", "reputability": "official" },
          "default_installed": false,
          "safety": "clean; 85 SKILL.md files, the largest skill list of any pack, so it is installed for audits only",
          "tags": ["security", "audit", "vulnerability-scanning", "official"]
        },
        {
          "id": "ghostsecurity",
          "name": "Ghost Security Skills",
          "type": "skill",
          "tier": "extension",
          "domain": "security",
          "path": ".claude/skills/ext/ghostsecurity",
          "description": "Ghost Security AppSec skills: scan-code with per-stack criteria, scan-deps, scan-secrets, repo-context, validate, report. Used by /audit-infra.",
          "triggers": ["AppSec", "SAST", "dependency scan", "secret scan", "infrastructure audit"],
          "source": "https://github.com/ghostsecurity/skills",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add ghostsecurity", "env": [] },
          "license": "Apache-2.0",
          "maintainer": "ghostsecurity",
          "signal": { "stars": 408, "last_commit": "2026-09-23", "reputability": "official" },
          "default_installed": false,
          "safety": "caution: its proxy, scan-deps and scan-secrets skills include unpinned curl | bash installers; run them only with the user's consent",
          "tags": ["security", "appsec", "sast", "sca", "secrets"]
        },
        {
          "id": "defending-code",
          "name": "Anthropic Defending Code",
          "type": "skill",
          "tier": "extension",
          "domain": "security",
          "path": ".claude/skills/ext/defending-code",
          "description": "Anthropic's defending-code reference harness: threat-model, vuln-scan, triage, patch and verify skills (under the repo's .claude/skills/) plus methodology docs. Used by /audit-infra.",
          "triggers": ["threat model", "vulnerability triage", "security patching"],
          "source": "https://github.com/anthropics/defending-code-reference-harness",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add defending-code", "env": [] },
          "license": "Apache-2.0",
          "maintainer": "anthropics",
          "signal": { "stars": 7523, "last_commit": "2026-08-06", "reputability": "official" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["security", "threat-modeling", "triage", "official"]
        },
        {
          "id": "qedgen",
          "name": "QEDGen Solana Skills",
          "type": "skill",
          "tier": "extension",
          "domain": "security",
          "path": ".claude/skills/ext/qedgen",
          "description": "Formal verification for Solana programs: Lean 4 proofs of program invariants.",
          "triggers": ["formal verification", "Lean 4", "invariant proofs"],
          "source": "https://github.com/QEDGen/solana-skills",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add qedgen", "env": ["MISTRAL_API_KEY"] },
          "license": "MIT",
          "maintainer": "QEDGen",
          "signal": { "stars": 68, "last_commit": "2026-09-25", "reputability": "org" },
          "default_installed": false,
          "safety": "clean; needs the qedgen CLI and MISTRAL_API_KEY, and is the largest pack on disk (about 11 MB)",
          "tags": ["formal-verification", "lean4", "security"]
        },
        {
          "id": "sendai",
          "name": "SendAI Skills",
          "type": "skill",
          "tier": "extension",
          "domain": "solana-defi",
          "path": ".claude/skills/ext/sendai",
          "description": "SendAI's protocol skills: Raydium, Orca, Meteora, Kamino, marginfi, Sanctum, Pyth, Switchboard, Squads, pump.fun, deBridge, LI.FI, Light Protocol and more, plus the web3.js to Kit migration skills. Its jupiter, metaplex, helius and magicblock folders are older than the official packs.",
          "triggers": ["DeFi protocols", "Raydium", "Orca", "Meteora", "Kamino", "marginfi", "Sanctum", "Pyth", "Switchboard", "Squads", "pump.fun", "bridging", "web3.js to Kit migration"],
          "source": "https://github.com/sendaifun/skills",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add sendai", "env": [] },
          "license": "Apache-2.0",
          "maintainer": "sendaifun",
          "signal": { "stars": 128, "last_commit": "2026-07-31", "reputability": "org" },
          "default_installed": false,
          "safety": "clean; community skills, so prefer a protocol's official pack where one exists",
          "tags": ["solana", "defi", "protocols", "oracles", "bridges"]
        },
        {
          "id": "jupiter",
          "name": "Jupiter Agent Skills",
          "type": "skill",
          "tier": "extension",
          "domain": "solana-defi",
          "path": ".claude/skills/ext/jupiter",
          "description": "Jupiter's official skills: integrating-jupiter (swap, lend, perps, trigger, recurring), jupiter-lend, jupiter-swap-migration, jupiter-vrfd.",
          "triggers": ["Jupiter", "token swaps", "Jupiter Lend", "perps", "trigger orders", "recurring orders"],
          "source": "https://github.com/jup-ag/agent-skills",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add jupiter", "env": [] },
          "license": "MIT",
          "maintainer": "jup-ag",
          "signal": { "stars": 84, "last_commit": "2026-07-07", "reputability": "official" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["solana", "defi", "jupiter", "swap", "official"]
        },
        {
          "id": "metaplex",
          "name": "Metaplex Skill",
          "type": "skill",
          "tier": "extension",
          "domain": "solana-nft",
          "path": ".claude/skills/ext/metaplex",
          "description": "Metaplex's official skill: Core, Token Metadata, Bubblegum compressed NFTs, Candy Machine, Genesis launches, Umi.",
          "triggers": ["NFTs", "Metaplex Core", "Token Metadata", "Bubblegum", "Candy Machine", "Umi"],
          "source": "https://github.com/metaplex-foundation/skill",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add metaplex", "env": [] },
          "license": "Apache-2.0 (stated in README; no LICENSE file)",
          "maintainer": "metaplex-foundation",
          "signal": { "stars": 21, "last_commit": "2026-07-21", "reputability": "official" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["solana", "nft", "metaplex", "cnft", "official"]
        },
        {
          "id": "magicblock",
          "name": "MagicBlock Dev Skill",
          "type": "skill",
          "tier": "extension",
          "domain": "solana-infra",
          "path": ".claude/skills/ext/magicblock",
          "description": "MagicBlock's official skill: Ephemeral Rollups with delegated state, ER and PER architecture and settlement, private payments, session keys, VRF, cranks. Replaces the sendai magicblock folder, which pins ephemeral-rollups-sdk 0.6.5 (this pack covers 0.16.2).",
          "triggers": ["MagicBlock", "Ephemeral Rollups", "delegated state", "real-time games", "on-chain randomness"],
          "source": "https://github.com/magicblock-labs/magicblock-dev-skill",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add magicblock", "env": [] },
          "license": "MIT",
          "maintainer": "magicblock-labs",
          "signal": { "stars": 9, "last_commit": "2026-09-24", "reputability": "official" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["solana", "ephemeral-rollups", "gaming", "real-time", "official"]
        },
        {
          "id": "helius",
          "name": "Helius Core AI",
          "type": "skill",
          "tier": "extension",
          "domain": "solana-infra",
          "path": ".claude/skills/ext/helius",
          "description": "Helius's official skills: RPC, DAS, webhooks, WebSockets, Laserstream, Sender, priority fees, SVM internals and partner integrations. The kit's Helius MCP server answers doc questions without it.",
          "triggers": ["Helius", "DAS", "webhooks", "Laserstream", "Sender", "priority fees", "SVM internals"],
          "source": "https://github.com/helius-labs/core-ai",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add helius", "env": [] },
          "license": "MIT",
          "maintainer": "helius-labs",
          "signal": { "stars": 28, "last_commit": "2026-08-31", "reputability": "official" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["solana", "rpc", "das", "webhooks", "official"]
        },
        {
          "id": "alchemy",
          "name": "Alchemy Skills",
          "type": "skill",
          "tier": "extension",
          "domain": "solana-infra",
          "path": ".claude/skills/ext/alchemy",
          "description": "Alchemy's official skills: the Alchemy API, CLI and MCP server, with Solana RPC, DAS, Yellowstone gRPC and WebSocket references, plus a keyless x402 gateway for app code.",
          "triggers": ["Alchemy APIs", "Yellowstone gRPC", "x402 gateway"],
          "source": "https://github.com/alchemyplatform/skills",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add alchemy", "env": ["ALCHEMY_API_KEY"] },
          "license": "MIT",
          "maintainer": "alchemyplatform",
          "signal": { "stars": 49, "last_commit": "2026-08-26", "reputability": "official" },
          "default_installed": false,
          "safety": "clean; each skill ships twice (skills/ and plugins/alchemy/skills/)",
          "tags": ["rpc", "das", "grpc", "multi-chain", "official"]
        },
        {
          "id": "quicknode-anchor",
          "name": "QuickNode Solana Finance Skill",
          "type": "skill",
          "tier": "extension",
          "domain": "solana-core",
          "path": ".claude/skills/ext/quicknode-anchor",
          "description": "QuickNode's Solana references: financial math and fixed-point arithmetic (RUST.md), Anchor patterns, Quasar zero-copy. The hub reads the reference files, not the SKILL.md workflow layer.",
          "triggers": ["financial math", "fixed-point arithmetic", "Quasar zero-copy"],
          "source": "https://github.com/quicknode/solana-finance-claude-plugin",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add quicknode-anchor", "env": [] },
          "license": "MIT",
          "maintainer": "quicknode",
          "signal": { "stars": 91, "last_commit": "2026-09-25", "reputability": "official" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["solana", "anchor", "math", "quasar"]
        },
        {
          "id": "eth-to-sol",
          "name": "ETH to SOL",
          "type": "skill",
          "tier": "extension",
          "domain": "solana-core",
          "path": ".claude/skills/ext/eth-to-sol",
          "description": "Solana Foundation's EVM porting skill: type, pattern and stdlib mappings, the mental model, and security and optimization notes for translating Solidity contracts.",
          "triggers": ["Solidity", "EVM", "port from Ethereum"],
          "source": "https://github.com/solana-foundation/eth-to-sol-skill",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add eth-to-sol", "env": [] },
          "license": "none/unspecified",
          "maintainer": "solana-foundation",
          "signal": { "stars": 2, "last_commit": "2026-06-19", "reputability": "official" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["solana", "evm", "solidity", "porting", "official"]
        },
        {
          "id": "solana-game",
          "name": "Solana Game Skill",
          "type": "skill",
          "tier": "extension",
          "domain": "gaming",
          "path": ".claude/skills/ext/solana-game",
          "description": "Superteam Brazil's game skill: Solana.Unity-SDK, C# patterns, game architecture, PlaySolana (PSG1, PlayDex, PlayID), mobile game patterns. Read by the game-architect and unity-engineer agents.",
          "triggers": ["Unity", "C#", "games", "PlaySolana", "PSG1"],
          "source": "https://github.com/solanabr/solana-game-skill",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add solana-game", "env": [] },
          "license": "MIT",
          "maintainer": "solanabr",
          "signal": { "stars": 9, "last_commit": "2026-01-30", "reputability": "org" },
          "default_installed": false,
          "safety": "clean; carries an older copy of solana-dev-skill as a nested submodule",
          "tags": ["gaming", "unity", "csharp", "playsolana"]
        },
        {
          "id": "solana-mobile",
          "name": "Solana Mobile Skills",
          "type": "skill",
          "tier": "extension",
          "domain": "mobile",
          "path": ".claude/skills/ext/solana-mobile",
          "description": "Solana Mobile's official skills: React Native and Expo scaffolding, Mobile Wallet Adapter 2.0, Seeker Genesis Token and .skr domains, dApp Store publishing. Read by the mobile-engineer agent.",
          "triggers": ["React Native", "Expo", "Mobile Wallet Adapter", "Seeker", "dApp Store"],
          "source": "https://github.com/solana-mobile/solana-mobile-skills",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add solana-mobile", "env": [] },
          "license": "Apache-2.0",
          "maintainer": "solana-mobile",
          "signal": { "stars": 8, "last_commit": "2026-09-24", "reputability": "official" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["mobile", "react-native", "mwa", "seeker", "official"]
        },
        {
          "id": "cloudflare",
          "name": "Cloudflare Skills",
          "type": "skill",
          "tier": "extension",
          "domain": "infra",
          "path": ".claude/skills/ext/cloudflare",
          "description": "Cloudflare's official skills: Workers best practices, wrangler, Durable Objects, Agents SDK, sandboxes. Read by the devops-engineer agent for Workers code.",
          "triggers": ["Cloudflare Workers", "wrangler", "Durable Objects", "Agents SDK"],
          "source": "https://github.com/cloudflare/skills",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add cloudflare", "env": [] },
          "license": "Apache-2.0",
          "maintainer": "cloudflare",
          "signal": { "stars": 2907, "last_commit": "2026-09-22", "reputability": "official" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["infra", "workers", "edge", "official"]
        },
        {
          "id": "vercel",
          "name": "Vercel Agent Skills",
          "type": "skill",
          "tier": "extension",
          "domain": "frontend-design",
          "path": ".claude/skills/ext/vercel",
          "description": "Vercel's agent skills: React and Next.js performance, composition patterns, web design guidelines, deploying to Vercel.",
          "triggers": ["Vercel", "Next.js", "React performance", "web design review"],
          "source": "https://github.com/vercel-labs/agent-skills",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add vercel", "env": [] },
          "license": "MIT (stated in README and package.json; no LICENSE file)",
          "maintainer": "vercel-labs",
          "signal": { "stars": 31526, "last_commit": "2026-08-28", "reputability": "official" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["frontend", "nextjs", "react", "deploy", "official"]
        },
        {
          "id": "solana-new",
          "name": "solana.new",
          "type": "skill",
          "tier": "extension",
          "domain": "go-to-market",
          "path": ".claude/skills/ext/solana-new",
          "description": "SendAI and Superteam go-to-market references: marketing video, brand and frontend design, tokenomics, DefiLlama research, launch playbooks, and ecosystem catalogs in cli/data/. The kit's idea-sprint, pitch-deck and hackathon skills are telemetry-free adaptations of three of its skills and link its references.",
          "triggers": ["go-to-market", "marketing video", "brand design", "tokenomics", "DefiLlama research", "ecosystem catalogs"],
          "source": "https://github.com/sendaifun/solana-new",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add solana-new", "env": [] },
          "license": "MIT",
          "maintainer": "sendaifun",
          "signal": { "stars": 176, "last_commit": "2026-07-31", "reputability": "org" },
          "default_installed": false,
          "safety": "caution: its 33 SKILL.md files open with telemetry preambles that POST usage events; read them as reference data and don't run the preamble bash blocks",
          "tags": ["go-to-market", "design", "marketing", "research", "telemetry"]
        },
        {
          "id": "colosseum",
          "name": "Colosseum Copilot",
          "type": "skill",
          "tier": "extension",
          "domain": "go-to-market",
          "path": ".claude/skills/ext/colosseum",
          "description": "Colosseum Copilot: startup research, idea validation and competitive landscape from Colosseum's hackathon archives. Read by the solana-researcher and solana-architect agents.",
          "triggers": ["Colosseum", "hackathon archives", "idea validation", "competitive research"],
          "source": "https://github.com/ColosseumOrg/colosseum-copilot",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add colosseum", "env": ["COLOSSEUM_COPILOT_PAT"] },
          "license": "proprietary (README: Copyright Colosseum)",
          "maintainer": "ColosseumOrg",
          "signal": { "stars": 12, "last_commit": "2026-07-13", "reputability": "official" },
          "default_installed": false,
          "safety": "clean; queries Colosseum's API with COLOSSEUM_COPILOT_PAT",
          "tags": ["hackathon", "research", "ideas", "official"]
        },
        {
          "id": "anthropic-skills",
          "name": "Anthropic Skills (Apache-2.0 subset)",
          "type": "skill",
          "tier": "extension",
          "domain": "frontend-design",
          "path": ".claude/skills",
          "commit": "8a1541c4a3ffa5a20a5a91de0dcf3f0bab1d1ef4",
          "skills": ["frontend-design", "webapp-testing", "mcp-builder"],
          "description": "Anthropic's frontend-design (distinctive UI direction), webapp-testing (Playwright tests of a local web app) and mcp-builder (MCP servers for a program or API), installed as top-level skills in .claude/skills/<name>/, which agents load natively (Claude Code, Codex, Grok Build and other Agent Skills clients). skills.sh fetches only these folders at the pinned commit and copies them unchanged, LICENSE.txt included.",
          "triggers": ["UI design direction", "Playwright tests of a local web app", "building an MCP server"],
          "source": "https://github.com/anthropics/skills",
          "install": { "method": "kit", "command": "bash .claude/bin/skills.sh add anthropic-skills", "env": [] },
          "license": "Apache-2.0 (these three); the repo's docx, pdf, pptx and xlsx skills are proprietary and doc-coauthoring has no license, so skills.sh refuses them",
          "maintainer": "anthropics",
          "signal": { "stars": 179151, "last_commit": "2026-09-28", "reputability": "official" },
          "default_installed": false,
          "safety": "caution: webapp-testing's scripts/with_server.py runs the server commands it is given through a shell, and mcp-builder's evaluation script calls the Anthropic API (ANTHROPIC_API_KEY) with unpinned pip requirements; the skills' guidance is agent-neutral",
          "tags": ["frontend", "design", "playwright", "testing", "mcp", "cross-agent", "official"]
        },
        {
          "id": "anthropic-claude-code-plugins",
          "name": "Anthropic Claude Code Plugins",
          "type": "plugin",
          "domain": "dev-workflow",
          "description": "Anthropic-authored Claude Code plugins: code-review, pr-review-toolkit, feature-dev, security-guidance. Complementary to the kit's /diff-review + cso/audit-infra (note the overlap).",
          "source": "https://github.com/anthropics/claude-code",
          "install": { "method": "plugin-marketplace", "command": "/plugin marketplace add anthropics/claude-code", "env": [] },
          "license": "Anthropic-commercial-ToS (not OSI)",
          "maintainer": "anthropics",
          "signal": { "stars": 132567, "last_commit": "2026-06-15", "reputability": "official" },
          "default_installed": false,
          "safety": "clean (Anthropic-authored; security-guidance is itself a safety hook); overlaps the kit's /diff-review + cso/audit-infra",
          "tags": ["code-review", "pr-review", "feature-dev", "security-guidance", "official"]
        },
        {
          "id": "wshobson-agents",
          "name": "wshobson Agents Marketplace",
          "type": "plugin",
          "domain": "dev-workflow",
          "description": "Multi-harness agent/command/skill plugin marketplace for general dev workflows.",
          "source": "https://github.com/wshobson/agents",
          "install": { "method": "plugin-marketplace", "command": "/plugin marketplace add wshobson/agents", "env": [] },
          "license": "MIT",
          "maintainer": "wshobson",
          "signal": { "stars": 36800, "last_commit": "2026-06-15", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["agents", "commands", "workflow", "marketplace"]
        },
        {
          "id": "get-shit-done",
          "name": "Get Shit Done (GSD)",
          "type": "template-repo",
          "domain": "dev-workflow",
          "description": "Spec-driven / meta-prompting workflow system (agents + commands).",
          "source": "https://github.com/gsd-build/get-shit-done",
          "install": { "method": "git-clone", "command": "git clone https://github.com/gsd-build/get-shit-done", "env": [] },
          "license": "MIT",
          "maintainer": "gsd-build",
          "signal": { "stars": 64000, "last_commit": "2026-05-31", "reputability": "org" },
          "default_installed": false,
          "safety": "clean (star count is web-search-inflated; treat as a floor)",
          "tags": ["spec-driven", "meta-prompting", "workflow", "agents", "commands"]
        },
        {
          "id": "get-shit-pretty",
          "name": "Get Shit Pretty (GSP)",
          "type": "template-repo",
          "domain": "frontend-design",
          "description": "Design-engineering system for AI coding agents (the design counterpart to GSD): 45+ skills + 13 sub-agents covering brand strategy, identity, design systems, UI build, accessibility, and critique via a dual-diamond pipeline, with 35 style presets. Not Solana-specific.",
          "source": "https://github.com/jubscodes/get-shit-pretty",
          "install": { "method": "npx", "command": "pnpm dlx get-shit-pretty   # or: bunx get-shit-pretty", "env": ["FIGMA_ACCESS_TOKEN (optional, for the bundled Figma MCP)"] },
          "license": "MIT",
          "maintainer": "jubscodes",
          "signal": { "stars": 43, "last_commit": "2026-06-07", "reputability": "individual" },
          "default_installed": false,
          "safety": "caution: ships auto-running Claude Code hooks (gsp/hooks/hooks.json) + bin/install.js merges hooks+statusline into settings.json — review before installing; otherwise MIT, no telemetry/curl|sh",
          "tags": ["design", "branding", "design-systems", "ui-polish", "frontend", "accessibility", "claude-code", "hooks"]
        },
        {
          "id": "dev-browser",
          "name": "Dev Browser",
          "type": "skill",
          "domain": "testing-qa",
          "description": "Gives the agent a real web browser for frontend QA, testing, and scraping.",
          "source": "https://github.com/SawyerHood/dev-browser",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/SawyerHood/dev-browser .claude/skills/ext/dev-browser", "env": [] },
          "license": "MIT",
          "maintainer": "SawyerHood",
          "signal": { "stars": 6300, "last_commit": "2026-06-05", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["browser", "testing", "qa", "frontend"]
        },
        {
          "id": "ios-simulator-skill",
          "name": "iOS Simulator Skill",
          "type": "skill",
          "domain": "testing-qa",
          "description": "xcodebuild wrapper to drive the iOS Simulator; pairs with the kit's build-mobile.",
          "source": "https://github.com/conorluddy/ios-simulator-skill",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/conorluddy/ios-simulator-skill .claude/skills/ext/ios-simulator", "env": [] },
          "license": "MIT",
          "maintainer": "conorluddy",
          "signal": { "stars": 1100, "last_commit": "2026-06-14", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["ios", "simulator", "xcode", "mobile", "testing"]
        },
        {
          "id": "frontend-slides",
          "name": "Frontend Slides",
          "type": "skill",
          "domain": "frontend-design",
          "description": "Build animation-rich HTML slide decks (synergy with the kit's pitch-deck).",
          "source": "https://github.com/zarazhangrui/frontend-slides",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/zarazhangrui/frontend-slides .claude/skills/ext/frontend-slides", "env": [] },
          "license": "MIT",
          "maintainer": "zarazhangrui",
          "signal": { "stars": 21785, "last_commit": "2026-06-13", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["slides", "presentation", "html", "animation", "frontend"]
        },
        {
          "id": "anydesign",
          "name": "AnyDesign",
          "type": "skill",
          "domain": "frontend-design",
          "description": "Turn an image / URL / Figma reference into design.md design tokens; closest genre-mate to animation-principles.",
          "source": "https://github.com/uxKero/anydesign",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/uxKero/anydesign .claude/skills/ext/anydesign", "env": [] },
          "license": "MIT",
          "maintainer": "uxKero",
          "signal": { "stars": 109, "last_commit": "2026-06-11", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["design-tokens", "figma", "ui", "frontend"]
        },
        {
          "id": "webgpu-claude-skill",
          "name": "WebGPU Claude Skill",
          "type": "skill",
          "domain": "frontend-design",
          "description": "WebGPU + Three.js graphics skill for the browser.",
          "source": "https://github.com/dgreenheck/webgpu-claude-skill",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/dgreenheck/webgpu-claude-skill .claude/skills/ext/webgpu", "env": [] },
          "license": "none/unspecified",
          "maintainer": "dgreenheck",
          "signal": { "stars": 1000, "last_commit": "2026-04-10", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean (no license — do not vendor/redistribute until clarified)",
          "tags": ["webgpu", "three.js", "graphics", "frontend"]
        },
        {
          "id": "swiftui-design-skill",
          "name": "SwiftUI Design Skill",
          "type": "skill",
          "domain": "frontend-design",
          "description": "Anti-AI-slop SwiftUI design rules for Apple/mobile builders.",
          "source": "https://github.com/Wholiver/swiftui-design-skill",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/Wholiver/swiftui-design-skill .claude/skills/ext/swiftui-design", "env": [] },
          "license": "MIT",
          "maintainer": "Wholiver",
          "signal": { "stars": 138, "last_commit": "2026-05-01", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["swiftui", "design", "apple", "mobile", "ios"]
        },
        {
          "id": "animation-principles",
          "name": "Animation Principles",
          "type": "skill",
          "domain": "frontend-design",
          "description": "Genre-template skill for motion / animation design principles (pure prose).",
          "source": "https://github.com/dylantarre/animation-principles",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/dylantarre/animation-principles .claude/skills/ext/animation-principles", "env": [] },
          "license": "MIT",
          "maintainer": "dylantarre",
          "signal": { "stars": 47, "last_commit": "2025-12-30", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean — pure-prose, zero scripts/installers; stale (~Dec 2025), unmaintained",
          "tags": ["animation", "motion", "ui", "frontend"]
        },
        {
          "id": "emilkowalski-skill",
          "name": "Emil Kowalski Motion Skill",
          "type": "skill",
          "domain": "frontend-design",
          "description": "Motion / interaction design skill from a renowned motion author (Sonner, Vaul).",
          "source": "https://github.com/emilkowalski/skill",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/emilkowalski/skill .claude/skills/ext/emilkowalski-skill", "env": [] },
          "license": "none/unspecified",
          "maintainer": "emilkowalski",
          "signal": { "stars": 2400, "last_commit": "2026-03-25", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean (no license — do not vendor/redistribute until clarified); stale (~Mar 2026)",
          "tags": ["motion", "animation", "interaction", "frontend"]
        },
        {
          "id": "brand-design-md",
          "name": "Brand Design (md)",
          "type": "skill",
          "domain": "frontend-design",
          "description": "Brand-design reference in markdown.",
          "source": "https://github.com/zephyrwang6/brand-design-md",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/zephyrwang6/brand-design-md .claude/skills/ext/brand-design-md", "env": [] },
          "license": "none/unspecified",
          "maintainer": "zephyrwang6",
          "signal": { "stars": 88, "last_commit": "2026-04-10", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean (no license — do not vendor/redistribute until clarified); overlaps solana-new brand-design",
          "tags": ["branding", "design", "frontend"]
        },
        {
          "id": "ux-writing-skill",
          "name": "UX Writing Skill",
          "type": "skill",
          "domain": "ux-writing",
          "description": "Systematic UX microcopy: onboarding, error, empty-state and button copy with quality standards.",
          "source": "https://github.com/content-designer/ux-writing-skill",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/content-designer/ux-writing-skill .claude/skills/ext/ux-writing", "env": [] },
          "license": "MIT",
          "maintainer": "content-designer",
          "signal": { "stars": 112, "last_commit": "2026-05-26", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean (one build-skill.sh builder, not runtime)",
          "tags": ["ux-writing", "microcopy", "content-design", "onboarding"]
        },
        {
          "id": "design-skills",
          "name": "Design Skills (UX process)",
          "type": "skill",
          "domain": "ux-writing",
          "description": "UX-process breadth: 10 skills incl. ux-research, design-critique, journey-mapping, a11y-audit.",
          "source": "https://github.com/cuellarfr/design-skills",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/cuellarfr/design-skills .claude/skills/ext/design-skills", "env": [] },
          "license": "MIT",
          "maintainer": "cuellarfr",
          "signal": { "stars": 31, "last_commit": "2026-05-04", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["ux-research", "design-critique", "journey-mapping", "accessibility", "ux"]
        },
        {
          "id": "scientific-agent-skills",
          "name": "Scientific Agent Skills",
          "type": "skill",
          "domain": "data",
          "description": "140 science skills + 100 database connectors; best-in-class for data-heavy builders.",
          "source": "https://github.com/K-Dense-AI/scientific-agent-skills",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/K-Dense-AI/scientific-agent-skills .claude/skills/ext/scientific-agent-skills", "env": [] },
          "license": "MIT",
          "maintainer": "K-Dense-AI",
          "signal": { "stars": 28300, "last_commit": "2026-06-15", "reputability": "org" },
          "default_installed": false,
          "safety": "clean",
          "tags": ["science", "data", "database-connectors", "research"]
        },
        {
          "id": "claude-d3js-skill",
          "name": "Claude D3.js Skill",
          "type": "skill",
          "domain": "data",
          "description": "D3 data-visualization skill for dashboards.",
          "source": "https://github.com/chrisvoncsefalvay/claude-d3js-skill",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/chrisvoncsefalvay/claude-d3js-skill .claude/skills/ext/d3js", "env": [] },
          "license": "none/unspecified",
          "maintainer": "chrisvoncsefalvay",
          "signal": { "stars": 192, "last_commit": "2025-10-18", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean (no license — do not vendor/redistribute until clarified); stale (~Oct 2025)",
          "tags": ["d3", "data-viz", "dashboards", "data"]
        },
        {
          "id": "claude-skills-marketplace",
          "name": "Claude Skills Marketplace (mhattingpete)",
          "type": "plugin",
          "domain": "dev-workflow",
          "description": "Plugin marketplace: git + test + code-review pack.",
          "source": "https://github.com/mhattingpete/claude-skills-marketplace",
          "install": { "method": "plugin-marketplace", "command": "/plugin marketplace add mhattingpete/claude-skills-marketplace", "env": [] },
          "license": "Apache-2.0",
          "maintainer": "mhattingpete",
          "signal": { "stars": 607, "last_commit": "2026-03-06", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean; borderline stale (~Mar 2026)",
          "tags": ["git", "testing", "code-review", "marketplace", "workflow"]
        },
        {
          "id": "playwright-skill",
          "name": "Playwright Skill",
          "type": "skill",
          "domain": "testing-qa",
          "description": "De-facto Playwright skill for browser automation and webapp testing.",
          "source": "https://github.com/lackeyjb/playwright-skill",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/lackeyjb/playwright-skill .claude/skills/ext/playwright", "env": [] },
          "license": "MIT",
          "maintainer": "lackeyjb",
          "signal": { "stars": 2800, "last_commit": "2025-12-19", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean; stale (~Dec 2025)",
          "tags": ["playwright", "browser", "testing", "qa", "e2e"]
        },
        {
          "id": "vercel-plugin",
          "name": "Vercel Plugin",
          "type": "plugin",
          "domain": "frontend-design",
          "description": "Full Vercel plugin: 28 skills + 3 agents + official read-only Vercel MCP (Next.js/React/AI-SDK frontend bundle).",
          "source": "https://github.com/vercel/vercel-plugin",
          "install": { "method": "plugin-marketplace", "command": "/plugin marketplace add vercel/vercel-plugin", "env": ["VERCEL_PLUGIN_TELEMETRY=off (opt-out of default telemetry)"] },
          "license": "Apache-2.0",
          "maintainer": "vercel",
          "signal": { "stars": 190, "last_commit": "2026-06-15", "reputability": "org" },
          "default_installed": false,
          "safety": "caution: telemetry ON by default (anonymized DAU pings, no content); opt-out VERCEL_PLUGIN_TELEMETRY=off",
          "tags": ["vercel", "nextjs", "react", "ai-sdk", "frontend", "deployment"]
        },
        {
          "id": "meteora-sdk-skill",
          "name": "Meteora SDK Skill",
          "type": "skill",
          "domain": "solana-defi",
          "description": "Meteora DLMM SDK-depth skill (net-new vs solana-new; sendai already ships a meteora skill — add only for SDK-level depth).",
          "source": "https://github.com/MeteoraAg/meteora-sdk-skill",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/MeteoraAg/meteora-sdk-skill .claude/skills/ext/meteora-sdk", "env": [] },
          "license": "unspecified",
          "maintainer": "MeteoraAg",
          "signal": { "stars": null, "last_commit": "2026-06", "reputability": "org" },
          "default_installed": false,
          "safety": "clean; overlaps the bundled sendai meteora skill — confirm SDK-depth delta before adding",
          "tags": ["meteora", "dlmm", "defi", "sdk", "solana"]
        },
        {
          "id": "x402-proxy-mcp",
          "name": "x402 Proxy MCP",
          "type": "mcp",
          "domain": "solana-infra",
          "description": "Agent-payments proxy MCP (x402). Net-new vs solana-new (its x402-mcp is a different git-clone impl).",
          "source": "https://www.npmjs.com/package/x402-proxy",
          "install": { "method": "npx", "command": "claude mcp add x402-proxy -- npx -y x402-proxy", "env": [] },
          "license": "unspecified",
          "maintainer": "x402",
          "signal": { "stars": null, "last_commit": null, "reputability": "emerging — verify before install" },
          "default_installed": false,
          "safety": "caution: BIP-39 key custody for agent payments — isolate keys, explicit opt-in only, never a default",
          "tags": ["x402", "payments", "mcp", "key-custody", "solana"]
        },
        {
          "id": "pyth-pro-mcp",
          "name": "Pyth Pro MCP",
          "type": "mcp",
          "domain": "solana-infra",
          "description": "Pyth Pro price-feed MCP: 500+ feeds, low latency. Net-new vs solana-new (Pyth appears only as a dependency keyword there).",
          "source": "https://www.npmjs.com/package/@pythnetwork/pyth-mcp",
          "install": { "method": "npx", "command": "claude mcp add pyth-pro -- npx -y @pythnetwork/pyth-mcp", "env": ["PYTH_API_KEY"] },
          "license": "unspecified",
          "maintainer": "pyth-network",
          "signal": { "stars": null, "last_commit": null, "reputability": "org" },
          "default_installed": false,
          "safety": "caution: paid API key (billable); no custody risk",
          "tags": ["pyth", "oracle", "price-feeds", "mcp", "solana"]
        },
        {
          "id": "chainstack-mcp",
          "name": "Chainstack MCP",
          "type": "mcp",
          "domain": "solana-infra",
          "description": "Hosted unified multi-chain RPC MCP. Net-new vs solana-new.",
          "source": "https://mcp.chainstack.com/mcp",
          "install": { "method": "npx", "command": "claude mcp add --transport http chainstack https://mcp.chainstack.com/mcp", "env": [] },
          "license": "unspecified",
          "maintainer": "chainstack",
          "signal": { "stars": null, "last_commit": null, "reputability": "org" },
          "default_installed": false,
          "safety": "caution: hosted multi-chain RPC — check data-retention policy",
          "tags": ["rpc", "multi-chain", "mcp", "hosted", "solana"]
        },
        {
          "id": "noesis-mcp",
          "name": "Noesis MCP",
          "type": "mcp",
          "domain": "solana-infra",
          "description": "Hosted token-intelligence MCP. Net-new vs solana-new.",
          "source": "https://noesisapi.dev/mcp",
          "install": { "method": "npx", "command": "claude mcp add --transport http noesis https://noesisapi.dev/mcp", "env": [] },
          "license": "unspecified",
          "maintainer": "noesis",
          "signal": { "stars": null, "last_commit": null, "reputability": "emerging — verify before install" },
          "default_installed": false,
          "safety": "caution: hosted token-intel — verify provenance/traction before trusting",
          "tags": ["token-intel", "mcp", "hosted", "solana"]
        },
        {
          "id": "dexpaprika-mcp",
          "name": "DexPaprika MCP",
          "type": "mcp",
          "domain": "solana-infra",
          "description": "Free, no-key DEX market-data MCP. Net-new vs solana-new (its DEX-data MCP is a different provider).",
          "source": "https://www.npmjs.com/package/dexpaprika-mcp",
          "install": { "method": "npx", "command": "claude mcp add dexpaprika -- npx -y dexpaprika-mcp", "env": [] },
          "license": "unspecified",
          "maintainer": "dexpaprika",
          "signal": { "stars": null, "last_commit": null, "reputability": "org" },
          "default_installed": false,
          "safety": "clean; free no-key DEX market data, low-risk read-only",
          "tags": ["dex", "market-data", "mcp", "solana"]
        },
        {
          "id": "phantom-mcp",
          "name": "Phantom MCP",
          "type": "mcp",
          "domain": "solana-infra",
          "description": "Phantom wallet MCP — can sign/submit transactions. Also cataloged in solana-new (phantom-mcp-server); kept here because the signing-custody warning is load-bearing.",
          "source": "https://www.npmjs.com/package/@phantom/mcp-server",
          "install": { "method": "npx", "command": "claude mcp add phantom -- npx -y @phantom/mcp-server", "env": [] },
          "license": "unspecified",
          "maintainer": "phantom",
          "signal": { "stars": null, "last_commit": null, "reputability": "org" },
          "default_installed": false,
          "safety": "caution: wallet signing — can sign/submit transactions; explicit user consent only, never a default (key-custody risk)",
          "tags": ["phantom", "wallet", "signing", "mcp", "solana"]
        },
        {
          "id": "gmem",
          "name": "gmem",
          "type": "skill",
          "domain": "solana-infra",
          "description": "Agent memory layer (watchlist — young/unverified).",
          "source": "https://github.com/yksanjo/gmem",
          "install": null,
          "license": "unverified",
          "maintainer": "yksanjo",
          "signal": { "stars": null, "last_commit": null, "reputability": "emerging — verify before install" },
          "default_installed": false,
          "safety": "caution: unverified — confirm maintenance + license before any use",
          "tags": ["memory", "agent", "watchlist", "solana"]
        },
        {
          "id": "snap-protocol",
          "name": "Snap Protocol",
          "type": "skill",
          "domain": "solana-infra",
          "description": "Snapshot/state protocol skill (watchlist — young/unverified).",
          "source": "https://github.com/agentzeny/snap-public",
          "install": null,
          "license": "unverified",
          "maintainer": "agentzeny",
          "signal": { "stars": null, "last_commit": null, "reputability": "emerging — verify before install" },
          "default_installed": false,
          "safety": "caution: early — verify reachability + traction before any use",
          "tags": ["snapshot", "state", "protocol", "watchlist", "solana"]
        },
        {
          "id": "seeker-skills",
          "name": "Seeker Skills",
          "type": "skill",
          "domain": "solana-infra",
          "description": "Solana Seeker (mobile) skills (watchlist — young/unverified). Cross-check vs ext/solana-mobile coverage.",
          "source": "https://github.com/Sarthib7/seeker-skills",
          "install": { "method": "submodule", "command": "git submodule add https://github.com/Sarthib7/seeker-skills .claude/skills/ext/seeker-skills", "env": [] },
          "license": "unverified",
          "maintainer": "Sarthib7",
          "signal": { "stars": null, "last_commit": null, "reputability": "emerging — verify before install" },
          "default_installed": false,
          "safety": "caution: niche mobile, unverified — cross-check vs ext/solana-mobile before adding",
          "tags": ["seeker", "mobile", "watchlist", "solana"]
        },
        {
          "id": "sati",
          "name": "SATI (SAID/SATI/AIP)",
          "type": "skill",
          "domain": "identity",
          "description": "Agent-identity standards (SAID/SATI/AIP). Not a skill yet — emerging standard (watchlist). Net-new vs solana-new.",
          "source": "https://github.com/cascade-protocol/sati",
          "install": null,
          "license": "unverified",
          "maintainer": "cascade-protocol",
          "signal": { "stars": null, "last_commit": null, "reputability": "emerging — verify before install" },
          "default_installed": false,
          "safety": "caution: emerging standard, not a skill yet — monitor for adoption",
          "tags": ["agent-identity", "standard", "watchlist", "solana"]
        },
        {
          "id": "composio-awesome-claude-skills",
          "name": "Composio Awesome Claude Skills",
          "type": "aggregator",
          "domain": "dev-workflow",
          "description": "Scout source: best current skills-specific aggregator (1000+, domain-grouped). Not installable.",
          "source": "https://github.com/ComposioHQ/awesome-claude-skills",
          "install": null,
          "license": "unspecified",
          "maintainer": "ComposioHQ",
          "signal": { "stars": 64700, "last_commit": "2026-05-22", "reputability": "org" },
          "default_installed": false,
          "safety": "clean — discovery source only, nothing executed",
          "tags": ["aggregator", "scout", "skills", "discovery"]
        },
        {
          "id": "travisvn-awesome-claude-skills",
          "name": "travisvn Awesome Claude Skills",
          "type": "aggregator",
          "domain": "dev-workflow",
          "description": "Scout source: tight, high-signal, well-maintained skills list. Not installable.",
          "source": "https://github.com/travisvn/awesome-claude-skills",
          "install": null,
          "license": "unspecified",
          "maintainer": "travisvn",
          "signal": { "stars": 13500, "last_commit": "2026-04-28", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean — discovery source only, nothing executed",
          "tags": ["aggregator", "scout", "skills", "discovery"]
        },
        {
          "id": "buildwithclaude",
          "name": "Build With Claude",
          "type": "aggregator",
          "domain": "dev-workflow",
          "description": "Scout source: live searchable hub (buildwithclaude.com); best for plugins/marketplaces. Not installable.",
          "source": "https://github.com/davepoon/buildwithclaude",
          "install": null,
          "license": "unspecified",
          "maintainer": "davepoon",
          "signal": { "stars": 3100, "last_commit": "2026-06-15", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean — discovery source only, nothing executed",
          "tags": ["aggregator", "scout", "plugins", "marketplaces", "discovery"]
        },
        {
          "id": "hesreallyhim-awesome-claude-code",
          "name": "Awesome Claude Code",
          "type": "aggregator",
          "domain": "dev-workflow",
          "description": "Scout source: canonical Claude Code list (README mid-reorg). Not installable.",
          "source": "https://github.com/hesreallyhim/awesome-claude-code",
          "install": null,
          "license": "unspecified",
          "maintainer": "hesreallyhim",
          "signal": { "stars": 46500, "last_commit": "2026-04-27", "reputability": "individual" },
          "default_installed": false,
          "safety": "clean — discovery source only, nothing executed",
          "tags": ["aggregator", "scout", "claude-code", "discovery"]
        },
        {
          "id": "voltagent-awesome-claude-code-subagents",
          "name": "VoltAgent Awesome Claude Code Subagents",
          "type": "aggregator",
          "domain": "dev-workflow",
          "description": "Scout source: 100+ subagents by domain (agents, not skills). Not installable.",
          "source": "https://github.com/VoltAgent/awesome-claude-code-subagents",
          "install": null,
          "license": "unspecified",
          "maintainer": "VoltAgent",
          "signal": { "stars": 21800, "last_commit": "2026-06-15", "reputability": "org" },
          "default_installed": false,
          "safety": "clean — discovery source only, nothing executed",
          "tags": ["aggregator", "scout", "subagents", "discovery"]
        },
        {
          "id": "anthropics-claude-plugins-community",
          "name": "Anthropic Claude Plugins Community Index",
          "type": "aggregator",
          "domain": "dev-workflow",
          "description": "Scout source: 2,201-plugin community index; discovery source, NOT first-party-vetted. Not installable.",
          "source": "https://github.com/anthropics/claude-plugins-community",
          "install": null,
          "license": "Apache-2.0",
          "maintainer": "anthropics",
          "signal": { "stars": 183, "last_commit": "2026-06-15", "reputability": "official" },
          "default_installed": false,
          "safety": "clean — community index, not first-party-vetted; verify each entry before installing",
          "tags": ["aggregator", "scout", "plugins", "community", "discovery"]
        },
        {
          "id": "nansen-mcp",
          "name": "Nansen",
          "type": "mcp",
          "domain": "data",
          "description": "Institutional on-chain analytics via Nansen's hosted MCP: wallet labeling/profiler, smart-money flows, token analytics (DEX trades, OHLCV, screener, quant scores), PnL, holder analysis. 18+ chains including Solana. Net-new vs solana-new.",
          "source": "https://github.com/nansen-ai/nansen-cli",
          "install": {
            "method": "remote-http-mcp",
            "command": "claude mcp add --transport http nansen https://mcp.nansen.ai/ra/mcp --header \"NANSEN-API-KEY: ${NANSEN_API_KEY}\"",
            "env": ["NANSEN_API_KEY"]
          },
          "license": "proprietary hosted MCP; nansen-cli MIT",
          "maintainer": "Nansen (first-party)",
          "signal": { "stars": null, "last_commit": "2026-06-11", "reputability": "high" },
          "default_installed": false,
          "safety": "caution: SaaS data-routing — queries and API key sent to mcp.nansen.ai (Nansen servers); key passed in request header; free tier 100 credits, paid ~$0.001/credit or $0.01–$0.05/x402 call; opt-in only",
          "tags": ["analytics", "wallet-labeling", "smart-money", "on-chain-data", "solana", "multi-chain", "paid"]
        }
      ]
    }
    
  • SKILL.md 17 KB
    ---
    name: solana-dev
    description: Routing hub for Solana development. Maps a task to the one reference to read first in the ext/ skill submodules or the kit's local skills.
    user-invocable: true
    ---
    
    # Solana skill hub
    
    Find the task, read the linked file, and follow further links only as needed. Paths are relative to this file.
    
    Every install carries the core packs, solana-dev and safe-solana-builder. The other `ext/` packs are extensions: the kit pins them, and a project installs one when a task needs it. A row that links into an extension gives its install command; run it when the linked folder is missing (`/update` keeps what you install). The Extensions table at the end lists each one with when to use it.
    
    When sources overlap: the program-code house rules in the project instruction file (`CLAUDE.md`, or `AGENTS.md` in `--agents` installs) win; a protocol's official skill wins for its own SDK (Jupiter, Metaplex, Helius, MagicBlock, Alchemy); [ext/solana-dev](ext/solana-dev/skills/solana-dev/SKILL.md) wins for general Solana work; sendai and community skills fill gaps only.
    
    ## Programs
    
    | Task | Read |
    |------|------|
    | Any program, client or test work (entry point) | [solana-dev SKILL.md](ext/solana-dev/skills/solana-dev/SKILL.md) |
    | Anchor | [programs/anchor.md](ext/solana-dev/skills/solana-dev/references/programs/anchor.md); upgrading to 1.x: [migrating-v0.32-to-v1.md](ext/solana-dev/skills/solana-dev/references/anchor/migrating-v0.32-to-v1.md) |
    | Pinocchio, CU optimization | [programs/pinocchio.md](ext/solana-dev/skills/solana-dev/references/programs/pinocchio.md) |
    | Account and PDA design | [programs/design-patterns.md](ext/solana-dev/skills/solana-dev/references/programs/design-patterns.md) |
    | Tests: LiteSVM, Mollusk, Surfpool | [testing.md](ext/solana-dev/skills/solana-dev/references/testing.md), [surfpool/overview.md](ext/solana-dev/skills/solana-dev/references/surfpool/overview.md) |
    | Error codes, failing transactions | [common-errors.md](ext/solana-dev/skills/solana-dev/references/common-errors.md) |
    | Toolchain version pairing | [compatibility-matrix.md](ext/solana-dev/skills/solana-dev/references/compatibility-matrix.md) |
    | Security review | [security.md](ext/solana-dev/skills/solana-dev/references/security.md), [safe-solana-builder](ext/safe-solana-builder/SKILL.md) (security-first scaffolding, Anchor/native/Pinocchio) |
    | Financial math, Quasar zero-copy | [RUST.md](ext/quicknode-anchor/skills/solana/RUST.md), [ANCHOR.md](ext/quicknode-anchor/skills/solana/ANCHOR.md), [QUASAR.md](ext/quicknode-anchor/skills/solana/QUASAR.md) from [quicknode-anchor](ext/quicknode-anchor/); reference files only, skip that repo's SKILL.md workflow layer (install: `bash .claude/bin/skills.sh add quicknode-anchor`) |
    | Formal verification (Lean 4) | [qedgen](ext/qedgen/skills/qedgen/SKILL.md) from [QEDGen](ext/qedgen/); needs the `qedgen` CLI and `MISTRAL_API_KEY` (install: `bash .claude/bin/skills.sh add qedgen`) |
    | Port from Solidity/EVM | [eth-to-sol](ext/eth-to-sol/SKILL.md) from [eth-to-sol](ext/eth-to-sol/): [type-mapping](ext/eth-to-sol/translation/type-mapping.md), [pattern-mapping](ext/eth-to-sol/translation/pattern-mapping.md), [stdlib-mapping](ext/eth-to-sol/translation/stdlib-mapping.md), [mental-model](ext/eth-to-sol/translation/mental-model.md), [translation/](ext/eth-to-sol/translation/), [security/](ext/eth-to-sol/security/), [optimization/](ext/eth-to-sol/optimization/); concept map: [solana-vs-evm.md](ext/solana-new/skills/idea/solana-beginner/references/solana-vs-evm.md) (install: `bash .claude/bin/skills.sh add eth-to-sol solana-new`) |
    
    Anchor 1.x defaults this kit uses (not all spelled out upstream): SPL transfers through `token_interface::transfer_checked`, account space `T::DISCRIMINATOR.len() + T::INIT_SPACE`, Rust LiteSVM tests under `programs/<name>/tests/` (`anchor test` runs Surfpool).
    
    ## Clients and frontend
    
    | Task | Read |
    |------|------|
    | Wallet connection, React hooks, `@solana/kit` UI | [frontend.md](ext/solana-dev/skills/solana-dev/references/frontend.md) |
    | Transactions, Kit and web3.js boundary | [kit-web3-interop.md](ext/solana-dev/skills/solana-dev/references/kit-web3-interop.md) |
    | web3.js to Kit migration | [solana-kit-migration/](ext/sendai/skills/solana-kit-migration/), [solana-kit/](ext/sendai/skills/solana-kit/) (install: `bash .claude/bin/skills.sh add sendai`) |
    | Clients generated from an IDL (Codama, Shank) | [idl-codegen.md](ext/solana-dev/skills/solana-dev/references/idl-codegen.md) |
    | Payments, Solana Pay, Kora | [payments.md](ext/solana-dev/skills/solana-dev/references/payments.md) |
    | Official doc links | [resources.md](ext/solana-dev/skills/solana-dev/references/resources.md) |
    | Vercel, Next.js, AI SDK, v0 | [ext/vercel/skills/](ext/vercel/skills/) from [Vercel](ext/vercel/) (install: `bash .claude/bin/skills.sh add vercel`) |
    | UI design direction; Playwright tests of a local dApp | Anthropic's `frontend-design/SKILL.md` and `webapp-testing/SKILL.md` (install: `bash .claude/bin/skills.sh add anthropic-skills`; later sessions load them by description) |
    
    ## Tokens and NFTs
    
    | Task | Read |
    |------|------|
    | Token-2022 extensions: pick, combine and create them (CLI, Kit, Anchor); fees, hooks, metadata, pausable, soulbound | [token-extensions](token-extensions/SKILL.md) |
    | Confidential transfers | [confidential-transfers.md](ext/solana-dev/skills/solana-dev/references/confidential-transfers.md) |
    | NFTs: Core, Token Metadata, Bubblegum, Candy Machine, Umi | [metaplex](ext/metaplex/skills/metaplex/SKILL.md) (official; install: `bash .claude/bin/skills.sh add metaplex`) |
    
    ## DeFi, RPC and data
    
    | Task | Read |
    |------|------|
    | Jupiter swap, lend, perps, trigger, recurring | [integrating-jupiter](ext/jupiter/skills/integrating-jupiter/SKILL.md) (official); also [jupiter-lend](ext/jupiter/skills/jupiter-lend/SKILL.md), [jupiter-swap-migration](ext/jupiter/skills/jupiter-swap-migration/SKILL.md), [jupiter-vrfd](ext/jupiter/skills/jupiter-vrfd/SKILL.md) (install: `bash .claude/bin/skills.sh add jupiter`) |
    | Helius RPC, DAS, webhooks, Sender, priority fees | [helius](ext/helius/helius-skills/helius/SKILL.md) (official; install: `bash .claude/bin/skills.sh add helius`) |
    | SVM internals, consensus, validators, SIMDs | [svm](ext/helius/helius-skills/svm/SKILL.md) (install: `bash .claude/bin/skills.sh add helius`) |
    | Alchemy RPC, DAS, Yellowstone gRPC; keyless x402 access | [alchemy-api](ext/alchemy/skills/alchemy-api/SKILL.md) (official), [agentic-gateway](ext/alchemy/skills/agentic-gateway/SKILL.md) (install: `bash .claude/bin/skills.sh add alchemy`) |
    | MagicBlock Ephemeral Rollups: delegated state, real-time apps and games, private payments, VRF, cranks | [magicblock](ext/magicblock/skill/SKILL.md) (official; install: `bash .claude/bin/skills.sh add magicblock`) |
    
    Other protocols from [SendAI](ext/sendai/skills/) (install: `bash .claude/bin/skills.sh add sendai`): perps [phoenix](ext/sendai/skills/phoenix/) and leverage [lavarage](ext/sendai/skills/lavarage/); AMMs [raydium](ext/sendai/skills/raydium/), [meteora](ext/sendai/skills/meteora/), [orca](ext/sendai/skills/orca/); lending [kamino](ext/sendai/skills/kamino/), [marginfi](ext/sendai/skills/marginfi/); LSTs [sanctum](ext/sendai/skills/sanctum/); launches [pumpfun](ext/sendai/skills/pumpfun/); oracles [pyth](ext/sendai/skills/pyth/), [switchboard](ext/sendai/skills/switchboard/); multisig [squads](ext/sendai/skills/squads/); bridging [debridge](ext/sendai/skills/debridge/), [lifi](ext/sendai/skills/lifi/); encrypted compute [arcium](ext/sendai/skills/arcium/); ZK compression [light-protocol](ext/sendai/skills/light-protocol/); data [birdeye](ext/sendai/skills/birdeye/), [wallet-analysis](ext/sendai/skills/wallet-analysis/); RPC [carbium](ext/sendai/skills/carbium/), [quicknode](ext/sendai/skills/quicknode/); order book [manifest](ext/sendai/skills/manifest/); order flow [dflow](ext/sendai/skills/dflow/); account cleanup [sol-incinerator](ext/sendai/skills/sol-incinerator/); agents [solana-agent-kit](ext/sendai/skills/solana-agent-kit/); wallets [phantom-connect](ext/sendai/skills/phantom-connect/); scanning [vulnhunter](ext/sendai/skills/vulnhunter/). SendAI's own jupiter, metaplex, helius and magicblock folders are older copies; the official skills above supersede them.
    
    ## Security tooling
    
    - [safe-ai-skill](https://github.com/solanabr/safe-ai-skill), core (the `safe-ai-skill@stbr` plugin): hooks gate mainnet, value-moving and authority actions and secret reads. At session start it pins skills and `ext/` submodules and moves any that drift or look unsafe into quarantine, so a missing `ext/` path may be quarantined rather than uninitialized. Its ask or deny is the user's policy, so don't retry the action another way. CLI (on PATH while the plugin is enabled, else `npx @stbr/safe-ai-skill`): `status`, `verify check <dir>`, `registry list`.
    - [Trail of Bits](ext/trailofbits/plugins/building-secure-contracts/skills/) (install: `bash .claude/bin/skills.sh add trailofbits`): [solana-vulnerability-scanner](ext/trailofbits/plugins/building-secure-contracts/skills/solana-vulnerability-scanner/), [audit-prep-assistant](ext/trailofbits/plugins/building-secure-contracts/skills/audit-prep-assistant/), [code-maturity-assessor](ext/trailofbits/plugins/building-secure-contracts/skills/code-maturity-assessor/), [token-integration-analyzer](ext/trailofbits/plugins/building-secure-contracts/skills/token-integration-analyzer/), [guidelines-advisor](ext/trailofbits/plugins/building-secure-contracts/skills/guidelines-advisor/)
    - [Ghost Security](ext/ghostsecurity/plugins/ghost/skills/) AppSec (install: `bash .claude/bin/skills.sh add ghostsecurity`): [scan-code](ext/ghostsecurity/plugins/ghost/skills/scan-code/) with per-stack [criteria](ext/ghostsecurity/plugins/ghost/skills/scan-code/criteria/), [scan-deps](ext/ghostsecurity/plugins/ghost/skills/scan-deps/), [scan-secrets](ext/ghostsecurity/plugins/ghost/skills/scan-secrets/), [repo-context](ext/ghostsecurity/plugins/ghost/skills/repo-context/), [validate](ext/ghostsecurity/plugins/ghost/skills/validate/), [report](ext/ghostsecurity/plugins/ghost/skills/report/). Its proxy, scan-deps and scan-secrets files include unpinned `curl ... | bash` installers; run them only with the user's consent.
    - [Anthropic defending-code](ext/defending-code/) (install: `bash .claude/bin/skills.sh add defending-code`): [threat-model](ext/defending-code/.claude/skills/threat-model/), [vuln-scan](ext/defending-code/.claude/skills/vuln-scan/), [triage](ext/defending-code/.claude/skills/triage/), [patch](ext/defending-code/.claude/skills/patch/), methodology [docs](ext/defending-code/docs/)
    
    ## Deploy, infra, backend
    
    - [deployment.md](deployment.md): devnet and mainnet flow, verifiable builds, Squads multisig upgrades, rollback
    - [backend-async.md](backend-async.md): Rust services and indexers that talk to Solana
    - MCP server for a program or API: Anthropic's `mcp-builder/SKILL.md` (install: `bash .claude/bin/skills.sh add anthropic-skills`); its evaluation script needs `ANTHROPIC_API_KEY`
    - [Cloudflare](ext/cloudflare/skills/) (install: `bash .claude/bin/skills.sh add cloudflare`): [workers-best-practices](ext/cloudflare/skills/workers-best-practices/), [agents-sdk](ext/cloudflare/skills/agents-sdk/), [sandbox-stable](ext/cloudflare/skills/sandbox-stable/), [durable-objects](ext/cloudflare/skills/durable-objects/), [wrangler](ext/cloudflare/skills/wrangler/)
    
    ## Games and mobile
    
    - [solana-game](ext/solana-game/skill/) (install: `bash .claude/bin/skills.sh add solana-game`): [SKILL.md](ext/solana-game/skill/SKILL.md), [unity-sdk.md](ext/solana-game/skill/unity-sdk.md), [playsolana.md](ext/solana-game/skill/playsolana.md) (PSG1, PlayDex, PlayID), [game-architecture.md](ext/solana-game/skill/game-architecture.md), [mobile.md](ext/solana-game/skill/mobile.md), [csharp-patterns.md](ext/solana-game/skill/csharp-patterns.md)
    - [solana-mobile](ext/solana-mobile/skills/) (install: `bash .claude/bin/skills.sh add solana-mobile`): [solana-mobile-wallet](ext/solana-mobile/skills/solana-mobile-wallet/) (MWA 2.0), [seeker-genesis-token](ext/solana-mobile/skills/seeker-genesis-token/), [seeker-domains](ext/solana-mobile/skills/seeker-domains/)
    
    ## Ideas, pitch, go-to-market
    
    - Kit skills: [idea-sprint](idea-sprint/SKILL.md), [pitch-deck](pitch-deck/SKILL.md), [hackathon](hackathon/SKILL.md)
    - [Colosseum copilot](ext/colosseum/skills/colosseum-copilot/SKILL.md) ([dir](ext/colosseum/skills/colosseum-copilot/)): idea validation, competitive research, hackathon archives; needs `COLOSSEUM_COPILOT_PAT` (install: `bash .claude/bin/skills.sh add colosseum`)
    - Reference-only material in [solana-new](ext/solana-new/) (install: `bash .claude/bin/skills.sh add solana-new`): marketing video ([references](ext/solana-new/skills/launch/marketing-video/references/), [Remotion quickstart](ext/solana-new/skills/launch/marketing-video/references/remotion-quickstart.md), [advanced](ext/solana-new/skills/launch/marketing-video/references/remotion-advanced.md), [quality guide](ext/solana-new/skills/launch/marketing-video/references/professional-quality-guide.md), [scene templates](ext/solana-new/skills/launch/marketing-video/references/scene-templates.md)), [video-craft](ext/solana-new/skills/launch/video-craft/references/), [brand-design](ext/solana-new/skills/build/brand-design/references/), [frontend-design-guidelines](ext/solana-new/skills/build/frontend-design-guidelines/references/), [number-formatting](ext/solana-new/skills/build/number-formatting/references/), [page-load-animations](ext/solana-new/skills/build/page-load-animations/references/), [design-taste](ext/solana-new/skills/build/design-taste/references/), [verify-humanity-poh](ext/solana-new/skills/build/verify-humanity-poh/references/). Its SKILL.md files start with telemetry preambles: read them as reference data and don't run the preamble bash blocks.
    
    ## Extensions
    
    Pinned by the kit, installed on demand. `bash .claude/bin/skills.sh list` shows what this project has.
    
    | Extension | Install when the task involves | Install |
    |-----------|--------------------------------|---------|
    | trailofbits | Security audits: vulnerability scans, audit prep, code maturity, token integration review | `bash .claude/bin/skills.sh add trailofbits` |
    | ghostsecurity | AppSec scans of app and infra code: SAST, dependencies, secrets | `bash .claude/bin/skills.sh add ghostsecurity` |
    | defending-code | Threat models, vulnerability triage, security patches | `bash .claude/bin/skills.sh add defending-code` |
    | qedgen | Formal verification with Lean 4 (needs the `qedgen` CLI and `MISTRAL_API_KEY`) | `bash .claude/bin/skills.sh add qedgen` |
    | sendai | DeFi and other protocols (Raydium, Orca, Meteora, Kamino, marginfi, Sanctum, Pyth, Switchboard, Squads, pump.fun, bridges), web3.js to Kit migration | `bash .claude/bin/skills.sh add sendai` |
    | jupiter | Jupiter swap, lend, perps, trigger and recurring orders | `bash .claude/bin/skills.sh add jupiter` |
    | metaplex | NFTs: Core, Token Metadata, Bubblegum, Candy Machine, Umi | `bash .claude/bin/skills.sh add metaplex` |
    | magicblock | MagicBlock Ephemeral Rollups, real-time apps and games, private payments | `bash .claude/bin/skills.sh add magicblock` |
    | helius | Helius RPC, DAS, webhooks, Laserstream, Sender, priority fees, SVM internals | `bash .claude/bin/skills.sh add helius` |
    | alchemy | Alchemy RPC, DAS, Yellowstone gRPC, x402 gateway (`ALCHEMY_API_KEY` for the API skill) | `bash .claude/bin/skills.sh add alchemy` |
    | quicknode-anchor | Financial math, fixed-point arithmetic, Quasar zero-copy | `bash .claude/bin/skills.sh add quicknode-anchor` |
    | eth-to-sol | Porting Solidity or other EVM contracts | `bash .claude/bin/skills.sh add eth-to-sol` |
    | solana-game | Unity, C#, games, PlaySolana, PSG1 | `bash .claude/bin/skills.sh add solana-game` |
    | solana-mobile | React Native, Expo, Mobile Wallet Adapter, Seeker, dApp Store | `bash .claude/bin/skills.sh add solana-mobile` |
    | cloudflare | Cloudflare Workers, wrangler, Durable Objects, Agents SDK | `bash .claude/bin/skills.sh add cloudflare` |
    | vercel | Vercel deploys, Next.js and React performance, web design review | `bash .claude/bin/skills.sh add vercel` |
    | solana-new | Go-to-market references: marketing video, brand design, tokenomics, DefiLlama research, ecosystem catalogs; idea-sprint, pitch-deck and hackathon link it | `bash .claude/bin/skills.sh add solana-new` |
    | colosseum | Colosseum hackathon archives, idea validation, competitive research (needs `COLOSSEUM_COPILOT_PAT`) | `bash .claude/bin/skills.sh add colosseum` |
    | anthropic-skills | UI design direction, Playwright tests of a local web app, building an MCP server (Anthropic's Apache-2.0 frontend-design, webapp-testing and mcp-builder, installed as top-level skills in `skills/<name>/`) | `bash .claude/bin/skills.sh add anthropic-skills` |
    
    ## Add-ons
    
    [skill-registry.json](skill-registry.json) records each pack's tier, triggers, license and source. Its entries without a tier are opt-in tools the kit doesn't pin; install one only when the user asks and `safe-ai-skill add skill|mcp <source>` returns `proceed: true`. Wider ecosystem catalogs: [ext/solana-new/cli/data/](ext/solana-new/cli/data/) (install: `bash .claude/bin/skills.sh add solana-new`).
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related