diff --git a/CHANGELOG.md b/CHANGELOG.md
index cc5dad0..55c4a41 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,13 @@ All notable changes to RigDoctor are recorded here. Format follows
(`MAJOR.MINOR.PATCH`, pre-1.0). `__version__` and `pyproject.toml` must match the git
release tag (so the auto-updater, D18, can compare versions).
+## [0.18.0] - 2026-05-22
+### Added
+- **Global recording indicator.** While a capture is running, the sidebar shows a red
+ **● Recording** badge on every page — with the **game** being captured and the live sample
+ count (and a GPU-lost flag if seen). It polls the recorder, so it reflects captures started
+ any way: manual `record`, a guided diagnostic, or the Steam launch wrapper.
+
## [0.17.0] - 2026-05-22
### Added
- **Inventory page is back in the GUI** (it was removed in 0.7.2 in favor of the CLI). Sidebar
diff --git a/pyproject.toml b/pyproject.toml
index 116afd4..ad9588b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "rigdoctor"
-version = "0.17.0"
+version = "0.18.0"
description = "Modular hardware monitoring & crash diagnostics for Linux gamers."
readme = "README.md"
requires-python = ">=3.11"
diff --git a/src/rigdoctor/__init__.py b/src/rigdoctor/__init__.py
index ae719c7..02629fc 100644
--- a/src/rigdoctor/__init__.py
+++ b/src/rigdoctor/__init__.py
@@ -1,3 +1,3 @@
"""RigDoctor — modular hardware monitoring & crash diagnostics for Linux gamers."""
-__version__ = "0.17.0"
+__version__ = "0.18.0"
diff --git a/src/rigdoctor/gui/main_window.py b/src/rigdoctor/gui/main_window.py
index bc99f3d..ee8afbc 100644
--- a/src/rigdoctor/gui/main_window.py
+++ b/src/rigdoctor/gui/main_window.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+import html
import os
import sys
import threading
@@ -36,7 +37,7 @@ from .notifications_page import NotificationsPage
from .recorder_page import RecorderPage
from .setup_page import SetupPage
from .share_page import SharePage
-from .theme import ACCENT, GOOD, MUTED
+from .theme import ACCENT, CRIT, GOOD, MUTED, TEXT
from .worker import SamplerWorker
_NAV_ITEMS = ["Dashboard", "Logs", "Health", "Games", "Environment", "Inventory", "Setup", "Notifications", "Share"]
@@ -127,6 +128,14 @@ class MainWindow(QMainWindow):
self._update_timer.timeout.connect(self._start_update_check)
self._update_timer.start()
+ # Reflect any capture (manual, diagnostic, or the Steam wrapper) in the sidebar on
+ # every page, so it's always clear when RigDoctor is recording and for which game.
+ self._rec_timer = QTimer(self)
+ self._rec_timer.setInterval(1500)
+ self._rec_timer.timeout.connect(self._update_recording)
+ self._rec_timer.start()
+ self._update_recording()
+
def _build_sidebar(self) -> QFrame:
bar = QFrame()
bar.setObjectName("Sidebar")
@@ -141,6 +150,17 @@ class MainWindow(QMainWindow):
subtitle.setObjectName("AppSubtitle")
v.addWidget(title)
v.addWidget(subtitle)
+
+ # Global recording indicator — visible on every page while a capture runs.
+ self._rec_indicator = QLabel()
+ self._rec_indicator.setWordWrap(True)
+ self._rec_indicator.setTextFormat(Qt.TextFormat.RichText)
+ self._rec_indicator.setStyleSheet(
+ f"background: #241316; border: 1px solid {CRIT}; border-radius: 8px; padding: 8px 10px;"
+ )
+ self._rec_indicator.hide()
+ v.addSpacing(12)
+ v.addWidget(self._rec_indicator)
v.addSpacing(18)
group = QButtonGroup(self)
@@ -242,6 +262,23 @@ class MainWindow(QMainWindow):
self.health_page._run()
self.inventory_page._run()
+ def _update_recording(self) -> None:
+ from .core import diagnostic
+
+ status = diagnostic.active()
+ if not status:
+ self._rec_indicator.hide()
+ return
+ game = status.get("game")
+ samples = status.get("samples", 0)
+ lost = " · GPU-lost" if status.get("gpu_lost") else ""
+ lines = [f"● Recording"]
+ if game:
+ lines.append(f"{html.escape(str(game))}")
+ lines.append(f"{samples} samples{lost}")
+ self._rec_indicator.setText("
".join(lines))
+ self._rec_indicator.show()
+
def _set_games_badge(self, count: int) -> None:
btn = self._nav_buttons.get("Games")
if btn is not None: