The Rustlings-inspired onboarding journey to Solana.
Think back to your first Rustlings exercise: you fixed a tiny compile error,
hit cargo test, and… all green. That quick win pulled you deeper into Rust.
Anchorlings recreates that exact moment — only now the green lights unlock
Solana. Each exercise is a small, broken Anchor program with a // TODO:
comment. You edit, re-run, watch the error change shape, and move on.
Rust developers (comfortable with Rustlings-level Rust) who want a tight
compile / test / fix loop into Anchor. You're assumed to know what a
keypair and a transaction are; you're not assumed to know what a PDA
is, or why an Account<'info, T> differs from an AccountInfo<'info>.
What this is not: a Solana fundamentals course, a deployment tutorial,
or a TypeScript-client tutorial. No JavaScript anywhere. No on-chain
deploy. Pure Rust, pure host-tier compile + solana-program-test.
Today Anchorlings runs from a cloned checkout (a cargo install anchorlings distribution is on the roadmap):
git clone https://github.com/NZT48/anchorlings
cd anchorlings
cargo build -p anchorlings
./target/debug/anchorlings list # see the 28 exercises
./target/debug/anchorlings # enter watch mode (default)The first compile fetches anchor + solana — expect ~1–2 minutes once. After that, each iteration is sub-second.
Default mode is watch: anchorlings runs the current exercise once, then
re-runs it on every save inside exercises/. On green it auto-advances to
the next exercise and watches that one. The whole feedback loop becomes:
anchorlings # starts; runs current; you see the error
# edit the file in your editor and save
# ← debouncer fires (~1s), re-runs, prints result
# ← on pass, advances to next exercise automatically
# edit the next file…
^C # quit when you want
Prefer one-shot? anchorlings run runs the current exercise once and
exits — useful in CI or scripts.
| Command | What it does |
|---|---|
anchorlings / anchorlings watch |
Watch mode (default): re-runs the current exercise on every save in exercises/, advances on pass |
anchorlings run |
Runs the current exercise once and exits (no watching) |
anchorlings run <name> |
Runs a specific exercise (e.g. ex04_handler_arg) |
anchorlings list |
Shows every exercise with done (✓) / current marker |
anchorlings hint |
Prints the hint for the current exercise |
anchorlings hint <name> |
Prints the hint for a specific one |
anchorlings reset <name> |
Marks an exercise as not-done (file restore is not yet wired up — revert the source manually) |
Progress lives in .anchorlings-state.toml at the workspace root. Delete
it to start over.
28 exercises across 12 chapters. Numbers grow as the curriculum deepens; see Roadmap below.
| # | Chapter | Exercises | Tier | What you learn |
|---|---|---|---|---|
| 01 | Skeleton | 3 | check | declare_id!, #[program], handler shape |
| 02 | Handlers | 4 | check | Instruction args, return types, custom-struct args |
| 03 | Accounts structs | 4 | check | #[derive(Accounts)], the 'info lifetime, multiple handlers |
| 04 | Constraints | 3 | mixed | mut, signer, has_one |
| 05 | Account types | 3 | mixed | Account<'info, T>, SystemAccount, Program<'info, T> |
| 06 | State | 2 | mixed | #[account], multi-field state mutations |
| 07 | Init & space | 2 | check | init constraint, payer, space, #[derive(InitSpace)] |
| 08 | Errors | 2 | mixed | #[error_code], require! |
| 09 | PDAs | 2 | mixed | seeds, bump, find_program_address |
| 10 | PDA signing | 1 | check | ctx.bumps.* for invoke_signed |
| 11 | CPIs | 1 | test | CpiContext, System Program transfer |
| 12 | Events | 1 | check | #[event], emit! |
Tier explained:
- check — Anchorlings runs
cargo check+cargo clippy. The broken state produces a real compile error you can read and fix. - test — Anchorlings runs
cargo check+cargo test+cargo clippy. The exercise ships an integration test that boots asolana-program-testbank, builds a real transaction, and asserts the lesson at runtime.
exercises/01_skeleton/ex01_declare_id/
├── Cargo.toml # tiny anchor lib crate
└── src/lib.rs # broken program with a // TODO
solutions/01_skeleton/ex01_declare_id/
├── Cargo.toml
└── src/lib.rs # the fixed version
Test-tier exercises also have:
tests/<name>.rs # solana-program-test driver
Every exercise is a real crate — Anchor's macros need a module/crate context, so the rustlings "single .rs file" form doesn't apply. The tier is what we run on it, not what shape it is.
solana-program-test's processor! macro expects a fn pointer with
independent lifetimes on the AccountInfo slice vs. its elements, but
Anchor's generated entry ties them together (&'info [AccountInfo<'info>]).
Test-tier exercises use a one-line helper from
test-kit/:
anchorlings_test_kit::anchor_entry!(entry, my_program);
#[tokio::test]
async fn it_runs() {
let (mut banks, payer, blockhash) =
ProgramTest::new("my_program", my_program::ID, processor!(entry))
.start().await;
// ...
}The unsafe lifetime-laundering lives in the kit, not in your face.
A single script checks every solution compiles and every test-tier solution passes its tests:
./scripts/verify-solutions.shUsed in CI; useful locally before opening a PR.
| Concern | Decision | Why |
|---|---|---|
| Test harness | solana-program-test |
Full tx semantics, official, pure-Rust, no validator process |
| Compile target | Native (host) only | No BPF/SBF — faster, no toolchain deps |
| Exercise language | Rust | No TypeScript anywhere |
| CLI language | Rust | Mirrors the stack |
| Prerequisites | cargo only |
No solana-cli, no anchor-cli, no avm. All deps are pinned crates |
| Anchor version | =0.30.1 |
Pinned exact to prevent semver drift mid-curriculum |
| Solana version | =1.18.26 |
Mutually compatible with Anchor 0.30.1 |
What works today:
- ✅ 28 exercises authored, all solutions compile, all test-tier solutions pass
- ✅ Watch mode (default):
notify+ 1s debounce, re-runs on save, auto-advances on pass - ✅
anchorlings run / list / hint / resetCLI - ✅
solana-program-test↔ Anchor lifetime bridge viatest-kit - ✅ Per-project state file with auto-advance on green
- ✅ Verification script
What's next (PRs welcome):
- ⏳
anchorlings init— scaffold a workspace into an empty dir from embedded resources - ⏳ File restore on
reset— replace edited source with the original embedded bytes - ⏳ Fill out the curriculum —
owner,address, combinations in Ch 04; a real PDA-signed CPI in Ch 10; more state and event work; aiming for ~45 exercises total - ⏳
cargo install anchorlingsdistribution onceinitlands - ⏳ Public leaderboard for friendly rivalry on completion counts
Anchorlings is open source and built for "first time OSS" contributions.
- Adding an exercise: pick an open issue tagged
good-first-exercise, copy an existing exercise + solution + info.toml entry, send a PR. - Improving a hint: hints live in
info.toml. One-line change, big pedagogical impact. - Fixing a typo or a clippy nit: just send the PR.
Each exercise should follow the same three-part rhythm:
- Broken state that produces a clean, teachable error — never a wall of macro vomit.
- Hint that points at the lesson without giving the answer.
- Solution that's the minimum change to make it pass.
Run ./scripts/verify-solutions.sh before opening a PR.
Licensed under the Apache License, Version 2.0.
Anchorlings makes Solana feel as friendly as your first Rustlings commit.
