# Rustlings User Guide

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`, and `cargo clippy` for the current exercise on every save.
- One-keystroke controls: `n` next, `h` hint, `l` list, `c` check all,
  `x` reset, `q` quit, `r` manual run.
- Built-in interactive list view with search, filters (Done / Pending), and
  per-exercise reset.
- `--edit-cmd` to auto-open exercises in your editor (auto-detects VS Code and
  Zellij).
- `rustlings dev` subcommand 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:**

```bash
cargo install rustlings
rustlings init
```

```text
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:

```bash
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 adds `rustlings` to that workspace's `members` list 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/rustlings` repository and run `rustlings` from there in a release
> build, it bails with the message *"You are trying to run Rustlings using the
> old method before version 6."* Use `cargo install rustlings` followed by
> `rustlings init` instead.

### 2.2 Install methods

=== "Cargo (recommended)"
    ```bash
    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"
    ```bash
    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"
    ```bash
    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:

```bash
rustlings init
```

`init` does the following, in order:

1. Refuses to run if a `rustlings/` directory already exists.
2. Verifies that Rust is installed by calling `cargo locate-project` and
   `cargo clippy --version`.
3. 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.
4. Writes the `exercises/` tree with all 96 exercise files, the `solutions/`
   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 the `rust-lang.rust-analyzer` extension).
5. If you're not already inside a `.git` or `.jj` repository, runs
   `git init` so your progress can be version-controlled.

```text
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 init` aborts with "It looks like Rustlings is already initialized
> in this directory" if both `exercises/` and `solutions/` already exist. To
> start over, move or delete the old directory first.

### 2.4 Verify the install

```bash
rustlings --version
```

```text
rustlings 6.5.0
```

```bash
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:

```bash
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_PROGRAM`
> environment variable and prefers `code` (or `codium`) if either is on the PATH.
> `--edit-cmd` is **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:

1. If `TERM_PROGRAM=vscode`: try `code`, then `codium`. If either responds to
   `--version`, use it.
2. Otherwise, if you passed `--edit-cmd "PROGRAM …"`: parse it with shell-like
   splitting and use that.
3. Otherwise, if `$ZELLIJ` is set and `zellij --version` succeeds: open each
   exercise as a new Zellij pane (and close the previous pane on switch).
4. Otherwise: do not open an editor.

> [!TIP]
> The `--edit-cmd` value is parsed with a shell-style splitter, so quoted
> arguments work as expected: `--edit-cmd "subl --new-window"` becomes
> `subl --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:

```text
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:

```bash
rustlings
```

```text
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. |

```bash
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`, and `reset` all update `.rustlings-state.txt` to record which
> exercise you're now "on" — they're not pure read commands. `check-all` writes
> 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 (`l` then `c`).

### 4.7 What "done" means

A pending exercise becomes **done** when:

1. `cargo build --bin <exercise_name>` exits 0.
2. If `test = true` in `info.toml` (the default), `cargo test --bin <name>`
   passes.
3. `cargo clippy --bin <name> --profile test` passes. If the exercise sets
   `strict_clippy = true` (e.g. `clippy1`/`clippy2`/`clippy3`), Rustlings
   appends `-- -D warnings` so any Clippy warning fails the check.
4. `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

```bash
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

```bash
rustlings reset variables3
```

```text
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

```bash
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

```bash
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).

```text
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

```bash
rustlings hint vecs2
```

```text
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

```bash
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

```bash
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

```bash
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:run` key 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:

```text
+----------------------------------------------------+
|          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:

```bash
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 requires `git`. If `git 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**:
1. `cd` into the directory `rustlings init` created.
2. Verify `Cargo.toml` exists alongside `exercises/` and `solutions/`.
3. Run `cargo --version` to 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:
1. `rustlings run <name>` runs a single exercise and exits.
2. `rustlings check-all` runs 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**:
1. `cd` out of the repo.
2. `cargo install rustlings`.
3. `rustlings init` in 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**:
1. If you want to keep your old progress: `cd <existing-dir>` and run
   `rustlings`.
2. If you want a fresh start: move/delete `exercises/`, `solutions/`,
   `Cargo.toml`, and `.rustlings-state.txt`, then re-run `rustlings 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**:
1. Either remove it: `rm -rf rustlings`.
2. Or `cd rustlings` and run `rustlings` to 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**:
1. `cargo install rustlings` to upgrade.
2. 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**:
1. `rustup component add clippy`.
2. 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**:
1. Run `rustlings --manual-run` instead.
2. Press `r` after 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**:
1. Raise the file-descriptor limit: `ulimit -n 4096` on Linux/macOS.
2. 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:

```text
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](https://github.com/rust-lang/rustlings) are
the right place. The community Q&A discussions are also linked from the
website footer.

---

_Generated April 2026 from rust-lang/rustlings at b730882. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
