6 AM. Monday. Couldn't sleep.
Not the inspirational "I'm so motivated" kind of can't sleep. More like my brain decided to start compiling the entire weekly sprint at 5:47 AM and wouldn't shut up until I opened VS Code.
By 11 AM I had shipped four things that weren't even on this week's list. By Friday, the actual plan got done too. Some of it. Enough of it. This is the story of both.
PC Workman is at v1.7.2 now. If you're new here: it's an open-source AI-powered system monitor I've been building solo for 800+ hours. Python, PyQt5, WMI, a custom AI diagnostic engine called hck_GPT, and a lot of late nights after Żabka shifts. This week was one of the heaviest since I started.
Let's cut it open.
1. hck_GPT Time Badges — The Small Feature That Took Months to Actually Do
This one has been haunting me since Monday Grind Blueprint #1.
The problem was simple: hck_GPT would tell you things like "Chrome ate 6GB RAM recently." When recently? An hour ago? Yesterday? During that Windows update at 3 AM?
No timestamp. No context. Just "recently."
I kept pushing it back. "Next sprint." "After the UI redesign." "When I have time." Classic.
Monday morning, 6:23 AM, I just... did it.
The Interesting Part
hck_GPT's chat panel is a tk.Text widget. Most people use Text widgets for plain text. Type stuff in, maybe color some words, done.
But tkinter has this thing called window_create() that lets you embed any widget inside the text flow. Not on top of it. Not floating above it. Inside it, like it's just another character.
So instead of prepending "[08:52]" as plain text (boring, hard to style, breaks if the message wraps weird), I built a tiny canvas badge:
# panel.py
def _make_time_badge(self):
badge = tk.Canvas(
self.log,
width=62, height=14,
bg=THEME["bg_panel"],
highlightthickness=0,
)
badge.create_rectangle(0, 0, 62, 14, fill="#0d0f14", outline="")
badge.create_rectangle(0, 0, 3, 14, fill="#dc2626", outline="") # left red bar
badge.create_rectangle(59, 0, 62, 14, fill="#dc2626", outline="") # right red bar
badge.create_line(3, 0, 3, 14, fill="#374151")
badge.create_text(31, 7, text=time.strftime("%H:%M"),
fill="#94a3b8", font=("Consolas", 7, "bold"))
return badge
Dark background, red accent bars on each side, Consolas font, 7pt bold. It looks like a tiny terminal badge sitting in the chat.
Then in add_message():
def add_message(self, msg):
self.log.config(state="normal")
if msg.startswith("hck_GPT:"):
badge = self._make_time_badge()
self.log.window_create("end", window=badge, padx=2, pady=1)
self.log.insert("end", " ")
self.log.insert("end", msg + "\n")
self.log.config(state="disabled")
That window_create("end", window=badge) is the whole trick. The canvas lives inside the text flow, scrolls with everything else, and costs almost nothing performance-wise.
Small feature. One morning. Months overdue. Now every hck_GPT message says when it happened. 08:52, not "a while ago."
2. Process Library — From "Unknown" to "Oh, That's What You Are"
This one started in Blueprint #1 too. The idea was simple: when PC Workman mentions a process, you should know what it is without opening Google.
process_library.json already had ~60 entries. But real usage kept surfacing gaps. hck_GPT would say "WmiPrvSE.exe is using 34% CPU" and the tooltip showed... nothing. Unknown process.
This week I added 8 more entries, specifically the ones that kept showing up as unknowns during actual sessions:
-
wmiprvse.exe— WMI Provider Host. Every monitoring tool talks to this. Including PC Workman itself. -
msmpeng.exe— Windows Defender's scan engine. The one that randomly spikes CPU at 2 AM. -
registry— NT kernel process, no .exe extension. Easy to miss entirely. -
claude.exe— Yes, the Claude desktop app. I use it enough that it shows up in Top 5. -
hitman.exe,hitman2.exe,hitman3.exe— HITMAN trilogy. Each one with different VRAM profiles. -
datatransfer.exe— Connected Devices Platform sync. Nobody knows what this is until it's eating RAM.
Each entry follows the same schema:
{
"msmpeng.exe": {
"name": "Windows Defender Antimalware Service",
"vendor": "Microsoft",
"category": "Security",
"description": "Core scan engine for Windows Defender. Periodic CPU spikes are normal during scheduled scans.",
"power_usage": "medium-high during scans",
"safety": "safe — do not kill",
"typical_cpu": "0-5% idle, 15-40% during scan",
"typical_ram": "150-300 MB"
}
}
Clean, queryable, and every field actually means something.
Tooltips Everywhere, Not Just in Chat
Before this week, the hover tooltip only worked inside hck_GPT's chat panel. If a process showed up in the main dashboard Top 5 panels, you were on your own.
Fixed that. But it wasn't as simple as "just add a tooltip."
The Top 5 panels update every render tick. Process names change constantly. If you capture the process name at widget creation time, the tooltip will show stale data within seconds.
Solution: store the process name in a mutable dict that gets updated every tick:
# main_window_expanded.py
widget_data = {
"row": row, "name": name_lbl,
"cpu_bar": cpu_bar, "cpu_val": cpu_val,
"ram_bar": ram_bar, "ram_val": ram_val,
"proc_name": "", # updated every render tick
}
if self._process_tooltip:
def _enter(e, wd=widget_data):
pn = wd["proc_name"]
if pn:
tt = _proc_lib.format_tooltip_text(pn)
if tt:
self._process_tooltip.show(e, pn, tt)
def _leave(e):
self._process_tooltip.hide()
name_lbl.bind("<Enter>", _enter)
row.bind("<Enter>", _enter) # whole row = bigger hit area
Then in the render loop, one line:
widget_data["proc_name"] = display_name
The wd=widget_data in the lambda captures by reference, not by value. So when the render loop updates proc_name, the tooltip reads the fresh name. No timer, no polling, no auto-hide. Mouse in = tooltip. Mouse out = gone. User reads at their own pace.
3. First Setup & Drivers — Building a Driver Booster From Scratch
This was the big one. Not planned for Monday. Not planned for this week at all. Just... happened.
I opened Driver Booster, IObit's tool, the one everyone installs when they get a new PC. And I thought: what does it actually do?
It reads your installed drivers. Checks versions. Shows you what's outdated. That's it. The "boost" part is just a download link.
I can do that. Without internet. Without admin rights. Without a third-party API.
Reading Drivers From the Windows Registry
Windows stores driver metadata in the registry under SYSTEM\CurrentControlSet\Control\Class\{GUID}. Each device class (GPU, Audio, Network, USB) has its own GUID. You open the key, enumerate subkeys, and read three values: DriverDesc, DriverVersion, DriverDate.
def _read_class_driver(guid):
key_path = fr"SYSTEM\CurrentControlSet\Control\Class\{guid}"
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path) as cls:
for i in range(min(winreg.QueryInfoKey(cls)[0], 24)):
sn = winreg.EnumKey(cls, i)
if not sn[:4].isdigit():
continue
with winreg.OpenKey(cls, sn) as dev:
desc = winreg.QueryValueEx(dev, "DriverDesc")[0]
if any(kw in desc.lower() for kw in _SKIP):
continue
ver = winreg.QueryValueEx(dev, "DriverVersion")[0]
drv_date = winreg.QueryValueEx(dev, "DriverDate")[0]
return {"name": desc, "version": ver, "date": drv_date}
No internet call. No admin popup. Just winreg.OpenKey on HKEY_LOCAL_MACHINE. Windows lets you read this without elevation. You just can't write to it.
The _SKIP list filters out virtual network adapters (Hyper-V, VPN clients, Docker). Without it, the page fills up with phantom devices nobody cares about.
The Date Format Problem
Driver dates come from the registry as strings. Sounds simple. Except Windows uses at least three different formats depending on... I honestly don't know what. Device class? Driver manufacturer? Phase of the moon?
MM-DD-YYYYYYYY-MM-DDYYYYMMDD
The _driver_age_days() function tries all three. If none work, it returns None and the health score takes a small penalty for "unknown age" instead of crashing.
Health Score — Computed, Not Faked
Driver Booster shows you a big number. "Your system health: 73%." Where does that number come from? Nobody knows.
Mine is transparent:
def _compute_score(drivers, startup_count):
score = 100
for d in drivers:
days = _driver_age_days(d.get("date", ""))
if days is None: score -= 6
elif days >= 365: score -= 20
elif days >= 180: score -= 9
if startup_count > 12: score -= 15
elif startup_count > 8: score -= 8
return max(10, min(100, score))
Driver older than a year? Minus 20. Unknown date? Minus 6. Too many startup programs? Penalty. The formula is right there. You can read it, disagree with it, and fork it.
The score renders as an arc gauge drawn with canvas.create_arc(). 270° sweep, green→amber→red based on value. Nothing fancy. Nothing hidden.
Quick Actions
The page also has a Quick Actions panel. One-click access to Device Manager, Services, System Info, and MSConfig. These are just subprocess.Popen calls to devmgmt.msc, services.msc, msinfo32.exe, and msconfig.exe.
Sounds trivial. But I deep-researched what other tools in this space offer for first-time PC setup, and most of them... don't offer this. They focus on the driver scan and ignore the fact that someone setting up a new machine probably also wants quick access to system tools.
The Architecture Bit
The page itself is ~370 lines (ui/pages/first_setup_drivers.py). UI builds immediately — instant render, no loading screen. The driver scan runs in a threading.Thread and posts results back to the main thread via sf.after(0, lambda: _apply(...)).
Startup programs come from two registry hives:
paths = [
(winreg.HKEY_CURRENT_USER,
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "User"),
(winreg.HKEY_LOCAL_MACHINE,
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "System"),
]
User-level and system-level. Both matter.
There's also a setup checklist that persists to data/cache/setup_checklist.json. Toggle items on click, progress bar updates live. Small thing, but it makes the page feel like a tool you come back to, not a one-time scan.
4. The Bug Nobody Noticed
The "First Setup & Drivers" button in yourpc_page.py was routing to the wrong page.
Click "First Setup & Drivers" → opens the optimization wizard. Not the setup page. The optimization wizard worked fine, so nobody reported it. Including me. I was clicking through the sidebar, not through the yourpc page buttons.
# Before (wrong):
btn.config(command=lambda: self._nav_to("optimization_wizard"))
# After (correct):
btn.config(command=lambda: self._nav_to("first_setup"))
One line. Probably been wrong since the button was created. The sidebar badge now also shows the live checklist state (e.g., "3/6 done"), loaded from JSON on every render.
5. The Scars
Every week has them. Here are this week's:
The scroll_frame width trap. When you embed a tk.Frame inside a tk.Canvas via create_window, the frame doesn't automatically fill the canvas width. Your entire page content renders in a narrow strip on the left. All your fill="x" packs are filling a 1px-wide frame and you don't know why.
Fix:
win_id = wrap.create_window((0, 0), window=sf, anchor="nw")
wrap.bind("<Configure>",
lambda e: wrap.itemconfig(win_id, width=e.width - 2))
One binding. Took me 10 minutes of staring at the screen to figure out. If you're doing scrollable frames in tkinter — bookmark this.
The dead-code ghost. Earlier in the project, I deleted a _build_yourpc_page_OLD_REMOVED function. But a nested function inside it (_build_sensors_page_placeholder) survived the edit because the first attempt only replaced the function header, leaving the body orphaned. 40 lines of dead code sitting there, not breaking anything, not doing anything. Just vibing. Had to go back and kill it properly.
The write tool rejection. After writing ~370 lines for the new Setup & Drivers page, the file write failed because a linter touched the file between read and write. Had to re-read and re-issue the entire write. Not a code problem. Workflow problem. Lesson: on large files, write in one shot without anything touching the file in between.
What's Coming — The Week Plan (v1.7.2 → v1.7.4)
This was the Monday Grind Blueprint #3 plan. Here's what's on the board:
Dashboard Button Redesign
The buttons work. They look like 2015. PIL-generated gradients, canvas caching for button states, CSS-like hover system with state tracking. Zero FPS impact — gradients are pre-rendered once on init, then reused. The purple color scheme stays.
System Cleanup Utilities
Temp files cleaner (%temp%, Windows\Temp, Prefetch, browser caches). Log file manager with archive-before-delete. Startup optimizer with enable/disable toggles and impact ratings (High/Medium/Low).
One rule that won't change: nothing gets deleted without explicit user confirmation. No "we cleaned 2.3 GB!" surprises. You see the size, you confirm, then it happens. Detailed log of everything that was removed.
Complete "My PC" Health Tab
Right now: pretty placeholder. This week: real hardware detection via WMI queries (Win32_Processor, Win32_VideoController), temperature warnings (>85°C yellow, >90°C red), uptime stats, and JSON export for the health report.
TURBO — Auto RAM Flush
The one I'm most curious about. Advanced SystemCare and CCleaner claim 300-800 MB freed. What are they actually doing?
Researching three approaches:
-
EmptyStandbyList.exe(Sysinternals) — clears standby list - Native Python via
ctypes(SetSystemFileCacheSize) — direct kernel call - Gentle per-process working set flush — least aggressive
Trigger: RAM >75% for >30 seconds. Measure before/after. Show the user exactly how much was freed. Toggle on/off, threshold adjustable.
If it works reliably without causing instability, it becomes the first real TURBO feature in PC Workman.
The Numbers
- Version: 1.7.2
- Hours logged: 800+
- GitHub stars: 23
- Downloads: ~100
- Roadmap issues: 17 tracked, 4 done, 7 in review
- Retail shifts between coding sessions: 5 per week
- Microsoft Store: Q4 2026
- Sleep this week: not enough
The Bigger Picture
I started PC Workman on a laptop hitting 94°C during compilation. Got fired three days before Christmas. Moved back to Poland. Started working at Żabka to pay bills while I keep building.
This isn't a weekend project. It's 800+ hours of "I refuse to let another project die at 70%."
v1.7.2 is the most feature-complete version yet. The First Setup & Drivers page alone competes with tools people pay for. The process library makes hck_GPT actually useful instead of just impressive. The timestamps make diagnostics real instead of vague.
And we're not even at v2.0 yet.
If you're building something solo, between shifts, between life — I see you. Keep shipping. Even the messy weeks count.
Star the repo if you want to follow along: github.com/HuckleR2003/PC_Workman_HCK
All my links: linktr.ee/marcin_firmuga
Monday Grind Blueprint sets the bar.
Wednesday Code Autopsy cuts it open.
Friday Shipped & Scarred shows what actually happened.
See you Wednesday.
About the Author
I'm Marcin Firmuga. Solo developer and founder of HCK_Labs. Building PC Workman — an open-source AI-powered system monitor — from scratch, publicly, honestly. Before this: game translations, IT technician internships, warehouse shifts in the Netherlands, and twelve failed projects I never finished. This one stuck.




Top comments (0)