diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2c14e7d..d4d6440 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,38 @@
+<a name="5.5.0"></a>
+## 5.5.0 (2023-05-17)
+
+#### Added
+
+- `strings2`: Added a reference to the book chapter for reference conversion
+- `lifetimes`: Added a link to the lifetimekata project
+- Added a new `tests4` exercises, which teaches about testing for panics
+- Added a `!` prefix command to watch mode that runs an external command
+- Added a `--success-hints` option to watch mode that shows hints on exercise success
+
+#### Changed
+
+- `vecs2`: Renamed iterator variable bindings for clarify
+- `lifetimes`: Changed order of book references
+- `hashmaps2`: Clarified instructions in the todo block
+- Moved lifetime exercises before test exercises (via the recommended book ordering)
+- `options2`: Improved tests for layering options
+- `modules2`: Added more information to the hint
+
+#### Fixed
+
+- `errors2`: Corrected a comment wording
+- `iterators2`: Fixed a spelling mistake in the hint text
+- `variables`: Wrapped the mut keyword with backticks for readability
+- `move_semantics2`: Removed references to line numbers
+- `cow1`: Clarified the `owned_no_mutation` comments
+- `options3`: Changed exercise to panic when no match is found
+- `rustlings lsp` now generates absolute paths, which should fix VSCode `rust-analyzer` usage on Windows
+
+#### Housekeeping
+
+- Added a markdown linter to run on GitHub actions
+- Split quick installation section into two code blocks
+
 <a name="5.4.1"></a>
 ## 5.4.1 (2023-03-10)
 
diff --git a/Cargo.lock b/Cargo.lock
index 192a4ac..16f771c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -441,7 +441,7 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
 
 [[package]]
 name = "rustlings"
-version = "5.4.1"
+version = "5.5.0"
 dependencies = [
  "argh",
  "assert_cmd",
diff --git a/Cargo.toml b/Cargo.toml
index d22816c..e603bbf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "rustlings"
-version = "5.4.1"
+version = "5.5.0"
 authors = [
   "Liv <mokou@fastmail.com>",
   "Carol (Nichols || Goulding) <carol.nichols@gmail.com>",
diff --git a/README.md b/README.md
index be470fd..92daa33 100644
--- a/README.md
+++ b/README.md
@@ -36,8 +36,8 @@ This will install Rustlings and give you access to the `rustlings` command. Run
 Basically: Clone the repository at the latest tag, finally run `nix develop` or `nix-shell`.
 
 ```bash
-# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.4.1)
-git clone -b 5.4.1 --depth 1 https://github.com/rust-lang/rustlings
+# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.5.0)
+git clone -b 5.5.0 --depth 1 https://github.com/rust-lang/rustlings
 cd rustlings
 # if nix version > 2.3
 nix develop
@@ -74,8 +74,8 @@ If you get a permission denied message, you might have to exclude the directory
 Basically: Clone the repository at the latest tag, run `cargo install --path .`.
 
 ```bash
-# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.4.1)
-git clone -b 5.4.1 --depth 1 https://github.com/rust-lang/rustlings
+# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.5.0)
+git clone -b 5.5.0 --depth 1 https://github.com/rust-lang/rustlings
 cd rustlings
 cargo install --force --path .
 ```
diff --git a/flake.nix b/flake.nix
index 5815a92..c874919 100644
--- a/flake.nix
+++ b/flake.nix
@@ -22,7 +22,7 @@
         rustlings =
           pkgs.rustPlatform.buildRustPackage {
             name = "rustlings";
-            version = "5.4.1";
+            version = "5.5.0";
 
             buildInputs = cargoBuildInputs;
 
diff --git a/src/main.rs b/src/main.rs
index 74e8161..feb673d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -26,7 +26,7 @@ mod run;
 mod verify;
 
 // In sync with crate version
-const VERSION: &str = "5.4.1";
+const VERSION: &str = "5.5.0";
 
 #[derive(FromArgs, PartialEq, Debug)]
 /// Rustlings is a collection of small exercises to get you used to writing and reading Rust code
@@ -352,7 +352,11 @@ enum WatchStatus {
     Unfinished,
 }
 
-fn watch(exercises: &[Exercise], verbose: bool, success_hints: bool) -> notify::Result<WatchStatus> {
+fn watch(
+    exercises: &[Exercise],
+    verbose: bool,
+    success_hints: bool,
+) -> notify::Result<WatchStatus> {
     /* Clears the terminal with an ANSI escape code.
     Works in UNIX and newer Windows terminals. */
     fn clear_screen() {
@@ -368,7 +372,12 @@ fn watch(exercises: &[Exercise], verbose: bool, success_hints: bool) -> notify::
     clear_screen();
 
     let to_owned_hint = |t: &Exercise| t.hint.to_owned();
-    let failed_exercise_hint = match verify(exercises.iter(), (0, exercises.len()), verbose, success_hints) {
+    let failed_exercise_hint = match verify(
+        exercises.iter(),
+        (0, exercises.len()),
+        verbose,
+        success_hints,
+    ) {
         Ok(_) => return Ok(WatchStatus::Finished),
         Err(exercise) => Arc::new(Mutex::new(Some(to_owned_hint(exercise)))),
     };
@@ -390,7 +399,12 @@ fn watch(exercises: &[Exercise], verbose: bool, success_hints: bool) -> notify::
                             );
                         let num_done = exercises.iter().filter(|e| e.looks_done()).count();
                         clear_screen();
-                        match verify(pending_exercises, (num_done, exercises.len()), verbose, success_hints) {
+                        match verify(
+                            pending_exercises,
+                            (num_done, exercises.len()),
+                            verbose,
+                            success_hints,
+                        ) {
                             Ok(_) => return Ok(WatchStatus::Finished),
                             Err(exercise) => {
                                 let mut failed_exercise_hint = failed_exercise_hint.lock().unwrap();