diff --git a/CHANGELOG.md b/CHANGELOG.md
index faef829d..85ae6b48 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,7 @@
All notable changes to the Lager platform are documented here. For detailed release notes, see [docs.lagerdata.com](https://docs.lagerdata.com).
-## [Unreleased]
+## [0.31.8] - 2026-07-13
`lager uninstall` now actually removes what the modern `lager install` creates.
The `--all` cleanup had not kept pace with several releases of install changes,
diff --git a/cli/__init__.py b/cli/__init__.py
index 2e9c38b1..2af5f4bd 100644
--- a/cli/__init__.py
+++ b/cli/__init__.py
@@ -7,4 +7,4 @@
A Command Line Interface for Lager Data
"""
-__version__ = '0.31.7'
+__version__ = '0.31.8'
diff --git a/docs/docs.json b/docs/docs.json
index 23c07205..0135d573 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -211,6 +211,7 @@
{
"group": "Version History",
"pages": [
+ "source/release-notes/v0.31.8",
"source/release-notes/v0.31.7",
"source/release-notes/v0.31.6",
"source/release-notes/v0.31.5",
diff --git a/docs/source/release-notes/v0.31.8.mdx b/docs/source/release-notes/v0.31.8.mdx
new file mode 100644
index 00000000..9d2995f3
--- /dev/null
+++ b/docs/source/release-notes/v0.31.8.mdx
@@ -0,0 +1,30 @@
+---
+title: "Version 0.31.8"
+description: "July 13, 2026"
+---
+
+## Bug Fixes
+
+- **`lager uninstall --all` removes the artifacts today's install creates.** The old udev glob never matched the shipped `99-instrument.rules`, and the usbtmc modprobe blacklist, the `lager-box-config` sudoers file, the firewall helper script, the lager sysctl config, and the `lager` group were never removed at all. The removal list is now a single specification shared by the confirmation listing, `--dry-run`, the removal session, and the unit tests, so it cannot silently drift from what install creates. Deliberately left in place: docker itself (packages, buildx, the daemon.json DNS entry) and pip/apt packages.
+- **Privileged removals actually happen (and report honestly) on Lager Boxes without passwordless sudo.** Each sudo step used to fail silently and print "done" — a plain uninstall could leave `/etc/lager` behind while claiming success. All privileged steps now run in one interactive session (at most one sudo password prompt) with per-step results, and failures are summarized instead of hidden.
+- **`--all` removes this machine's key from the Lager Box's `authorized_keys`.** Previously the "deploy keys" cleanup deleted box-side private keys that modern installs never create, while the actual access grant survived. The output calls out that the next SSH connection will require a password.
+- **`--keep-config` is honored together with `--all`**, preserving `/etc/lager` (saved nets) through an otherwise complete removal.
+- **`--dry-run` inspects the real artifact list** and no longer reports `/etc/lager` as "(not found)" on Lager Boxes where reading it required sudo.
+
+## Installation
+
+To install this version:
+
+```bash
+pip install lager-cli==0.31.8
+```
+
+To upgrade from a previous version:
+
+```bash
+pip install --upgrade lager-cli
+```
+
+## Resources
+
+[View Release on PyPI](https://pypi.org/project/lager-cli/0.31.8/)