<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: VaultSoft</title>
    <description>The latest articles on DEV Community by VaultSoft (@vault_soft).</description>
    <link>https://dev.to/vault_soft</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3885170%2F4fbab8f1-2025-4058-ae1b-935bbc404740.png</url>
      <title>DEV Community: VaultSoft</title>
      <link>https://dev.to/vault_soft</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vault_soft"/>
    <language>en</language>
    <item>
      <title>I'm self-taught and just shipped my first real Windows app — here's everything I learned</title>
      <dc:creator>VaultSoft</dc:creator>
      <pubDate>Sat, 23 May 2026 00:03:14 +0000</pubDate>
      <link>https://dev.to/vault_soft/im-self-taught-and-just-shipped-my-first-real-windows-app-heres-everything-i-learned-29m1</link>
      <guid>https://dev.to/vault_soft/im-self-taught-and-just-shipped-my-first-real-windows-app-heres-everything-i-learned-29m1</guid>
      <description>&lt;p&gt;Six weeks ago I didn't know what PyQt6 was.&lt;/p&gt;

&lt;p&gt;Today I have two free Windows apps live, listed on &lt;br&gt;
MajorGeeks, Softpedia, SourceForge and AlternativeTo, &lt;br&gt;
with over 100 downloads across both.&lt;/p&gt;

&lt;p&gt;This is everything I learned along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who I am
&lt;/h2&gt;

&lt;p&gt;I'm Josh. Self-taught developer from the UK. No CS &lt;br&gt;
degree, no bootcamp, no formal training.&lt;/p&gt;

&lt;p&gt;I learned to code by building things I actually wanted &lt;br&gt;
to exist. That's still how I work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem I wanted to solve
&lt;/h2&gt;

&lt;p&gt;Task Manager has frustrated me for years.&lt;/p&gt;

&lt;p&gt;It tells you something is using your CPU. It won't &lt;br&gt;
tell you which core is thermal throttling, whether &lt;br&gt;
your GPU is about to overheat, or which startup &lt;br&gt;
program added 8 seconds to your boot time.&lt;/p&gt;

&lt;p&gt;I wanted one clean window showing everything. So I &lt;br&gt;
built it.&lt;/p&gt;

&lt;h2&gt;
  
  
  App 1 — PulseMonitor
&lt;/h2&gt;

&lt;p&gt;PulseMonitor is a free real-time PC health monitor &lt;br&gt;
for Windows. It shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU usage per core, clock speed and temperature&lt;/li&gt;
&lt;li&gt;GPU load, VRAM and temperature&lt;/li&gt;
&lt;li&gt;RAM usage with live history graph&lt;/li&gt;
&lt;li&gt;Network upload and download speeds&lt;/li&gt;
&lt;li&gt;Drive health across all connected drives&lt;/li&gt;
&lt;li&gt;Process manager with End Task&lt;/li&gt;
&lt;li&gt;Startup manager — add and remove startup programs&lt;/li&gt;
&lt;li&gt;Performance history graphs for 1hr, 24hr and 7 days&lt;/li&gt;
&lt;li&gt;Mini gaming overlay — press Ctrl+Shift+M&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  App 2 — SweptPC
&lt;/h2&gt;

&lt;p&gt;After shipping PulseMonitor I discovered my PC had &lt;br&gt;
14GB of junk it had been hoarding silently.&lt;/p&gt;

&lt;p&gt;SweptPC scans your system and shows exactly how much &lt;br&gt;
space each category is using before deleting anything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows temp files&lt;/li&gt;
&lt;li&gt;Chrome, Edge and Firefox cache&lt;/li&gt;
&lt;li&gt;Teams and Discord cache&lt;/li&gt;
&lt;li&gt;Windows Update leftovers&lt;/li&gt;
&lt;li&gt;Thumbnail cache&lt;/li&gt;
&lt;li&gt;Memory dumps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scan first, clean what you want. No surprises.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tech stack
&lt;/h2&gt;

&lt;p&gt;Both apps use the same stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.11&lt;/strong&gt; — language I know best&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyQt6&lt;/strong&gt; — desktop UI framework&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;psutil&lt;/strong&gt; — system metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;nvidia-smi&lt;/strong&gt; — NVIDIA GPU data via subprocess&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WMI&lt;/strong&gt; — AMD/Intel GPU and temperature data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; — performance history database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyInstaller&lt;/strong&gt; — bundles into standalone EXE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No installer needed. Just extract the ZIP and run.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hardest problems I solved
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Animation destroying CPU performance
&lt;/h3&gt;

&lt;p&gt;My first version gave every animated widget its own &lt;br&gt;
60fps QTimer.&lt;/p&gt;

&lt;p&gt;On a Ryzen 9 3900X with 24 cores that meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;24 CoreBar widgets × 60fps&lt;/li&gt;
&lt;li&gt;Plus MetricCard, CircleGauge, AnimFloat timers&lt;/li&gt;
&lt;li&gt;Total: 1,500+ repaints per second&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CPU usage hit 80%+. For a monitoring app.&lt;/p&gt;

&lt;p&gt;The fix was a singleton AnimDriver — one shared QTimer &lt;br&gt;
that all widgets register with when animating and &lt;br&gt;
deregister from when done. If nothing is animating &lt;br&gt;
the timer stops entirely.&lt;/p&gt;

&lt;p&gt;CPU dropped from 80%+ to under 5% idle.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Cross-thread Qt signals
&lt;/h3&gt;

&lt;p&gt;MonitorThread runs in a background thread. You cannot &lt;br&gt;
safely pass Python objects across Qt thread boundaries.&lt;/p&gt;

&lt;p&gt;The solution: emit a zero-argument signal from the &lt;br&gt;
thread. The UI reads from a shared snapshot instead &lt;br&gt;
of receiving data directly.&lt;/p&gt;

&lt;p&gt;Took me days to figure out. Costs 5 seconds to &lt;br&gt;
implement once you know.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Antivirus false positives
&lt;/h3&gt;

&lt;p&gt;Early builds were flagged by Bitdefender because I &lt;br&gt;
was using WinRing0 and LibreHardwareMonitor for &lt;br&gt;
temperature data.&lt;/p&gt;

&lt;p&gt;Solution: remove kernel drivers entirely. Use WMI &lt;br&gt;
and nvidia-smi only. Clean bill of health from &lt;br&gt;
every antivirus.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. PyInstaller packaging
&lt;/h3&gt;

&lt;p&gt;Getting a truly portable EXE — no Python needed, &lt;br&gt;
no dependencies, just extract and run — took several &lt;br&gt;
attempts.&lt;/p&gt;

&lt;p&gt;Key lessons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use --onedir not --onefile for faster startup&lt;/li&gt;
&lt;li&gt;Embed the icon in the spec file not the command line&lt;/li&gt;
&lt;li&gt;Test on a clean machine with no Python installed&lt;/li&gt;
&lt;li&gt;Add a crash log that writes to %APPDATA% not the 
temp directory&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What happened after launch
&lt;/h2&gt;

&lt;p&gt;I submitted both apps to software directories and &lt;br&gt;
reached out to tech bloggers and YouTubers.&lt;/p&gt;

&lt;p&gt;Results after 6 weeks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;27 SourceForge downloads&lt;/li&gt;
&lt;li&gt;50+ MajorGeeks downloads
&lt;/li&gt;
&lt;li&gt;26 Softpedia downloads&lt;/li&gt;
&lt;li&gt;124 GitHub clones by 63 unique developers&lt;/li&gt;
&lt;li&gt;4.5/5 review on Softpedia&lt;/li&gt;
&lt;li&gt;5/5 review on MajorGeeks&lt;/li&gt;
&lt;li&gt;Response from NetworkChuck's team (4.6M YouTube subs)&lt;/li&gt;
&lt;li&gt;Downloads in USA, UK, Germany and more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not life changing numbers. But real people using &lt;br&gt;
something I built from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Start marketing earlier.&lt;/strong&gt; I spent weeks perfecting &lt;br&gt;
the app before telling anyone it existed. Ship sooner, &lt;br&gt;
market sooner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Submit to directories on day one.&lt;/strong&gt; Softpedia, &lt;br&gt;
MajorGeeks and SourceForge bring consistent organic &lt;br&gt;
traffic forever. The sooner you're listed the sooner &lt;br&gt;
the downloads start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write about what you're building.&lt;/strong&gt; Every article &lt;br&gt;
brings more people than a week of social media posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Both apps are free and always will be. I'm planning &lt;br&gt;
a freemium v2.0 of PulseMonitor with a Pro tier for &lt;br&gt;
power features.&lt;/p&gt;

&lt;p&gt;VaultSoft is my indie brand. The goal is to build a &lt;br&gt;
small suite of genuinely useful free Windows tools &lt;br&gt;
and eventually make it sustainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Both apps are free and open source:&lt;/p&gt;

&lt;p&gt;🖥️ PulseMonitor — &lt;a href="https://vaultsoft.github.io/PulseMonitor" rel="noopener noreferrer"&gt;https://vaultsoft.github.io/PulseMonitor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🧹 SweptPC — &lt;a href="https://vaultsoft.github.io/SweptPC" rel="noopener noreferrer"&gt;https://vaultsoft.github.io/SweptPC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source code — &lt;a href="https://github.com/VaultSoft" rel="noopener noreferrer"&gt;https://github.com/VaultSoft&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're self-taught and thinking about shipping &lt;br&gt;
something — just start. The gap between "learning &lt;br&gt;
to code" and "shipping real software" is smaller &lt;br&gt;
than you think.&lt;/p&gt;

&lt;p&gt;What questions do you have about the build?&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>python</category>
      <category>showdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The Best Free PC Health Monitor for Windows in 2026 — PulseMonitor</title>
      <dc:creator>VaultSoft</dc:creator>
      <pubDate>Fri, 17 Apr 2026 20:48:35 +0000</pubDate>
      <link>https://dev.to/vault_soft/the-best-free-pc-health-monitor-for-windows-in-2026-pulsemonitor-7n1</link>
      <guid>https://dev.to/vault_soft/the-best-free-pc-health-monitor-for-windows-in-2026-pulsemonitor-7n1</guid>
      <description>&lt;h1&gt;
  
  
  Building PulseMonitor — what I learned making a Windows PC monitor in Python
&lt;/h1&gt;

&lt;p&gt;I'm a self-taught developer from the UK. A few weeks ago I decided to build a real Windows desktop app from scratch using Python and PyQt6.&lt;/p&gt;

&lt;p&gt;This is what I learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem I was solving
&lt;/h2&gt;

&lt;p&gt;Task Manager is fragmented. HWiNFO is powerful but overwhelming. I wanted one clean window that shows everything important about my PC in real time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech stack I chose
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.11&lt;/strong&gt; — language I know best&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyQt6&lt;/strong&gt; — surprisingly capable for desktop UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;psutil&lt;/strong&gt; — cross-platform system metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;nvidia-smi&lt;/strong&gt; — subprocess call for NVIDIA GPU data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WMI&lt;/strong&gt; — Windows Management Instrumentation for AMD/Intel GPU and temperatures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; — local performance history database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyInstaller&lt;/strong&gt; — bundles everything into a standalone EXE&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The hardest problems I solved
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Animation performance
&lt;/h3&gt;

&lt;p&gt;My first naive implementation gave every animated widget its own QTimer running at 60fps. With 24 CPU core bars on screen that was 1,500 repaints per second. CPU usage hit 80%+.&lt;/p&gt;

&lt;p&gt;The fix: a singleton _AnimDriver class — one shared QTimer that widgets register with when animating. CPU dropped from 80%+ to under 5%.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_AnimDriver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QObject&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pyqtSignal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;QTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# ~30fps
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;deregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Cross-thread Qt signals
&lt;/h3&gt;

&lt;p&gt;MonitorThread runs in a background thread and can't safely pass Python objects to the UI thread. The solution was a zero-argument signal — the thread emits a tick, the UI reads from a shared snapshot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MonitorThread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QThread&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;sig_tick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pyqtSignal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# zero args — no object crossing thread boundary
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_running&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_snapshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_collect_metrics&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sig_tick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Supporting AMD and Intel GPUs
&lt;/h3&gt;

&lt;p&gt;nvidia-smi only works for NVIDIA. For AMD and Intel I used WMI's GPU performance counters — the same data source Windows Task Manager uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;wmi&lt;/span&gt;
&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wmi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;WMI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;cimv2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Win32_PerfFormattedData_GPUPerformanceCounters_GPUEngine&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;engtype_3D&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;utilization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtilizationPercentage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Packaging with PyInstaller
&lt;/h3&gt;

&lt;p&gt;Getting a clean portable EXE with no false positive antivirus flags took several attempts. Key lessons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove any kernel-level drivers (WinRing0, LibreHardwareMonitor) — they trigger antivirus&lt;/li&gt;
&lt;li&gt;Use --onedir not --onefile for faster startup&lt;/li&gt;
&lt;li&gt;Embed the icon properly in the spec file&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;The finished app has 11 pages: Dashboard, CPU, Memory, GPU, Storage, Processes, Startup, Fans, Network, History and Settings.&lt;/p&gt;

&lt;p&gt;It uses under 5% CPU idle, runs from a ZIP with no installation, and has an auto-updater built in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;VaultCleaner — a PC cleanup tool using the same stack&lt;/li&gt;
&lt;li&gt;Freemium model once I have enough users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're interested in the source code or want to try it:&lt;br&gt;
&lt;a href="https://github.com/VaultSoft/PulseMonitor" rel="noopener noreferrer"&gt;https://github.com/VaultSoft/PulseMonitor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What would you build differently?&lt;/p&gt;

&lt;h2&gt;
  
  
  System Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OS:&lt;/strong&gt; Windows 10 or Windows 11 (64-bit)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RAM:&lt;/strong&gt; ~50 MB while running&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disk:&lt;/strong&gt; ~150 MB extracted&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GPU temp monitoring:&lt;/strong&gt; NVIDIA GPU required (AMD GPU support via &lt;a href="https://www.hwinfo.com" rel="noopener noreferrer"&gt;HWiNFO64&lt;/a&gt; with admin rights)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admin rights:&lt;/strong&gt; Optional — required only for CPU temperature on AMD Ryzen processors&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How to Run PulseMonitor
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download&lt;/strong&gt; the ZIP from the link below&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extract&lt;/strong&gt; it anywhere — Desktop, Downloads, a USB drive, wherever suits you&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run &lt;code&gt;PulseMonitor.exe&lt;/code&gt;&lt;/strong&gt; directly from the extracted folder&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional:&lt;/strong&gt; right-click the exe and send a shortcut to your Desktop or pin it to the taskbar&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. PulseMonitor is fully portable — no installer, no registry entries, no files scattered across your system. To remove it, delete the folder.&lt;/p&gt;




&lt;h2&gt;
  
  
  Download PulseMonitor — Free
&lt;/h2&gt;

&lt;p&gt;Stop guessing what your PC is doing. PulseMonitor gives you the full picture in one clean window, monitors in the background when you don't need it, and alerts you before small problems become big ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://vaultsoft.gumroad.com/l/PulseMonitor" rel="noopener noreferrer"&gt;→ Download PulseMonitor Free from Gumroad&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Compatible with Windows 10 and Windows 11. No subscription. No account required.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have a question or found a bug? Reach out at &lt;a href="mailto:vaultwall@proton.me"&gt;vaultwall@proton.me&lt;/a&gt; — feedback directly shapes future versions.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>windows</category>
      <category>software</category>
      <category>productivity</category>
      <category>python</category>
    </item>
  </channel>
</rss>
