Rustlings is a collection of small exercises that get you used to reading and
writing Rust code. You install one binary, run rustlings, and the tool walks
you through 96 hand-curated exercises across 24 topics — from your first
println! to threads, iterators, smart pointers, and macros. Each exercise is
a short Rust file with deliberate compile errors or failing tests; your job is
to read the compiler, fix the file, and watch Rustlings auto-detect your save
and re-run the check.
This guide covers everything a learner needs: install, the daily edit-save-pass loop, every key in watch mode, every CLI subcommand, the full topic map, and how to run a community exercise track.
1. Quick Start
Rustlings is a terminal-first interactive learner. It owns a single state file
in your working directory (.rustlings-state.txt), watches the exercises/
folder for changes, and re-runs the current exercise the moment you save.
Key features
- 96 official exercises, organized into 24 topic folders (variables, functions, if, primitives, vecs, move semantics, structs, enums, strings, modules, hashmaps, options, error handling, generics, traits, lifetimes, tests, iterators, smart pointers, threads, macros, clippy, conversions) plus three quizzes that mix concepts.
- Watch mode: file-system notifications auto-trigger
cargo build,cargo test, andcargo clippyfor the current exercise on every save. - One-keystroke controls:
nnext,hhint,llist,ccheck all,xreset,qquit,rmanual run. - Built-in interactive list view with search, filters (Done / Pending), and per-exercise reset.
--edit-cmdto auto-open exercises in your editor (auto-detects VS Code and Zellij).rustlings devsubcommand for authoring your own community exercise track.
Prerequisites: Rust toolchain 1.88 or newer (installs cargo, rustc,
rustfmt, and clippy).
Install and start in two commands:
cargo install rustlings
rustlings init
This command will create the directory `rustlings/` which will contain the exercises.
Press ENTER to continue
Initialization done ✓
Run `cd rustlings` to go into the generated directory.
Then run `rustlings` to get started.
Then drop into the new directory and run the bare binary:
cd rustlings
rustlings
The first time you run it you get a welcome message; press ENTER and Rustlings
opens watch mode on the first exercise (intro1). Open
exercises/00_intro/intro1.rs in your editor, follow the // I AM NOT DONE
comment, save, and Rustlings re-checks immediately.
Tip
If you're already inside a Cargo workspace when you run
rustlings init, Rustlings addsrustlingsto that workspace'smemberslist automatically instead of creating a standalone project. This is handy if you want Rustlings to share your existing target directory.
What to try next
- See the full topic map in section 4 ("Core Usage").
- Section 5 ("Common Tasks") walks through resetting an exercise, jumping ahead, and finishing the run.
- Section 6 ("Troubleshooting") covers the handful of errors people actually hit.
2. Installation
2.1 System requirements
| Requirement | Minimum | Notes |
|---|---|---|
| Rust toolchain | 1.88 | Set as rust-version in Cargo.toml. Older toolchains will refuse to build. |
| Cargo | bundled with Rust | Used for install, build, test, clippy, metadata. |
| Clippy | required | rustlings init aborts if cargo clippy --version fails. |
| Rustfmt | recommended | Required if you author solutions and want rustlings dev check to pass. |
| Terminal | interactive TTY | Watch mode refuses to start under a non-TTY stdout. |
| OS | Linux, macOS, Windows | All three are first-class. Windows crossterm features are enabled by default. |
Important
Rustlings is not a clone-the-repo workflow anymore. If you cloned the
rust-lang/rustlingsrepository and runrustlingsfrom there in a release build, it bails with the message "You are trying to run Rustlings using the old method before version 6." Usecargo install rustlingsfollowed byrustlings initinstead.
2.2 Install methods
Cargo (recommended)
cargo install rustlings
Cargo compiles from source, places the binary at ~/.cargo/bin/rustlings
(or %USERPROFILE%\.cargo\bin\rustlings.exe on Windows), and you're done.
Cargo + locked
cargo install rustlings --locked
--locked uses the exact dependency versions from the published Cargo.lock,
which protects you from a transitive crate breaking the build.
From source
git clone https://github.com/rust-lang/rustlings
cd rustlings
cargo install --path .
Useful only if you're contributing to Rustlings itself. For learning,
prefer cargo install rustlings.
2.3 Initialize an exercise project
After install, pick a directory where you'd like the rustlings/ folder to
live and run:
rustlings init
init does the following, in order:
- Refuses to run if a
rustlings/directory already exists. - Verifies that Rust is installed by calling
cargo locate-projectandcargo clippy --version. - If you're inside a Cargo workspace, asks for ENTER, then creates the directory as a workspace member. Otherwise, it just creates a standalone directory.
- Writes the
exercises/tree with all 96 exercise files, thesolutions/tree with placeholder files (filled in as you finish each exercise),Cargo.toml,rust-analyzer.toml(configures rust-analyzer to use Clippy with--profile test),.gitignore, and.vscode/extensions.json(recommends therust-lang.rust-analyzerextension). - If you're not already inside a
.gitor.jjrepository, runsgit initso your progress can be version-controlled.
This command will create the directory `rustlings/` which will contain the exercises.
Press ENTER to continue
Initialization done ✓
Run `cd rustlings` to go into the generated directory.
Then run `rustlings` to get started.
Warning
rustlings initaborts with "It looks like Rustlings is already initialized in this directory" if bothexercises/andsolutions/already exist. To start over, move or delete the old directory first.
2.4 Verify the install
rustlings --version
rustlings 6.5.0
cd rustlings
rustlings list
Press q to exit the list and you're ready to learn.
3. Configuration
Rustlings has zero user configuration in the traditional sense — there is no
~/.config/rustlings/config.toml, no environment variables, no profile file.
Everything is driven by command-line flags on the parent rustlings command
and a single state file.
3.1 Top-level flags
These flags belong to the parent rustlings command and apply across all
subcommands and the default watch mode.
| Flag | Default | Effect |
|---|---|---|
--no-editor |
off | Disables the automatic editor opener. Implies any --edit-cmd value is ignored. |
--edit-cmd "PROGRAM …" |
unset | Override the editor command. Rustlings appends the current exercise path as the last argument. The program is not allowed to block, so it must be a process-detaching launcher (e.g. code), not vim. |
--manual-run |
off | Disable the file watcher. You must press r in watch mode to rerun the exercise after each save. |
Examples:
rustlings --no-editor # Watch mode, no editor opens
rustlings --edit-cmd "code" # Open VS Code on each exercise
rustlings --edit-cmd "subl -n" # Open Sublime Text in a new window
rustlings --manual-run # File watcher off, press `r` to rerun
Note
Inside a VS Code integrated terminal Rustlings auto-detects the
TERM_PROGRAMenvironment variable and preferscode(orcodium) if either is on the PATH.--edit-cmdis ignored in VS Code terminals — VS Code's own URI handling opens the right file when Rustlings prints a clickable file link.
3.2 Editor integration
Rustlings can launch your editor on the current exercise file every time you move forward. Detection order:
- If
TERM_PROGRAM=vscode: trycode, thencodium. If either responds to--version, use it. - Otherwise, if you passed
--edit-cmd "PROGRAM …": parse it with shell-like splitting and use that. - Otherwise, if
$ZELLIJis set andzellij --versionsucceeds: open each exercise as a new Zellij pane (and close the previous pane on switch). - Otherwise: do not open an editor.
Tip
The
--edit-cmdvalue is parsed with a shell-style splitter, so quoted arguments work as expected:--edit-cmd "subl --new-window"becomessubl --new-window <path>. Quoting is required for arguments that contain spaces.
3.3 The state file
Rustlings creates .rustlings-state.txt in the project root the first time you
run it. The format is intentionally simple, one fact per line:
DON'T EDIT THIS FILE!
intro2
intro1
variables1
variables2
Line 1 is a header comment, line 2 is blank, line 3 is the current exercise
name, line 4 is blank, and every subsequent non-empty line is the name of an
exercise marked done. Rustlings always rewrites this file atomically
(rewind + truncate + write), so you can git add it to back up progress.
Caution
If you delete
.rustlings-state.txt, you lose your progress markers but not your work — the exercise files themselves are untouched. To start completely over you also need to revert the exercise files (rustlings reset <name>per file).
3.4 The info file (community tracks only)
If you create a community exercise track with rustlings dev new, the
authoritative configuration is info.toml at the project root. Official
Rustlings reads its own embedded info.toml; if you ship a custom one, see
the Admin Guide for the schema.
4. Core Usage
4.1 The default mode is watch mode
Run rustlings with no subcommand from inside the project directory and you
land in watch mode:
rustlings
Checking the exercise `intro1`. Please wait…
[Output of cargo build / cargo test / cargo clippy]
Progress: [######>-----------------------------------------] 1/96
Current exercise: exercises/00_intro/intro1.rs
n:next / h:hint / l:list / c:check all / x:reset / q:quit ?
The single-letter prompt at the bottom drives everything. As you save the
current .rs file in your editor, the file watcher (200 ms debounce) detects
the write, re-runs cargo build → cargo test (if the exercise has tests) →
cargo clippy, and re-renders. The progress bar at the bottom always reflects
total exercises done.
Note
Watch mode requires an interactive TTY. If stdout isn't a terminal (you piped output, ran inside CI, or launched the binary from a script), Rustlings exits with "Unsupported or missing terminal/TTY". Use
rustlings run <name>for non-interactive single-shot runs.
4.2 Watch-mode keys
These keys are only recognized when an exercise check is not running (input
is paused while cargo build etc. are working). Releases and repeats are
ignored — only key-press events fire.
| Key | What it does |
|---|---|
n |
Next. Only valid when the current exercise is done. Marks the current exercise complete in the state file and moves to the next pending exercise. |
r |
Run (manual mode only). Force-rerun the current exercise. Available only with --manual-run because in normal mode the file watcher does this for you. |
h |
Hint. Renders the multi-line hint for the current exercise. Hidden again on the next render. |
l |
List. Drops into the interactive list view (see 4.3). |
c |
Check all. Compiles + tests + clippies every exercise in parallel and marks them done/pending accordingly. Useful after editing many files at once. |
x |
Reset. Confirms with (y/n), then restores the current exercise file to its original content. |
q |
Quit. Prints a goodbye message and exits cleanly. |
Tip
Mouse scroll wheel works inside the interactive list view, so you don't have to hammer
j/k. In the watch screen, you can resize your terminal and the progress bar redraws to fit.
4.3 The interactive list view (l from watch, or rustlings list)
Press l in watch mode (or close watch mode and run rustlings list) to enter
a full-screen list. Every exercise appears with its done/pending status, and
the keyboard map mirrors common pager conventions:
| Key | Effect |
|---|---|
j / Down |
Move selection down |
k / Up |
Move selection up |
g / Home |
Jump to first |
G / End |
Jump to last |
d |
Toggle DONE filter (show only completed exercises) |
p |
Toggle PENDING filter (show only outstanding exercises) |
s or / |
Start incremental search by exercise name |
r |
Reset the highlighted exercise to its original content |
c |
Set the highlighted exercise as the current one (returns to watch mode) |
Esc |
Exit search mode (or clear the inline message) |
q |
Exit list view |
| Mouse scroll | Move selection up/down |
| Backspace | Delete a character from the search query |
Filter keys are toggles: press d once to show only done, press d again to
clear. Search and filters compose — search within the active filter set.
4.4 CLI subcommands
| Subcommand | What it does |
|---|---|
| (no subcommand) | Enter watch mode on the current/next exercise. |
init |
Initialize a new rustlings/ directory in the current dir. |
run [NAME] |
Run a single exercise once. With NAME, jump to and run that exercise. Without, run the next pending one. Exits with code 1 if the exercise fails. |
check-all |
Compile + test + clippy every exercise in parallel and mark them done/pending. Exits 1 if anything is pending. |
reset NAME |
Restore an exercise file to its original contents. The current exercise is also marked pending. |
hint [NAME] |
Print the hint for NAME (or for the next pending exercise) and exit. |
dev … |
Tools for authoring community exercise tracks. See section 4.5. |
rustlings run # Run the next pending exercise
rustlings run variables3 # Jump to variables3, run it once
rustlings hint # Print the hint for the next pending exercise
rustlings hint hashmaps2 # Print the hint for hashmaps2
rustlings reset move_semantics4 # Restore move_semantics4.rs to original
rustlings check-all # Run every exercise and tally pass/fail
Note
run,hint, andresetall update.rustlings-state.txtto record which exercise you're now "on" — they're not pure read commands.check-allwrites the per-exercise done/pending status for every exercise.
4.5 The rustlings dev family
rustlings dev is the toolkit for authoring an exercise track of your
own (a "community Rustlings"). Most learners never touch these.
| Subcommand | What it does |
|---|---|
dev new PATH [--no-git] |
Scaffold a new community-exercises project at PATH. Creates info.toml, Cargo.toml, README.md, .gitignore, .vscode/extensions.json, and exercises/ and solutions/ directories. Runs git init unless --no-git is given. |
dev check [-r/--require-solutions] |
Validate info.toml, exercise file conventions, the bin = […] section of Cargo.toml, and (if --require-solutions) that every exercise has a working solution and is rustfmt-clean. |
dev update |
Regenerate the bin = […] list in Cargo.toml from the current info.toml. Run this after adding or renaming an exercise. |
dev new aborts on the first failure (e.g. a git init non-zero exit code)
with a helpful message. dev check is strict: empty exercise names, duplicate
names, names containing characters other than [a-zA-Z0-9_], missing // TODO
comments, missing fn main() declarations, more than 999 exercises, or a
Cargo.toml whose bin = […] doesn't match info.toml are all hard errors.
See the Admin Guide section 8 for the full info.toml schema and the rules
dev check enforces.
4.6 The 24 topic folders
Each topic has its own exercises/<NN>_<topic>/README.md that explains what
you'll learn and links to the relevant chapters of The Rust Programming
Language book. Topics are presented strictly in this order:
| # | Folder | Exercises | Concept the folder teaches |
|---|---|---|---|
| 00 | 00_intro |
intro1, intro2 |
Mechanics of the Rustlings loop. intro1 is intentionally pre-solved (skip_check_unsolved = true). |
| 01 | 01_variables |
variables1–variables6 |
let, mut, shadowing, const, type inference, type annotations. |
| 02 | 02_functions |
functions1–functions5 |
Declarations, parameters with type annotations, return types, expression-vs-statement, the implicit unit return. |
| 03 | 03_if |
if1, if2, if3 |
if/else as expressions, branch-type unification, no parentheses. |
| Q1 | quizzes/quiz1 |
quiz1 |
Mixed quiz on variables, functions, if. |
| 04 | 04_primitive_types |
primitive_types1–primitive_types6 |
Booleans, characters, arrays, slices, tuples, indexing vs destructuring. |
| 05 | 05_vecs |
vecs1, vecs2 |
Vec::new(), vec![], push, iteration. |
| 06 | 06_move_semantics |
move_semantics1–move_semantics5 |
Ownership transfer, mut on bindings, borrows, &mut T lifetimes. |
| 07 | 07_structs |
structs1, structs2, structs3 |
Regular, tuple, and unit structs; struct update syntax; impl blocks and methods. |
| 08 | 08_enums |
enums1, enums2, enums3 |
Enum variants with different shapes, pattern matching, match deconstruction. |
| 09 | 09_strings |
strings1–strings4 |
&str vs String, From, deref coercion, trim, format!, replace. |
| 10 | 10_modules |
modules1, modules2, modules3 |
pub, use, pub use re-exports, nested paths from std::time. |
| 11 | 11_hashmaps |
hashmaps1, hashmaps2, hashmaps3 |
HashMap insertion, entry().or_insert(), entry().or_default(). |
| Q2 | quizzes/quiz2 |
quiz2 |
Mixed quiz; String + &str concatenation. |
| 12 | 12_options |
options1, options2, options3 |
Some/None, unwrap, nested if let, Option::flatten, partial moves with ref. |
| 13 | 13_error_handling |
errors1–errors6 |
Result<T, E>, the ? operator, Box<dyn Error>, map_err, validating constructors. |
| 14 | 14_generics |
generics1, generics2 |
Type parameters, generic methods. |
| 15 | 15_traits |
traits1–traits5 |
Trait declaration, default implementations, traits-as-parameters, multiple trait bounds with +. |
| Q3 | quizzes/quiz3 |
quiz3 |
Mixed quiz; trait bound syntax. |
| 16 | 16_lifetimes |
lifetimes1, lifetimes2, lifetimes3 |
Generic lifetimes 'a, narrowing scopes to make borrows valid. |
| 17 | 17_tests |
tests1, tests2, tests3 |
assert!, assert_eq!, #[should_panic]. |
| 18 | 18_iterators |
iterators1–iterators5 |
The Iterator trait, collect, fold/rfold, FromIterator. |
| 19 | 19_smart_pointers |
box1, rc1, arc1, cow1 |
Box<T> for recursive types, Rc<T> reference counting, Arc<T> for threads, Cow clone-on-write. |
| 20 | 20_threads |
threads1, threads2, threads3 |
JoinHandle::join, Arc<Mutex<T>>, mpsc channels. |
| 21 | 21_macros |
macros1–macros4 |
Calling macros, scope rules, #[macro_use], macro arms. |
| 22 | 22_clippy |
clippy1, clippy2, clippy3 |
All three exercises run with strict_clippy = true (warnings = errors). Replace approximate constants with std::f32::consts, prefer if let over for over Option. |
| 23 | 23_conversions |
using_as, from_into, from_str, try_from_into, as_ref_mut |
The as cast, From/Into, FromStr, TryFrom/TryInto, AsRef/AsMut. |
That's 96 exercises across 24 directories. Each exercises/<NN>_<topic>/
folder has a README.md introduction; read it before opening the first file
in that folder.
Tip
Don't memorize the order — Rustlings drives the order itself. Just save the current file and follow the prompts. You can always jump using
rustlings run <name>or by selecting a different exercise in the list view (lthenc).
4.7 What "done" means
A pending exercise becomes done when:
cargo build --bin <exercise_name>exits 0.- If
test = trueininfo.toml(the default),cargo test --bin <name>passes. cargo clippy --bin <name> --profile testpasses. If the exercise setsstrict_clippy = true(e.g.clippy1/clippy2/clippy3), Rustlings appends-- -D warningsso any Clippy warning fails the check.cargo run --bin <name>exits 0.
If any step fails, you stay pending and Rustlings shows the compiler/test/clippy
output. Press h for the curated hint or read the comments in the exercise
file.
5. Common Tasks
5.1 Start the next pending exercise
rustlings
Watch mode opens on the next exercise that isn't yet done. If you're brand new,
that's intro1.
5.2 Reset an exercise to its original content
rustlings reset variables3
The exercise exercises/01_variables/variables3.rs has been reset
The state file is updated to mark variables3 pending. In watch mode you can
also press x to reset whichever exercise you're currently looking at, then
confirm with y.
Caution
Reset is destructive — it overwrites your edits with the bundled exercise file. There's no undo. If you want to compare your work against the official solution first, look at
solutions/<NN>_<topic>/<name>.rs, which is dumped to disk after you finish each exercise (in release builds).
5.3 Skip ahead to a specific exercise
rustlings run hashmaps2
This runs hashmaps2 once, prints its compiler/test/clippy output, and updates
.rustlings-state.txt to set hashmaps2 as the current exercise. Re-running
rustlings (no subcommand) drops you into watch mode on hashmaps2. You can
also press l in watch mode, navigate to the target, and press c.
5.4 Check every exercise at once
rustlings check-all
Useful after a Rust toolchain upgrade, or after pulling new commits in a
community track. Spawns up to available_parallelism() worker threads
(default 8) and runs every exercise in parallel, then prints a colored grid
where each cell is exercise number colored by status (blue=checking,
green=done, red=pending).
Checking all exercises…
Color of exercise number: Checking - Done - Pending
1 2 3 4 5 6 7 8 9
…
One exercise pending: exercises/13_error_handling/errors4.rs
If anything is pending, exit code is 1 — handy for CI.
5.5 See the full hint for an exercise without leaving the shell
rustlings hint vecs2
Current exercise: exercises/05_vecs/vecs2.rs
Hint:
Use the `.push()` method on the vector to push new elements to it.
5.6 Open every exercise in VS Code automatically
rustlings --edit-cmd "code"
Or simply launch from inside VS Code's integrated terminal — Rustlings detects
TERM_PROGRAM=vscode and runs code automatically. The first time, accept
the recommended rust-lang.rust-analyzer extension (Rustlings adds it to
.vscode/extensions.json for you).
5.7 Use Zellij as the editor pane manager
ZELLIJ=1 rustlings
Inside an existing Zellij session, Rustlings detects $ZELLIJ and zellij
on the PATH, and opens each exercise as a new pane via zellij action edit <path>. When you advance, the previous pane is closed and a new one spawned.
5.8 Run watch mode without the file watcher
rustlings --manual-run
Use this on filesystems where file change notifications aren't reliable —
network shares, container bind mounts, some FUSE setups. After every save,
press r in the prompt to manually re-run the current exercise.
Note
Manual-run mode also surfaces the
r:runkey in the prompt; in default mode the watcher hides it because it'd be redundant.
5.9 Finish a topic and review
When all 96 exercises are done, Rustlings clears the screen and renders an ASCII Ferris-the-crab "Fe-nish line" banner along with a closing message:
+----------------------------------------------------+
| You made it to the Fe-nish line! |
+-------------------------- ------------------------+
\/
…ASCII Ferris…
We hope you enjoyed learning about the various aspects of Rust!
…
To replay any exercise after that, just rustlings run <name>.
5.10 Run a community Rustlings (third-party) track
Some authors publish their own Rustlings-compatible exercise sets. To use one:
git clone https://example.com/some-rustlings-track
cd some-rustlings-track
rustlings
Rustlings detects a local info.toml (instead of using the embedded official
list), reads it, and runs the same watch loop. Reset behavior is different in
community tracks: instead of dumping a bundled file, Rustlings runs git stash push -- <path> to undo your edits, so you must be inside a Git working tree.
Important
rustlings reset <name>in a community track requiresgit. Ifgit stash push -- <path>fails (no Git, dirty index, no working tree), Rustlings aborts with the underlying Git error. Commit or stash your unrelated work first.
6. Troubleshooting
Error: The command 'cargo metadata …' failed. Are you in the 'rustlings/' directory?
Cause: Rustlings runs cargo metadata --no-deps --format-version 1 at
startup to find the Cargo target directory, and Cargo couldn't find a
Cargo.toml. You're either in the wrong directory or your rustlings/
project doesn't have one (incomplete init).
Solution:
cdinto the directoryrustlings initcreated.- Verify
Cargo.tomlexists alongsideexercises/andsolutions/. - Run
cargo --versionto confirm Cargo is on the PATH.
Prevention: Always run rustlings from the project root (the directory
containing Cargo.toml), not from inside exercises/.
Error: Unsupported or missing terminal/TTY
Cause: Watch mode requires an interactive TTY for keyboard input. You ran
rustlings with stdout piped, redirected, or in a non-interactive context
like a CI job.
Solution: For one-shot, non-interactive checks, use the explicit subcommands:
rustlings run <name>runs a single exercise and exits.rustlings check-allruns the whole set and exits with status 0/1.
Prevention: Reserve rustlings (no subcommand) for interactive sessions.
Use the subcommands in scripts.
Error: You are trying to run Rustlings using the old method before version 6.
Cause: You're sitting inside a clone of the rust-lang/rustlings repo (a
dev/rustlings-repo.txt marker file is present) running a release-build
rustlings. The pre-v6 workflow of cloning the repo and running rustlings
inside the clone is gone.
Solution:
cdout of the repo.cargo install rustlings.rustlings initin a fresh directory.
Prevention: For learning, install via Cargo. The repo clone is only for
contributors building from source with cargo run.
Error: It looks like Rustlings is already initialized in this directory.
Cause: rustlings init found an exercises/ and a solutions/ directory
already existing in the current working directory.
Solution:
- If you want to keep your old progress:
cd <existing-dir>and runrustlings. - If you want a fresh start: move/delete
exercises/,solutions/,Cargo.toml, and.rustlings-state.txt, then re-runrustlings init.
Prevention: Pick a clean target directory before running init.
Error: A directory with the name 'rustlings' already exists in the current directory.
Cause: rustlings init always creates a subdirectory called rustlings/.
That subdirectory already exists.
Solution:
- Either remove it:
rm -rf rustlings. - Or
cd rustlingsand runrustlingsto continue from where you left off.
Error: The format version specified in the 'info.toml' file is higher than the last one supported.
Cause: You're running a community track whose info.toml declares a
format_version newer than this Rustlings supports. Currently the supported
version is 1.
Solution:
cargo install rustlingsto upgrade.- Re-run
rustlings.
Prevention: Keep Rustlings up to date via cargo install rustlings.
Error: Clippy, the official Rust linter, is missing.
Cause: rustlings init calls cargo clippy --version; Clippy didn't
respond. Some minimal Rust installs ship without it.
Solution:
rustup component add clippy.- Re-run
rustlings init.
Prevention: Install Rust via rustup (which bundles Clippy) rather than a
distro package.
Error: The automatic detection of exercise file changes failed :(
Cause: The OS file-watching API (inotify on Linux, FSEvents on macOS, ReadDirectoryChangesW on Windows) returned an error. Common on network filesystems and inside some sandboxed environments.
Solution:
- Run
rustlings --manual-runinstead. - Press
rafter each save to re-run.
Prevention: Move the project to a local filesystem if possible.
Error: A test passes locally but rustlings check-all reports it pending
Cause: check-all runs exercises in parallel using up to
thread::available_parallelism() workers (default 8 if that call fails). On
machines with low file-descriptor limits, the parallel sweep can hit
EMFILE/"too many open files." Rustlings retries failed slots
sequentially, but if the underlying issue persists, the exercise stays
pending.
Solution:
- Raise the file-descriptor limit:
ulimit -n 4096on Linux/macOS. - Re-run
rustlings check-all.
Prevention: Run on a machine with reasonable file-descriptor limits.
Issue: Wording of quiz1 is confusing (#2326)
The community has flagged the wording of quizzes/quiz1.rs; tracked upstream.
The exercise itself works — read the test in quiz1.rs carefully and trust
the assertions over the comment.
Issue: 08_enums/enum2.rs uses an array of messages instead of named variables (#2307)
A community discussion prefers named Message variables; until that lands,
the existing array-driven approach passes the tests. Your solution is correct
if the test passes.
Issue: 09_strings/strings3 README needs more links (#2338)
Open issue. The hint inside info.toml is sufficient, and the standard
library links it points to (String::trim, String::replace, the format!
macro) are still the right reading material.
7. FAQ
Q: I want to look at the official solution. Where do I find it?
After you finish an exercise in a release build, Rustlings writes the official
solution to solutions/<NN>_<topic>/<name>.rs and prints a clickable link in
the terminal:
Solution for comparison: solutions/05_vecs/vecs1.rs
If you're running a debug build (e.g. cargo run inside the Rustlings repo
itself), solution dumping is disabled to keep the dev loop fast.
Q: Can I cheat by editing .rustlings-state.txt?
You can, but the next rustlings check-all will re-verify every exercise and
revert any unsupported "done" markers to pending. You'll just slow yourself
down.
Q: How do I commit my progress with Git?
rustlings init runs git init for you (unless one is already present in
the parent tree). Commit exercises/, solutions/ (placeholders are okay),
Cargo.toml, and .rustlings-state.txt. The bundled .gitignore excludes
Cargo.lock, target/, and most of .vscode/ (but keeps
.vscode/extensions.json).
Q: How long does rustlings check-all take?
On a modern laptop, full sweep is typically 1–2 minutes from cold (first
build) and 10–20 seconds when the target directory is warm. Rustlings checks
in parallel up to available_parallelism() threads, defaulting to 8.
Q: Is there a "Done!" notification or auto-advance?
In watch mode, when an exercise passes, the screen updates with Exercise done ✓, the link to the official solution, and the prompt
When done experimenting, enter 'n' to move on to the next exercise 🦀.
Rustlings deliberately does not auto-advance — you choose when to leave
the exercise.
Q: Can I skip an exercise I don't care about?
Press l for the list view, navigate to a later exercise, press c to set
it as the current one. Or rustlings run <later-name> from the shell. Note
that you'll need to revisit skipped exercises before check-all reports the
whole set done.
Q: Why does clippy3 keep failing even when my code looks right?
clippy1, clippy2, and clippy3 set strict_clippy = true in
info.toml, which makes Rustlings run cargo clippy --bin <name> -- -D warnings (warnings = errors). Read every Clippy suggestion in the output
— each one is the actual bug.
Q: Where do the hints come from?
Each exercise's hint is a multi-line string in
rustlings-macros/info.toml, alongside its name, dir, test, and
strict_clippy fields. The macro rustlings_macros::include_files!()
embeds info.toml and every exercise/solution/README into the binary at
compile time, so a hint update requires a Rustlings rebuild.
Q: Do I need to know cargo, clippy, and rustfmt already?
You need cargo and clippy installed (Rustlings checks at init). You
don't need to know how to use them — Rustlings calls them with the right
flags. rustfmt is only needed if you author solutions for a community
track.
Q: What's the difference between the official Rustlings and a "community Rustlings"?
Official Rustlings is what cargo install rustlings ships: a fixed list of
96 exercises maintained by the Rust team, embedded in the binary. A
community Rustlings is a third-party project scaffolded by rustlings dev new that has its own info.toml next to its own exercises/ directory.
The same rustlings binary runs both.
Q: How do I get the welcome message back?
The welcome message is shown only the first time, gated by whether
.rustlings-state.txt already exists. Delete the state file (you'll lose
done markers) and run rustlings to see it again.
Q: How do I report a bug or suggest an improvement?
The CONTRIBUTING guide and the GitHub issues at github.com/rust-lang/rustlings are the right place. The community Q&A discussions are also linked from the website footer.