<?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: milton rojas</title>
    <description>The latest articles on DEV Community by milton rojas (@milton_rojas_6bdc219110e9).</description>
    <link>https://dev.to/milton_rojas_6bdc219110e9</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3939212%2F4ec06d96-bfe4-4760-b0c0-83dc29e25b19.png</url>
      <title>DEV Community: milton rojas</title>
      <link>https://dev.to/milton_rojas_6bdc219110e9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/milton_rojas_6bdc219110e9"/>
    <language>en</language>
    <item>
      <title>Your photos are quietly leaking your home address — the byte-level reason, and a fix</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Tue, 02 Jun 2026 22:54:47 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/your-photos-are-quietly-leaking-your-home-address-the-byte-level-reason-and-a-fix-3m5k</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/your-photos-are-quietly-leaking-your-home-address-the-byte-level-reason-and-a-fix-3m5k</guid>
      <description>&lt;p&gt;Last week I dropped a photo from my phone into a hex editor, scrolled about 30 bytes in, and found the exact latitude and longitude of the room I was standing in. Six decimal places. Accurate to a few meters.&lt;/p&gt;

&lt;p&gt;I had not tagged a location. I had not posted anything. The camera just &lt;em&gt;wrote it down&lt;/em&gt;, the way it does for every photo, on every phone, by default.&lt;/p&gt;

&lt;p&gt;Here is how that works, why "just crop it" does nothing, and how to actually remove it — including a tiny tool I built that does it entirely in your browser with zero uploads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the data hides
&lt;/h2&gt;

&lt;p&gt;A JPEG is not one blob. It is a stream of &lt;strong&gt;segments&lt;/strong&gt;, each introduced by a marker byte &lt;code&gt;0xFF&lt;/code&gt; followed by a type byte. The image you see lives in the scan data after the &lt;code&gt;Start of Scan&lt;/code&gt; marker (&lt;code&gt;0xFFDA&lt;/code&gt;). Everything before it is metadata.&lt;/p&gt;

&lt;p&gt;The interesting one is &lt;strong&gt;APP1&lt;/strong&gt; (&lt;code&gt;0xFFE1&lt;/code&gt;). It holds an Exif block, which is really a little-endian or big-endian TIFF structure with its own image file directories (IFDs). Walk the IFD entries and you get tags like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;0x010F&lt;/code&gt; Make, &lt;code&gt;0x0110&lt;/code&gt; Model — your exact camera/phone&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0x9003&lt;/code&gt; DateTimeOriginal — when, in your local time&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0xA434&lt;/code&gt; LensModel — even the lens&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0x8825&lt;/code&gt; — a pointer to the &lt;strong&gt;GPS IFD&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow that GPS pointer and you find &lt;code&gt;GPSLatitude&lt;/code&gt; and &lt;code&gt;GPSLongitude&lt;/code&gt;, each stored as three RATIONAL values — degrees, minutes, seconds — plus a &lt;code&gt;GPSLatitudeRef&lt;/code&gt; of &lt;code&gt;N&lt;/code&gt;/&lt;code&gt;S&lt;/code&gt; and &lt;code&gt;GPSLongitudeRef&lt;/code&gt; of &lt;code&gt;E&lt;/code&gt;/&lt;code&gt;W&lt;/code&gt;. Convert it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;deg&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;sec&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;S&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;W&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's your home, rendered as a number, riding inside a picture of your cat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why cropping and editing don't save you
&lt;/h2&gt;

&lt;p&gt;This is the part most people get wrong. The metadata is &lt;strong&gt;structurally separate&lt;/strong&gt; from the pixels. When you crop, rotate, or draw on a photo in most apps, you change the scan data — the APP1 block comes along untouched. Plenty of "edited" screenshots online still carry the original capture's GPS.&lt;/p&gt;

&lt;p&gt;Worse: some workflows that &lt;em&gt;do&lt;/em&gt; strip metadata do it by &lt;strong&gt;re-encoding&lt;/strong&gt; the whole image through a canvas. That drops the metadata, yes — but it also re-compresses your JPEG, throwing away real image quality every time. You traded your privacy fix for visible artifacts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The clean way: surgical removal
&lt;/h2&gt;

&lt;p&gt;You don't need to re-encode anything. You walk the segment list and copy every byte &lt;strong&gt;except&lt;/strong&gt; the metadata segments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// keep everything; drop APP1(Exif/XMP), APP13(IPTC), APP14(Adobe), COM&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mh"&gt;0xDA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// start of scan: image data follows&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;    &lt;span class="c1"&gt;// segment length&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isMeta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mh"&gt;0xE1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mh"&gt;0xED&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
                 &lt;span class="nx"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mh"&gt;0xEE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mh"&gt;0xFE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isMeta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;keepRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// then append from the scan marker to EOF unchanged&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is byte-for-byte identical in the parts that matter. The pixels are never touched. PNG works the same way — its metadata lives in &lt;code&gt;tEXt&lt;/code&gt;, &lt;code&gt;zTXt&lt;/code&gt;, &lt;code&gt;iTXt&lt;/code&gt;, &lt;code&gt;tIME&lt;/code&gt;, and &lt;code&gt;eXIf&lt;/code&gt; chunks that you simply don't copy forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  A tool that does exactly this, locally
&lt;/h2&gt;

&lt;p&gt;I packaged the parser and the lossless stripper into a single static page. Drop photos in, it shows you everything they're leaking — GPS on a map link, device, lens, timestamps, editing trail — and gives you a clean copy with the metadata surgically removed.&lt;/p&gt;

&lt;p&gt;The important part: &lt;strong&gt;nothing is uploaded.&lt;/strong&gt; There is no server and no analytics. The whole thing is one HTML file; you can turn off your wifi and it still works, and you can read every line of the source.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://thefinalmilkman.github.io/metastrip/" rel="noopener noreferrer"&gt;MetaStrip — see what your photos reveal, then erase it&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Source: &lt;a href="https://github.com/thefinalmilkman/metastrip" rel="noopener noreferrer"&gt;https://github.com/thefinalmilkman/metastrip&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's free and open source (MIT). If it kept your address out of a photo and you want to throw something back, there's a USDC-on-Base tip address on the page — but the tool is yours regardless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways for builders
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Treat EXIF as untrusted user data you are &lt;em&gt;removing&lt;/em&gt;, not displaying — MakerNotes in particular are a junk drawer of vendor-specific identifiers.&lt;/li&gt;
&lt;li&gt;If you handle user image uploads, strip metadata &lt;strong&gt;server-side on ingest&lt;/strong&gt;. Don't trust the client, and don't assume your image library does it for you — many preserve EXIF by default.&lt;/li&gt;
&lt;li&gt;When you strip, prefer segment removal over re-encoding so you don't degrade the image.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your photos have been narrating your life in the background. Now you know where the script is written, and how to delete it.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>security</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Fixed My Windows Battery Health Dashboard and Open-Sourced It</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Tue, 02 Jun 2026 18:19:14 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/i-fixed-my-windows-battery-health-dashboard-and-open-sourced-it-mdp</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/i-fixed-my-windows-battery-health-dashboard-and-open-sourced-it-mdp</guid>
      <description>&lt;p&gt;Windows can generate a raw battery report, but it does not make laptop battery&lt;br&gt;
wear easy to understand. I wanted a local tool that turns the numbers into a&lt;br&gt;
quick decision view: current capacity, original design capacity, wear, charge&lt;br&gt;
history, and a simple A-F health grade.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Fixed Before Sharing It
&lt;/h2&gt;

&lt;p&gt;The first version needed cleanup. I fixed the portable setup, aligned the grade&lt;br&gt;
scale with the code, corrected the discharge display, hardened Windows terminal&lt;br&gt;
output, and rewrote the guide so every command matches the actual tool.&lt;/p&gt;

&lt;p&gt;The dashboard now includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an A-F battery-health grade&lt;/li&gt;
&lt;li&gt;local SQLite history&lt;/li&gt;
&lt;li&gt;degradation estimates after enough snapshots exist&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--watch&lt;/code&gt; and &lt;code&gt;--export&lt;/code&gt; modes&lt;/li&gt;
&lt;li&gt;an optional Groq summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Source
&lt;/h2&gt;

&lt;p&gt;The DIY source is MIT licensed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/thefinalmilkman/digital-downloads/tree/main/battery-dashboard-v1.1" rel="noopener noreferrer"&gt;https://github.com/thefinalmilkman/digital-downloads/tree/main/battery-dashboard-v1.1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a small Windows utility, not a cloud service. The battery data stays on&lt;br&gt;
the machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Support More Small Utilities
&lt;/h2&gt;

&lt;p&gt;If it saves you time and you want to support more practical local-first tools,&lt;br&gt;
a $10-equivalent tip is appreciated:&lt;/p&gt;

&lt;p&gt;Ready-to-run tipware package:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://redkings-battery-dashboard.netlify.app" rel="noopener noreferrer"&gt;https://redkings-battery-dashboard.netlify.app&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base USDC: &lt;code&gt;0x0eAFF975a4823c823cfE0c77E9110Ba47291E72A&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;SOL: &lt;code&gt;9Ga6JioPVtGCiuvWfc2VCCbN61WLNCkm6S1qFRVn38sG&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;HIVE: &lt;code&gt;@redkingsdesigns&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would rather release a small useful tool honestly than pretend a rough draft&lt;br&gt;
is a finished product.&lt;/p&gt;

</description>
      <category>python</category>
      <category>windows</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Built a Python Battery Health Dashboard Because Windows' Built-in Report is Useless</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Thu, 28 May 2026 03:26:51 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/i-built-a-python-battery-health-dashboard-because-windows-built-in-report-is-useless-3ejf</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/i-built-a-python-battery-health-dashboard-because-windows-built-in-report-is-useless-3ejf</guid>
      <description>&lt;p&gt;Windows has a built-in battery report. You run &lt;code&gt;powercfg /batteryreport&lt;/code&gt;, open an HTML file, and stare at a wall of raw numbers — full charge capacity in mWh, design capacity, usage logs spanning months. There's no grade, no trend, no answer to the actual question: &lt;em&gt;is my battery dying or fine?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I built a terminal dashboard that answers that question directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the tool does
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Windows Battery Health Dashboard&lt;/strong&gt; reads WMI battery data directly, assigns an A–F health grade, tracks degradation over time in SQLite, predicts remaining useful life via linear regression, and generates a plain-English AI summary via Groq. It runs entirely in the terminal. No GUI, no bloat.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────┐
│         BATTERY HEALTH DASHBOARD v1.0           │
├─────────────────────────────────────────────────┤
│  Health Grade:     B  (78.4% capacity retained) │
│  Design Capacity:  45,000 mWh                   │
│  Full Charge Now:  35,280 mWh                   │
│  Cycle Count:      312                          │
│  Status:           Discharging  (67%)           │
├─────────────────────────────────────────────────┤
│  Trend: -0.8% capacity/month over 6 snapshots   │
│  Estimated lifespan: ~14 months remaining       │
├─────────────────────────────────────────────────┤
│  AI Summary:                                    │
│  Your battery is in good shape but showing      │
│  steady degradation. At the current rate, plan  │
│  for a replacement within the next 14 months.   │
└─────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How the WMI queries work
&lt;/h2&gt;

&lt;p&gt;Python's &lt;code&gt;wmi&lt;/code&gt; library exposes the &lt;code&gt;root/wmi&lt;/code&gt; namespace, which is where the real battery data lives — not the surface-level stuff in &lt;code&gt;root/cimv2&lt;/code&gt;.&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;c&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/wmi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Design capacity (the original maximum, in mWh)
&lt;/span&gt;&lt;span class="n"&gt;static_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BatteryStaticData&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;design_capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;static_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DesignedCapacity&lt;/span&gt;

&lt;span class="c1"&gt;# Current full charge capacity (degrades over time)
&lt;/span&gt;&lt;span class="n"&gt;full_charge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BatteryFullChargedCapacity&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;current_full&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;full_charge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullChargedCapacity&lt;/span&gt;

&lt;span class="c1"&gt;# Cycle count (not available on all hardware)
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;cycle_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BatteryCycleCount&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;cycles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cycle_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CycleCount&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;cycles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="c1"&gt;# Health as a percentage
&lt;/span&gt;&lt;span class="n"&gt;health_pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_full&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;design_capacity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;health_pct&lt;/code&gt; is the core signal. The grading scale maps directly to it:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Grade&lt;/th&gt;
&lt;th&gt;Health %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;90–100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;75–89%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;60–74%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;40–59%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;&amp;lt; 40%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Degradation tracking and prediction
&lt;/h2&gt;

&lt;p&gt;A single snapshot tells you where you are. SQLite history tells you where you're going.&lt;/p&gt;

&lt;p&gt;Each run writes a row: &lt;code&gt;(timestamp, full_charge_capacity, health_pct)&lt;/code&gt;. After a few weeks of snapshots, the dashboard runs a linear regression over the health percentage values to estimate the monthly degradation rate and project when the battery will cross the 40% threshold — the point most manufacturers consider end-of-life.&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;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="c1"&gt;# x = days since first snapshot, y = health_pct values
&lt;/span&gt;&lt;span class="n"&gt;slope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intercept&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;polyfit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_health&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# months until health_pct hits 40%
&lt;/span&gt;&lt;span class="n"&gt;months_remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;current_health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slope&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prediction sharpens with more data points. Run it weekly and you'll have a useful trend within a month.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI summary
&lt;/h2&gt;

&lt;p&gt;The dashboard sends the health grade, cycle count, trend slope, and predicted lifespan to Groq's API (llama-3.3-70b) and gets back two sentences. That's it. No API key required to use the core dashboard — the summary is optional and clearly marked as such in the output.&lt;/p&gt;

&lt;p&gt;The prompt is intentionally terse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Battery health: {grade} ({health_pct:.1f}%). Cycles: {cycles}.
Degradation: {slope:.3f}%/day. Estimated months remaining: {months:.0f}.
Write a 2-sentence plain-English summary for a non-technical user.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Groq's free tier handles this easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest caveats
&lt;/h2&gt;

&lt;p&gt;This only works on &lt;strong&gt;Windows laptops and tablets with a real battery&lt;/strong&gt;. Desktops, VMs, and WSL will either throw a WMI error or return no battery data. The &lt;code&gt;wmi&lt;/code&gt; Python package requires Windows — this is not a cross-platform tool and doesn't pretend to be.&lt;/p&gt;

&lt;p&gt;Some manufacturers also block or omit cycle count data from WMI. The dashboard handles that gracefully and skips cycle count if unavailable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;

&lt;p&gt;The full dashboard — including the SQLite history module, regression logic, Groq integration, and a clean terminal UI — is available for &lt;strong&gt;$15&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://milkyway801.gumroad.com/l/wdmrqv" rel="noopener noreferrer"&gt;&lt;strong&gt;Download on Gumroad →&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Direct ZIP download: &lt;a href="https://github.com/thefinalmilkman/digital-downloads/releases/download/v1.0.0/battery-dashboard-v1.zip" rel="noopener noreferrer"&gt;battery-dashboard-v1.zip&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Requirements: Python 3.9+, Windows 10/11, &lt;code&gt;wmi&lt;/code&gt;, &lt;code&gt;pywin32&lt;/code&gt;, &lt;code&gt;psutil&lt;/code&gt;. Optional: &lt;code&gt;groq&lt;/code&gt; for the AI summary.&lt;/p&gt;




&lt;p&gt;Built by &lt;a href="https://redkingsdesigns.netlify.app" rel="noopener noreferrer"&gt;RedKingsDesigns&lt;/a&gt; — small tools that solve real problems.&lt;/p&gt;

</description>
      <category>python</category>
      <category>windows</category>
      <category>tools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I built a personal AI assistant that actually remembers things (Claude + Telegram + SQLite)</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Thu, 28 May 2026 01:56:20 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/i-built-a-personal-ai-assistant-that-actually-remembers-things-claude-telegram-sqlite-94k</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/i-built-a-personal-ai-assistant-that-actually-remembers-things-claude-telegram-sqlite-94k</guid>
      <description>&lt;p&gt;Most AI assistants have a fundamental flaw: every conversation starts cold. ChatGPT doesn't know you told it yesterday that you prefer bullet points. Claude forgets you're working on a Node project. The context you built up over weeks evaporates the moment you close the tab.&lt;/p&gt;

&lt;p&gt;I wanted something different — a personal assistant that lives in Telegram, runs on my own machine, and actually &lt;em&gt;retains&lt;/em&gt; state between sessions. Here's how I built it and why the architecture works.&lt;/p&gt;




&lt;h2&gt;
  
  
  The shape of the problem
&lt;/h2&gt;

&lt;p&gt;Before writing any code, it's worth being precise about what "remembering things" actually means for a chat assistant. There are two distinct memory types:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short-term memory&lt;/strong&gt; — the conversation context Claude needs to give coherent replies. "What did the user just ask?" If you don't pass prior messages back to the API, the model is stateless by definition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Long-term memory&lt;/strong&gt; — facts that should persist across sessions. "The user prefers concise answers." "They're building a Node.js project." These shouldn't vanish when the process restarts.&lt;/p&gt;

&lt;p&gt;Most tutorials handle neither. They show you how to get a single Claude response and call it a day. This post covers both.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt; — runtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;node-telegram-bot-api&lt;/code&gt;&lt;/strong&gt; — Telegram interface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@anthropic-ai/sdk&lt;/code&gt;&lt;/strong&gt; — Claude Haiku (fast, ~$0.001/message)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;better-sqlite3&lt;/code&gt;&lt;/strong&gt; — persistent memory (single &lt;code&gt;.db&lt;/code&gt; file, no server)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;dotenv&lt;/code&gt;&lt;/strong&gt; — config&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total dependencies: 4. The whole thing is one file.&lt;/p&gt;




&lt;h2&gt;
  
  
  Database schema — two tables, one file
&lt;/h2&gt;

&lt;p&gt;The memory architecture is intentionally simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;      &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;role&lt;/span&gt;    &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;-- 'user' or 'assistant'&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unixepoch&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;notes&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;      &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTOINCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;-- free-form personal fact&lt;/span&gt;
  &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unixepoch&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;messages&lt;/code&gt; handles short-term memory — the rolling conversation window. &lt;code&gt;notes&lt;/code&gt; handles long-term memory — facts the user explicitly stores with &lt;code&gt;/remember&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They're separate for a reason. Conversation history has a natural expiry: old exchanges stop being relevant after N turns. Personal notes don't expire — "I prefer Celsius" is true forever. Mixing them in one table would mean either polluting your context with stale messages or accidentally pruning permanent facts.&lt;/p&gt;




&lt;h2&gt;
  
  
  The rolling window — how short-term memory stays bounded
&lt;/h2&gt;

&lt;p&gt;Every Claude API call costs tokens. Passing 500 messages of history is both expensive and counterproductive (the model's attention dilutes over very long contexts). The fix is a rolling window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;saveMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`INSERT INTO messages (role, content) VALUES (?, ?)`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Prune: keep only the latest MAX_HISTORY * 2 rows&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
    DELETE FROM messages WHERE id NOT IN (
      SELECT id FROM messages ORDER BY id DESC LIMIT ?
    )
  `&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MAX_HISTORY&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getHistory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`SELECT role, content FROM messages ORDER BY id ASC`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After every save, a DELETE prunes everything outside the window. The default is 10 exchanges (20 rows — user + assistant pairs). This is configurable via &lt;code&gt;MEMORY_WINDOW&lt;/code&gt; in &lt;code&gt;.env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Why &lt;code&gt;MAX_HISTORY * 2&lt;/code&gt;? The Anthropic messages API requires alternating &lt;code&gt;user&lt;/code&gt;/&lt;code&gt;assistant&lt;/code&gt; turns. If you store them separately and count by message count, you'd need even pairs anyway. Doubling the window size and pruning by row count naturally maintains that invariant.&lt;/p&gt;




&lt;h2&gt;
  
  
  Long-term notes — injecting facts into the system prompt
&lt;/h2&gt;

&lt;p&gt;This is the key part. Notes aren't passed as messages — they're injected into the &lt;em&gt;system prompt&lt;/em&gt;. This matters because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;System prompt content is read before any conversation turn&lt;/li&gt;
&lt;li&gt;It doesn't count against the conversational history limit&lt;/li&gt;
&lt;li&gt;The model treats it as foundational context, not a thing the user once said
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;askClaude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNotes&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;systemText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;noteList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`- &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;systemText&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`\n\nPersonal notes from the user (always honor these):\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;noteList&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getHistory&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CLAUDE_MODEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;system&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;systemText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run &lt;code&gt;/remember I work in Central Time&lt;/code&gt;, that note goes into the &lt;code&gt;notes&lt;/code&gt; table. Every subsequent API call re-reads all notes and appends them to the system prompt. The model now knows your timezone permanently — across restarts, across cleared histories — because it's always in the system prompt.&lt;/p&gt;




&lt;h2&gt;
  
  
  The full message handler
&lt;/h2&gt;

&lt;p&gt;The Telegram side is straightforward once the database helpers are in place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// single allowed chat ID — private by default&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// commands handled separately&lt;/span&gt;

  &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendChatAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// show typing indicator&lt;/span&gt;

  &lt;span class="nf"&gt;saveMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;askClaude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;saveMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The auth guard (&lt;code&gt;isAllowed&lt;/code&gt;) checks &lt;code&gt;msg.chat.id&lt;/code&gt; against &lt;code&gt;TELEGRAM_ALLOWED_CHAT_ID&lt;/code&gt; from &lt;code&gt;.env&lt;/code&gt;. This prevents the bot from responding to anyone who stumbles on your bot token — a real concern if you ever accidentally expose it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Built-in commands
&lt;/h2&gt;

&lt;p&gt;Three commands ship out of the box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/remember &amp;lt;text&amp;gt;  — store a permanent note
/forget           — clear conversation history (notes survive)
/status           — uptime, message count, memory stats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/forget&lt;/code&gt; clears &lt;code&gt;messages&lt;/code&gt; but leaves &lt;code&gt;notes&lt;/code&gt; untouched. This is intentional — starting a fresh conversation shouldn't erase the facts you've stored. You'd need a separate &lt;code&gt;/clearnotes&lt;/code&gt; command if you wanted that.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/status&lt;/code&gt; is handy for debugging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Assistant Status

Uptime: 2h 14m
Model: claude-haiku-4-5-20251001
Messages this session: 8 in context
Total messages ever: 312
Stored notes: 4
Memory window: 10 exchanges
DB: memory.db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Running cost
&lt;/h2&gt;

&lt;p&gt;Claude Haiku is priced at $0.80 per million input tokens and $4.00 per million output tokens. A typical message exchange — 500 tokens in, 200 out — costs about $0.0012. Run it 30 times a day and you're at $0.036/day. A $5 Anthropic credit lasts roughly 4-5 months of normal personal use.&lt;/p&gt;

&lt;p&gt;Telegram bots are free. SQLite is free. The only recurring cost is the Anthropic API, and at this usage level it's effectively rounding error.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why SQLite and not a vector DB
&lt;/h2&gt;

&lt;p&gt;Every AI memory tutorial wants to reach for Pinecone, Weaviate, or at minimum Redis. For a &lt;em&gt;personal&lt;/em&gt; assistant handling &lt;em&gt;your&lt;/em&gt; notes, this is massive overkill.&lt;/p&gt;

&lt;p&gt;You will not have 100,000 notes. You might have 50. A &lt;code&gt;SELECT * FROM notes&lt;/code&gt; returning 50 rows and injecting them into a system prompt is instant, free, and never breaks. Semantic search across 50 items is not a problem that needs solving.&lt;/p&gt;

&lt;p&gt;SQLite also gives you durability for free. &lt;code&gt;better-sqlite3&lt;/code&gt; writes are synchronous — there's no async error surface, no connection pool to manage. The file is just there when you restart.&lt;/p&gt;

&lt;p&gt;Scale the vector approach when you have a real semantic retrieval problem (thousands of documents, fuzzy lookup, cross-user search). For one person's notes: a SQLite table is the right tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  Extending it
&lt;/h2&gt;

&lt;p&gt;The architecture makes extensions clean because each new command is independent. Some examples of what drops in naturally:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Daily briefings via cron:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cron&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-cron&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0 8 * * *&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;briefing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;askClaude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Give me a short morning briefing. Check my notes for context.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ALLOWED_CHAT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`Good morning!\n\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;briefing&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Reminders stored in SQLite:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;remind &lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt; in &lt;/span&gt;&lt;span class="se"&gt;(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)(&lt;/span&gt;&lt;span class="sr"&gt;m|h&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3600000&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT INTO reminders (message, fire_at) VALUES (?, ?)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`Reminder set.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Vision — analyze photos you send:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;photo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;file_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFileLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// fetch as base64, send to Claude with image content block&lt;/span&gt;
  &lt;span class="c1"&gt;// claude-haiku handles images natively — no separate vision model needed&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each of these is independent. Adding one doesn't touch the others.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this architecture can't do
&lt;/h2&gt;

&lt;p&gt;Being honest about limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No semantic search&lt;/strong&gt; — notes are injected verbatim. If you have 200 notes, you'd want to filter by relevance before injecting. At 20-30 notes this isn't a problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single user only&lt;/strong&gt; — the &lt;code&gt;ALLOWED_CHAT_ID&lt;/code&gt; guard is intentional. Multi-user requires per-user memory tables and more careful auth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No streaming&lt;/strong&gt; — &lt;code&gt;bot.sendMessage&lt;/code&gt; blocks until Claude replies. For long responses, a streaming approach would show text as it generates. Doable, just not in this minimal version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local persistence only&lt;/strong&gt; — &lt;code&gt;memory.db&lt;/code&gt; lives wherever you run the process. If you move machines, bring the file. No automatic cloud sync.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The full &lt;code&gt;.env&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;ANTHROPIC_API_KEY&lt;/span&gt;=&lt;span class="n"&gt;sk&lt;/span&gt;-&lt;span class="n"&gt;ant&lt;/span&gt;-...
&lt;span class="n"&gt;TELEGRAM_BOT_TOKEN&lt;/span&gt;=&lt;span class="n"&gt;your_bot_token_from_botfather&lt;/span&gt;
&lt;span class="n"&gt;TELEGRAM_ALLOWED_CHAT_ID&lt;/span&gt;=&lt;span class="n"&gt;your_numeric_chat_id&lt;/span&gt;

&lt;span class="c"&gt;# Optional — these have sane defaults
&lt;/span&gt;&lt;span class="n"&gt;CLAUDE_MODEL&lt;/span&gt;=&lt;span class="n"&gt;claude&lt;/span&gt;-&lt;span class="n"&gt;haiku&lt;/span&gt;-&lt;span class="m"&gt;4&lt;/span&gt;-&lt;span class="m"&gt;5&lt;/span&gt;-&lt;span class="m"&gt;20251001&lt;/span&gt;
&lt;span class="n"&gt;MEMORY_WINDOW&lt;/span&gt;=&lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;SYSTEM_PROMPT&lt;/span&gt;=&lt;span class="n"&gt;You&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;personal&lt;/span&gt; &lt;span class="n"&gt;AI&lt;/span&gt; &lt;span class="n"&gt;assistant&lt;/span&gt;. &lt;span class="n"&gt;Be&lt;/span&gt; &lt;span class="n"&gt;direct&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;concise&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get your chat ID by messaging &lt;code&gt;@userinfobot&lt;/code&gt; on Telegram.&lt;/p&gt;




&lt;h2&gt;
  
  
  Running it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
cp&lt;/span&gt; .env.example .env
&lt;span class="c"&gt;# fill in your three required keys&lt;/span&gt;
node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For persistent operation, wrap it in PM2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pm2
pm2 start index.js &lt;span class="nt"&gt;--name&lt;/span&gt; assistant
pm2 startup   &lt;span class="c"&gt;# auto-restart on reboot&lt;/span&gt;
pm2 save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;The core insight here is that "memory" for an LLM assistant is really just careful data management. Short-term context is a rolling SQLite window passed as the messages array. Long-term facts are a separate table injected into the system prompt. Neither requires a vector database, a cloud service, or anything beyond the four npm packages listed above.&lt;/p&gt;

&lt;p&gt;The total implementation is around 280 lines of well-commented JavaScript. That size is deliberate — small enough to read in one sitting, large enough to be a real working system rather than a hello-world skeleton.&lt;/p&gt;

&lt;p&gt;This is the same memory pattern used in a larger AI system running 88 MCP tools and full autonomy loops. The difference is 18 months of additions. The core memory architecture hasn't changed.&lt;/p&gt;




&lt;p&gt;If you want the full starter kit — the complete &lt;code&gt;index.js&lt;/code&gt;, a 30-minute setup guide, and 10 pre-built extensions (weather, reminders, vision, cron briefings, web search, FTS5 note search, Pomodoro timer, and more) — it's at &lt;strong&gt;&lt;a href="https://milkyway801.gumroad.com/l/hkdaox" rel="noopener noreferrer"&gt;https://milkyway801.gumroad.com/l/hkdaox&lt;/a&gt;&lt;/strong&gt; for $19 one-time. No subscription, no license key. Unzip, fill in &lt;code&gt;.env&lt;/code&gt;, run.&lt;/p&gt;

&lt;p&gt;Extensions you've built on this pattern, or questions about the memory architecture — drop them in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>javascript</category>
      <category>telegram</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I built a Python hardware monitor that shows real battery degradation, CPU temps per core, and SSD wear -- here's how</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Thu, 28 May 2026 01:34:40 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/i-built-a-python-hardware-monitor-that-shows-real-battery-degradation-cpu-temps-per-core-and-ssd-mab</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/i-built-a-python-hardware-monitor-that-shows-real-battery-degradation-cpu-temps-per-core-and-ssd-mab</guid>
      <description>&lt;p&gt;I was troubleshooting a performance issue on my laptop when I noticed something that stopped me cold.&lt;/p&gt;

&lt;p&gt;My CPU was sitting at 20% load. Nothing crazy. Just a browser, a terminal, and a couple of background tasks. But the temperature readout I was watching — thrown together in an afternoon — showed &lt;strong&gt;83°C on the hottest core&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then I checked the battery. &lt;strong&gt;74.4% health after 8 years.&lt;/strong&gt; The designed capacity was 45,000 mWh. The battery now maxes out at 33,480 mWh. Windows just says "100% charged" like nothing is wrong.&lt;/p&gt;

&lt;p&gt;Task Manager told me none of this. Neither did any monitoring software I trusted — they all wanted to install tray icons, telemetry services, or drivers I didn't ask for.&lt;/p&gt;

&lt;p&gt;So I built my own.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem with Windows Monitoring
&lt;/h2&gt;

&lt;p&gt;Windows exposes a lot of hardware data. The problem is it's scattered across three different APIs, one of them requires a kernel driver you probably don't have, and none of it is surfaced in the default UI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Task Manager&lt;/strong&gt;: CPU load %, memory GB. That's about it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Monitor&lt;/strong&gt;: Slightly more, still no temps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Monitor&lt;/strong&gt;: Overwhelming. Not useful for at-a-glance health.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Third-party tools&lt;/strong&gt;: HWiNFO64 is great but it's a full application. GPU-Z, CPU-Z — each does one thing. Nothing unified and scriptable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal: one Python script, no installer, reads what Windows actually knows about your hardware, and prints it cleanly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1 — GPU Stats via nvidia-smi
&lt;/h2&gt;

&lt;p&gt;The easiest piece. NVIDIA ships &lt;code&gt;nvidia-smi&lt;/code&gt; with every driver install. It has a machine-readable &lt;code&gt;--query-gpu&lt;/code&gt; mode that outputs CSV:&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;subprocess&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nvidia-smi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--query-gpu=temperature.gpu,utilization.gpu,memory.used,memory.free&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--format=csv,noheader&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;util&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;used&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;total_mib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;used&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GPU: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;C, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;util&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; load, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;used&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total_mib&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; MiB VRAM&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--format=csv,noheader&lt;/code&gt; flag gives you clean values with units attached (&lt;code&gt;62 C&lt;/code&gt;, &lt;code&gt;45 %&lt;/code&gt;, &lt;code&gt;3273 MiB&lt;/code&gt;). Split on &lt;code&gt;", "&lt;/code&gt;, strip the units when you need integers, done.&lt;/p&gt;

&lt;p&gt;For the VRAM bar graph I used a simple ratio:&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;def&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;used&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;filled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;X&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;filled&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;filled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 2 — Battery Wear via WMI (the interesting one)
&lt;/h2&gt;

&lt;p&gt;Most people don't know this WMI class exists. &lt;code&gt;BatteryFullChargedCapacity&lt;/code&gt; and &lt;code&gt;BatteryStaticData&lt;/code&gt; live in the &lt;code&gt;root/wmi&lt;/code&gt; namespace — not the default &lt;code&gt;root/cimv2&lt;/code&gt; that most WMI examples use.&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/wmi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&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;BatteryFullChargedCapacity&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;FullChargedCapacity&lt;/span&gt;
&lt;span class="n"&gt;design&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&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;BatteryStaticData&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;DesignedCapacity&lt;/span&gt;
&lt;span class="n"&gt;health_pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;design&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Battery health: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;health_pct&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%  (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;full&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; / &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;design&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; mWh)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;DesignedCapacity&lt;/code&gt; is what the manufacturer rated the battery at when it left the factory. &lt;code&gt;FullChargedCapacity&lt;/code&gt; is what it can actually hold right now. The ratio is your wear percentage.&lt;/p&gt;

&lt;p&gt;This is the same data that &lt;code&gt;powercfg /batteryreport&lt;/code&gt; uses internally — you are just reading it directly instead of parsing an HTML report.&lt;/p&gt;

&lt;p&gt;My battery: 33,480 / 45,000 = &lt;strong&gt;74.4%&lt;/strong&gt;. After 8 years that is actually respectable. But I would not have known without digging into this WMI namespace.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3 — SSD SMART via PowerShell StorageReliabilityCounter
&lt;/h2&gt;

&lt;p&gt;Windows 8+ ships with &lt;code&gt;Get-StorageReliabilityCounter&lt;/code&gt;, a PowerShell cmdlet that wraps SMART data without needing smartmontools or admin elevation for basic stats:&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;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;ps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Get-PhysicalDisk | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Get-StorageReliabilityCounter | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Select-Object PowerOnHours,Temperature,Wear | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ConvertTo-Json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;powershell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-Command&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SSD: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PowerOnHours&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; hours on, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Temperature&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;C, wear: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Wear&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PowerOnHours&lt;/code&gt; is cumulative lifetime hours. &lt;code&gt;Wear&lt;/code&gt; is the SMART wear indicator (0 = new, 100 = end of life). &lt;code&gt;Temperature&lt;/code&gt; is the drive's current thermal reading.&lt;/p&gt;

&lt;p&gt;My T-FORCE VULCAN Z: 9,101 hours on, 33C, 0% wear. Still healthy.&lt;/p&gt;

&lt;p&gt;One caveat: if you have multiple drives, &lt;code&gt;ConvertTo-Json&lt;/code&gt; returns an array. Wrap &lt;code&gt;data&lt;/code&gt; in a list check (&lt;code&gt;if isinstance(data, list)&lt;/code&gt;) and iterate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 4 — CPU Temps via LibreHardwareMonitor WMI
&lt;/h2&gt;

&lt;p&gt;This one is the trickiest. Windows intentionally blocks direct MSR (Model Specific Register) reads from userspace — that is where the actual thermal sensor data lives. To read CPU core temps without a kernel driver, you need something that already has ring-0 access to expose the data through a friendlier API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/LibreHardwareMonitor/LibreHardwareMonitor" rel="noopener noreferrer"&gt;LibreHardwareMonitor&lt;/a&gt; solves this. When it is running, it exposes all sensor data through its own WMI namespace: &lt;code&gt;root/LibreHardwareMonitor&lt;/code&gt;.&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;lhm&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/LibreHardwareMonitor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sensors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lhm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sensor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;cpu_temps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sensors&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SensorType&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CPU Core&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;s&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sensor&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cpu_temps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;s&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;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sensor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  [HOT]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sensor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;C&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dependency chain: run LibreHardwareMonitor in the background, then query its WMI namespace from Python. The tool handles this check at startup and warns if LHM is not running.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Output Looks Like
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;============================================================
  DESKTOP-V0J6K6M -- Hardware Monitor   2026-05-27 19:00
============================================================

[CPU]  Intel Core i7-8750H
  Load: 20%   Clock: 2208 MHz
  CPU Core #1    83.0C  [HOT]
  CPU Core #2    70.0C
  CPU Core #3    72.0C
  CPU Core #4    68.0C
  CPU Core #5    71.0C
  CPU Core #6    69.0C
  CPU Package    83.0C   Power: 25.2W

[GPU]  NVIDIA GeForce GTX 1050 Ti
  Temp:  62C
  VRAM:  [############################..] 3273/4005 MiB

[Storage]  T-FORCE VULCAN Z 512GB
  Temp: 33C   On: 9101 hrs   Wear: 0%

[Battery]  L17M3PG1
  Charge: 100%
  Health: [######################........] 74.4%

============================================================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;[HOT]&lt;/code&gt; flag triggers at 80C for cores, 85C for package. Thresholds are constants you can tune.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building It Out
&lt;/h2&gt;

&lt;p&gt;The script grew from "print some temps" into something with a few more features I kept reaching for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--watch&lt;/code&gt; mode that refreshes every N seconds (clears the terminal each cycle)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--json&lt;/code&gt; flag that dumps all readings as structured JSON for piping into other tools&lt;/li&gt;
&lt;li&gt;Graceful degradation: if nvidia-smi is not found, the GPU section is skipped cleanly instead of crashing&lt;/li&gt;
&lt;li&gt;Battery section only appears on laptops (checks if &lt;code&gt;BatteryStaticData&lt;/code&gt; returns any results)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The watch mode is where it became genuinely useful. Seeing the temps respond in real time when you open a heavy application tells you a lot more than a one-shot reading.&lt;/p&gt;




&lt;h2&gt;
  
  
  If You Don't Want to Build It Yourself
&lt;/h2&gt;

&lt;p&gt;I packaged the full version — &lt;code&gt;--watch&lt;/code&gt; mode, &lt;code&gt;--json&lt;/code&gt; export, the LHM detection logic, and thresholds already tuned — and put it on Gumroad for $5: &lt;a href="https://milkyway801.gumroad.com/l/ekpeqp" rel="noopener noreferrer"&gt;AI Hardware Monitor for Windows&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a single &lt;code&gt;.py&lt;/code&gt; file. No installer, no tray icon, no telemetry. Dependencies are &lt;code&gt;wmi&lt;/code&gt; (pip) and LibreHardwareMonitor for CPU temps. Everything else is stdlib.&lt;/p&gt;

&lt;p&gt;If you just want the battery and SSD pieces, the snippets above are complete as-is. The WMI namespaces are the non-obvious part — once you have those, the rest is straightforward Python.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Needs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPU temp, VRAM, utilization&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;nvidia-smi&lt;/code&gt; subprocess&lt;/td&gt;
&lt;td&gt;NVIDIA GPU + driver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Battery health %&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;root/wmi&lt;/code&gt; via &lt;code&gt;BatteryFullChargedCapacity&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Laptop, Python &lt;code&gt;wmi&lt;/code&gt; package&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSD hours, temp, wear&lt;/td&gt;
&lt;td&gt;PowerShell &lt;code&gt;Get-StorageReliabilityCounter&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Windows 8+, no elevation needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU per-core temps&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;root/LibreHardwareMonitor&lt;/code&gt; WMI&lt;/td&gt;
&lt;td&gt;LibreHardwareMonitor running&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The battery one is the sleeper. Most people have no idea &lt;code&gt;root/wmi&lt;/code&gt; exposes this. Check yours — you might be surprised what your laptop is hiding from you.&lt;/p&gt;

</description>
      <category>python</category>
      <category>windows</category>
      <category>hardware</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Spot a Legit Online Kratom Shop (Without Getting Burned)</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Mon, 25 May 2026 11:59:24 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/how-to-spot-a-legit-online-kratom-shop-without-getting-burned-2m3j</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/how-to-spot-a-legit-online-kratom-shop-without-getting-burned-2m3j</guid>
      <description>&lt;h1&gt;
  
  
  How to Spot a Legit Online Kratom Shop (Without Getting Burned)
&lt;/h1&gt;

&lt;p&gt;I've been buying kratom online since 2019, and I've been ripped off enough times to know the red flags. Stale powder that tastes like dirt, "Maeng Da" that hits like flour, vendors that vanish after one bad batch. If you've been around the forums — r/kratom, Reddit's vendor lists, the GMP-compliant directory — you already know the landscape is messy. Here's what actually separates a shop worth your money from one worth a chargeback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strain Selection That Goes Beyond the Big Three
&lt;/h2&gt;

&lt;p&gt;Every shop carries Red Bali, Green Maeng Da, and White Borneo. That's table stakes. What you want is a vendor stocking at least 15-20 distinct strains — Yellow Vietnam, Red Horn, Elephant, Sumatra White, the regional Indo varieties you can't find at gas stations. A deep menu signals the vendor has real Indonesian sourcing relationships, not a single warehouse drop-shipping the same kilo under different labels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab Testing You Can Actually Read
&lt;/h2&gt;

&lt;p&gt;"Lab tested" on a banner means nothing. Ask for the actual COA — Certificate of Analysis — and it should show alkaloid content (mitragynine and 7-hydroxymitragynine percentages), plus screens for heavy metals, salmonella, E. coli, and yeast. Reputable shops post these PDFs by batch number. If they hand-wave when you ask, walk. The AKA GMP qualified program is the closest thing the industry has to a standard, and roughly two dozen vendors hold it. Worth checking before you order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing That Makes Sense
&lt;/h2&gt;

&lt;p&gt;A kilo of decent kratom runs $80-130 depending on strain and vendor. Under $60 a kilo and you're buying old stock, stems and veins, or worse. Over $200 and you're paying for branding. The sweet spot for quality powder is usually $90-110/kg with auto-ship discounts knocking another 10-15% off. Watch the per-gram math on capsules — a lot of shops mark capsules up 4x over loose powder for the same product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customer Service That Knows the Product
&lt;/h2&gt;

&lt;p&gt;Email a shop and ask which strain they'd recommend for evening use versus morning. The answer tells you everything. A real vendor will ask about your tolerance, mention specific strain profiles, maybe suggest a sample pack. A bad one will copy-paste marketing copy or tell you "all our strains are great." Same test works for dosing questions — a knowledgeable rep will give a range and tell you to start low, not throw out a number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Payment Options That Don't Get Frozen
&lt;/h2&gt;

&lt;p&gt;Kratom is in a payment-processor gray zone, which is why legit shops accept eCheck, ACH, crypto, and sometimes Zelle — credit card processing gets shut down constantly. SSL is the bare minimum. What you actually want is a vendor that's been processing payments under the same business name for 2+ years without disappearing and rebranding. Check the WHOIS on the domain. A six-month-old domain selling "20 years of kratom expertise" is a flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Real-World Example
&lt;/h2&gt;

&lt;p&gt;A friend started kratom last fall, ordered from the first shop a Google ad pointed him at. $140 for 250g, no COAs, "proprietary blend" on the label. Felt almost nothing. He sent me the bag — generic ziplock, no batch number, no harvest date. The same money at a vetted vendor would've gotten him 500g of single-strain powder with a published COA and a satisfaction guarantee. The lesson: the shops that spend money on Google Ads usually aren't the ones spending money on lab testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;A good kratom vendor will bore you with paperwork — COAs, batch numbers, GMP certifications, refund policies in plain English. The sketchy ones will dazzle you with discount codes and "limited time" banners. Pick the boring one every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready to find your perfect kratom match? Check the latest price and reviews on Amazon: &lt;a href="https://www.amazon.com/s?k=kratom%20affiliate%20reviews%20smoke%20shop&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=kratom%20affiliate%20reviews%20smoke%20shop&amp;amp;tag=james-default-20&lt;/a&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Support This Content
&lt;/h2&gt;

&lt;p&gt;If this guide saved you time or money, a crypto tip keeps J.A.M.E.S. running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BTC:&lt;/strong&gt; &lt;code&gt;1B2xp9fu6eVNBiAByikcQYS569LeU1EVL7&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ETH:&lt;/strong&gt; &lt;code&gt;0x3a0419a218078751f4a210d2f3835a672fa4bf91&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOL:&lt;/strong&gt; &lt;code&gt;9Ga6JioPVtGCiuvWfc2VCCbN61WLNCkm6S1qFRVn38sG&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Every tip goes directly toward research, tools, and keeping the lights on. Thank you.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kratom</category>
      <category>kratomaffiliatereviewssmo</category>
      <category>productivity</category>
      <category>review</category>
    </item>
    <item>
      <title>Kratom affiliate reviews smoke shop Guide</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Mon, 25 May 2026 11:49:22 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/kratom-affiliate-reviews-smoke-shop-guide-59ad</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/kratom-affiliate-reviews-smoke-shop-guide-59ad</guid>
      <description>&lt;p&gt;&lt;strong&gt;The Kratom Vendor Test I Wish Someone Had Shown Me Three Years Ago&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've burned through more bad kratom than I care to admit. Stale green Maeng Da that tasted like lawn clippings. A "premium" red Bali that turned out to be cut with something that gave me a headache for two days. A vendor that ghosted me after charging $89 for an order that never shipped. If you've shopped for kratom online for more than six months, you know the drill — and you know how exhausting it gets reading the same recycled blog posts that all say the exact same nothing.&lt;/p&gt;

&lt;p&gt;So let me skip the fluff and tell you what actually separates a smoke shop worth your money from one that's about to waste it.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;You're Shopping at 11pm, Not at Noon&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here's the thing nobody talks about: most kratom buyers aren't browsing during business hours. We're shopping after a long shift, after the kids are asleep, after we've decided we need something &lt;em&gt;now&lt;/em&gt; — not next Tuesday when the head shop on Main Street finally opens back up. A solid online vendor gets that. Real-time stock counts, shipping cutoffs posted on the product page (not buried in an FAQ), and reorder buttons that remember your last strain. That's the bar.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;"High-Quality" Means Lab Results You Can Actually Read&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Every vendor on Earth claims premium kratom. The ones who mean it post third-party lab tests with batch numbers — alkaloid percentages, heavy metals, salmonella, the works. If a vendor's "lab tested" page is a single stock photo of a beaker, close the tab. The good ones publish mitragynine content in the 1.2–1.8% range for their reds, and they'll tell you which harvest the batch came from. Affiliate reviews from people who actually cross-checked those numbers are worth ten generic "great product, fast shipping!" testimonials.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Price Math Most People Get Wrong&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Online kratom looks cheaper because it usually is — but the real savings hide in the kilo pricing. A reputable shop sells a kilo for $90–$130. The smoke shop down the street charges $20 an ounce, which works out to over $700 a kilo for kratom that's been sitting under fluorescent lights since Biden was in office. Freshness matters more than people realize. Kratom oxidizes. Six months on a shelf and your red turns into expensive dust.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Staff Question&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can tell within two emails whether a vendor actually knows kratom. Ask them the difference between a green Borneo and a green Hulu Kapuas. If they answer with copy-pasted marketing text, move on. If they tell you the Hulu hits faster but doesn't last as long and recommend you start at 2 grams, you've found someone worth buying from.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Real-World Use Case: The Anxiety Strain Hunt&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I spent four months chasing the right strain for evening anxiety — the racing-thoughts kind that hits around 9pm and won't let you sleep. Whites were too stimulating. Greens were a coin flip. What finally worked was a red vein Bantuangie at around 3 grams, taken about 45 minutes before I wanted to wind down. I never would've landed on Bantuangie on my own — it was buried three pages deep in a forum thread, mentioned by a user who tracked his doses in a spreadsheet for six weeks.&lt;/p&gt;

&lt;p&gt;That's the value of pooled experience. Solo trial and error costs you $40 a bag and a month per attempt. Reading thirty honest reviews on a place like &lt;a href="https://www.amazon.com/s?k=kratom%20affiliate%20reviews%20smoke%20shop&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;&lt;strong&gt;Kraken Kratom Affiliate Reviews Smoke Shop&lt;/strong&gt;&lt;/a&gt; costs you twenty minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Bottom Line&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Most kratom advice online is written by people who've never actually opened a bag. The vendors worth your money are the ones who post lab results, price kilos in the double digits, ship the same day you order, and employ people who can tell a Maeng Da from a Malay without Googling it. Everything else is marketing.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you're tired of rolling the dice, start with vendors that have a paper trail — reviews, batch tests, return policies you can actually find. &lt;a href="https://www.amazon.com/s?k=kratom%20affiliate%20reviews%20smoke%20shop&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;&lt;strong&gt;Kraken Kratom Affiliate Reviews Smoke Shop&lt;/strong&gt;&lt;/a&gt; is one of the few that checks all four boxes.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Support This Content
&lt;/h2&gt;

&lt;p&gt;If this guide saved you time or money, a crypto tip keeps J.A.M.E.S. running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BTC:&lt;/strong&gt; &lt;code&gt;1B2xp9fu6eVNBiAByikcQYS569LeU1EVL7&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ETH:&lt;/strong&gt; &lt;code&gt;0x3a0419a218078751f4a210d2f3835a672fa4bf91&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOL:&lt;/strong&gt; &lt;code&gt;9Ga6JioPVtGCiuvWfc2VCCbN61WLNCkm6S1qFRVn38sG&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Every tip goes directly toward research, tools, and keeping the lights on. Thank you.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kratom</category>
      <category>kratomaffiliatereviewssmo</category>
      <category>productivity</category>
      <category>review</category>
    </item>
    <item>
      <title>The Texas Delta-8 Pivot: What Smoke Shop Owners Actually Need to Do Right Now</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Mon, 25 May 2026 05:44:47 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/the-texas-delta-8-pivot-what-smoke-shop-owners-actually-need-to-do-right-now-3mh3</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/the-texas-delta-8-pivot-what-smoke-shop-owners-actually-need-to-do-right-now-3mh3</guid>
      <description>&lt;h1&gt;
  
  
  The Texas Delta-8 Pivot: What Smoke Shop Owners Actually Need to Do Right Now
&lt;/h1&gt;

&lt;p&gt;If you're staring down a backroom full of Delta-8 gummies and vape carts wondering whether you're about to eat $40,000 in dead inventory — you're not alone, and you're not out of options. SB 3 changed the rules fast, and most of the "advice" floating around right now is either lawyer-hedged to uselessness or copy-pasted from California operators who don't understand how Texas DSHS actually enforces. Here's what's working for the shops I've been talking to in Houston, Beaumont, and the Valley — and the toolset that's keeping them open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Your COAs and Labels Straight Without Hiring a Consultant
&lt;/h2&gt;

&lt;p&gt;The first thing DSHS asks for on a walk-in inspection isn't your inventory — it's your Certificates of Analysis. If your COAs don't show total Delta-9 under 0.3% on a dry-weight basis (and total THC, not just delta-9 isolate), you're already out of compliance, ban or no ban. [&lt;strong&gt;Your Product Name&lt;/strong&gt;] &lt;a href="https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20&lt;/a&gt; pulls the lab PDF, parses the cannabinoid profile, and flags anything that won't survive an inspector's flashlight. It cut my compliance review from a Saturday afternoon down to about 20 minutes per SKU.&lt;/p&gt;

&lt;h2&gt;
  
  
  Labels That Match the Statute, Not Just the Vibe
&lt;/h2&gt;

&lt;p&gt;Texas Health &amp;amp; Safety Code 443 has specific language requirements — batch number, manufacturer info, the "consumable hemp product" designation, the QR code linking to the COA. I've watched shops get cited for fonts that were technically too small and warning language that paraphrased instead of quoted. [&lt;strong&gt;Your Product Name&lt;/strong&gt;] &lt;a href="https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20&lt;/a&gt; has the 443-compliant templates baked in, including the Spanish-language variants you need if you're anywhere south of San Antonio. Print, slap, move on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sourcing the Replacement Inventory
&lt;/h2&gt;

&lt;p&gt;The pivot most shops are running: legal hemp-derived CBD, CBG, and CBN products, plus the nicotine and kratom side of the house picking up margin. The trick is your distributor has to be able to ship to Texas post-SB 3, and a lot of them quietly delisted us. [&lt;strong&gt;Your Product Name&lt;/strong&gt;] &lt;a href="https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20&lt;/a&gt; maintains a vetted distributor list with current Texas shipping status — saved me three weeks of cold-calling sales reps who promised everything and delivered nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation That Holds Up When DSHS Walks In
&lt;/h2&gt;

&lt;p&gt;I had an inspector spend 90 minutes in my Port Arthur location last March. What got me through it clean wasn't the products — it was being able to hand him a binder (well, a tablet) with every COA, every invoice, every batch traceable back to the manufacturer in under 30 seconds. [&lt;strong&gt;Your Product Name&lt;/strong&gt;] &lt;a href="https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20&lt;/a&gt; keeps that record audit-ready and timestamped, so when somebody from Austin shows up unannounced you're not digging through Gmail looking for a PDF from eight months ago.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Sarah Did in Austin
&lt;/h2&gt;

&lt;p&gt;A shop owner I know on East 6th — call her Sarah — had about $28K in Delta-8 product on the shelf when SB 3 hit. She didn't panic-dump it on Craigslist (which is what half the Reddit threads were telling people to do). She used [&lt;strong&gt;Your Product Name&lt;/strong&gt;] &lt;a href="https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20&lt;/a&gt; to identify which SKUs were actually still legal under the revised definitions, returned what wasn't to her distributor under their buyback clause, and rebuilt the wall with CBD flower, hemp-derived CBG tinctures, and a bigger kratom selection. Her revenue dipped about 18% the first month and was back to flat by month three. She didn't close. That's the bar right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bottom Line
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The Texas Delta-8 ban isn't a death sentence for your shop — it's a margin compression event, and the operators who treat it like a paperwork problem instead of a panic event are the ones still open in 2027. Get your COAs clean, get your labels legal, and stop guessing about what your distributor can ship. Check the latest price and reviews on Amazon: &lt;a href="https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=Texas%20Delta-8%20THC%20ban%20pivot&amp;amp;tag=james-default-20&lt;/a&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Support This Content
&lt;/h2&gt;

&lt;p&gt;If this guide saved you time or money, a crypto tip keeps J.A.M.E.S. running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BTC:&lt;/strong&gt; &lt;code&gt;1B2xp9fu6eVNBiAByikcQYS569LeU1EVL7&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ETH:&lt;/strong&gt; &lt;code&gt;0x3a0419a218078751f4a210d2f3835a672fa4bf91&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOL:&lt;/strong&gt; &lt;code&gt;9Ga6JioPVtGCiuvWfc2VCCbN61WLNCkm6S1qFRVn38sG&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Every tip goes directly toward research, tools, and keeping the lights on. Thank you.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>texas</category>
      <category>texasdelta8thcbanpivot</category>
      <category>productivity</category>
      <category>review</category>
    </item>
    <item>
      <title>AI tools Guide</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Sat, 23 May 2026 17:12:01 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/ai-tools-guide-2faa</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/ai-tools-guide-2faa</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;#1 AI Tools for Small Business Owners: Boost Efficiency and Productivity with [Product Name]&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Last year, a restaurant owner I know was spending 11 hours a week on email alone. Not reading strategy docs or negotiating supplier contracts — just triaging, forwarding, and replying to the same five questions over and over. That's 572 hours a year. More than 14 full work weeks, gone.&lt;/p&gt;

&lt;p&gt;That's the mundane tax small business owners pay, and most don't even realize how steep it is until they add it up.&lt;/p&gt;

&lt;p&gt;If you're running a business under 50 people, you already know what it feels like to be the one who does everything. Sales, ops, hiring, customer complaints, the invoice that got lost — all of it lands on your desk. AI tools have gotten genuinely good at taking a real chunk of that off your plate, and [Product Name] is one of the few built specifically with small operators in mind rather than enterprise teams with six-figure software budgets.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Streamline Your Workflow with Automation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The hours that kill small business owners aren't the hard ones — they're the repetitive ones. Manually moving a lead from your inbox into your CRM. Copying order details into a spreadsheet. Sending the same follow-up email for the third time this week.&lt;/p&gt;

&lt;p&gt;[Product Name] handles this through workflow automation that doesn't require a developer to set up. You define the trigger and the action, and it runs. Practically, that looks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically routing inbound emails to the right person based on keywords or sender domain&lt;/li&gt;
&lt;li&gt;Pulling data from PDFs, invoices, or forms and dropping it into your records without manual entry&lt;/li&gt;
&lt;li&gt;Sending timed follow-up messages to customers who haven't responded in 48 hours&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The payoff isn't just time — it's consistency. A workflow doesn't have a bad day. It doesn't forget the step. If you've ever had a lead fall through because someone meant to follow up and didn't, this is the fix.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Make Data-Driven Decisions with AI-Powered Insights&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Most small business owners are making decisions based on gut feel plus a spreadsheet they update when they remember to. That's not a knock — it's just the reality when you're stretched thin. The problem is that gut feel doesn't catch the slow bleeds: the product category quietly losing margin, the ad channel that stopped converting three weeks ago, the customer segment that churns at twice the rate of everyone else.&lt;/p&gt;

&lt;p&gt;[Product Name] surfaces this automatically, analyzing your connected data and flagging what actually matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which customer segments are buying more, and which ones are drifting&lt;/li&gt;
&lt;li&gt;Where your conversion rate is dropping in the purchase funnel&lt;/li&gt;
&lt;li&gt;Revenue trends broken down by channel, product, or time period — without you having to build the report&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what separates businesses that grow intentionally from ones that grow by accident and then wonder why Q3 was brutal.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Enhance Customer Experience with AI-Driven Chatbots&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here's an uncomfortable truth: most small business websites go dark after 5pm. A potential customer has a question about your services at 9pm on a Tuesday, gets no response, and books your competitor by morning. You never even knew they were there.&lt;/p&gt;

&lt;p&gt;[Product Name]'s chatbot layer plugs that gap without making you hire a night-shift support rep. You train it on your own content — your FAQ, your pricing, your policies — and it handles the front line:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instant answers to the questions you get asked every single day&lt;/li&gt;
&lt;li&gt;Smooth handoffs to a human when the issue needs real judgment&lt;/li&gt;
&lt;li&gt;Sentiment tracking across conversations so you can spot patterns in what's frustrating your customers before it becomes a review problem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This matters most for service businesses where trust is the product. A fast, accurate response at 9pm says you're professional. A form that says "we'll get back to you in 2 business days" says you're not.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Get Started with [Product Name] Today&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The owners I've seen get the most out of tools like this aren't the most tech-savvy — they're the ones who are honest about where their time is actually going. If you're doing tasks a well-configured system could handle, every hour you spend on them is an hour you're not selling, building, or thinking.&lt;/p&gt;

&lt;p&gt;[Product Name] pulls automation, analytics, and customer support into one place without requiring you to stitch together five different subscriptions and a Zapier account.&lt;/p&gt;

&lt;p&gt;Check the latest price and reviews on Amazon: &lt;a href="https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup takes an afternoon. The time you get back compounds every week after that.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Support This Content
&lt;/h2&gt;

&lt;p&gt;If this guide saved you time or money, a crypto tip keeps J.A.M.E.S. running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BTC:&lt;/strong&gt; &lt;code&gt;1B2xp9fu6eVNBiAByikcQYS569LeU1EVL7&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ETH:&lt;/strong&gt; &lt;code&gt;0x3a0419a218078751f4a210d2f3835a672fa4bf91&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOL:&lt;/strong&gt; &lt;code&gt;9Ga6JioPVtGCiuvWfc2VCCbN61WLNCkm6S1qFRVn38sG&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Every tip goes directly toward research, tools, and keeping the lights on. Thank you.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aitools</category>
      <category>productivity</category>
      <category>review</category>
    </item>
    <item>
      <title>AI tools Guide</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Sat, 23 May 2026 16:19:11 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/ai-tools-guide-1ao3</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/ai-tools-guide-1ao3</guid>
      <description>&lt;p&gt;&lt;strong&gt;Unlock the Full Potential of Your Business with the Best AI Tools: AI-Powered Solutions for Increased Efficiency and Growth&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Are you tired of struggling with manual processes and tedious tasks at the office? Do you dream of streamlining your workflow, enhancing decision-making, and driving business growth? If so, you're in the right place! Within this article, we'll delve into the world of AI tools, exploring the benefits, features, and real-world applications of the top AI-powered solutions available today. You'll learn how to leverage AI tools to maximize efficiency, productivity, and profits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefit 1: Automate Repetitive Tasks with AI-Powered Efficiency&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using AI tools allows you to automate repetitive, mundane tasks, freeing up your valuable time for more complex, strategic initiatives. Many AI tools provide features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Natural Language Processing (NLP) for automatic data entry and processing&lt;/li&gt;
&lt;li&gt;Predictive analytics to forecast sales trends and customer behavior&lt;/li&gt;
&lt;li&gt;Machine Learning (ML) to optimize workflows, improve accuracy, and reduce errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Say goodbye to tedious data entry and hello to more time spent on high-leverage activities like business strategy and growth planning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefit 2: Enhance Decision-Making with AI-Driven Insights&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI tools can help you make informed, data-driven decisions by analyzing vast amounts of data and providing actionable insights. With the power of AI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Analyze customer feedback, reviews, and sentiment to identify areas for improvement&lt;/li&gt;
&lt;li&gt;Predict customer churn and take targeted actions to retain them&lt;/li&gt;
&lt;li&gt;Forecast sales and revenue, ensuring you're always prepared for the future&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay one step ahead of the competition with the knowledge and insights AI tools provide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefit 3: Scale Your Business with AI-Powered Insights&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI tools enable you to scale your business by identifying opportunities, predicting growth areas, and optimizing your operations. With the right AI tools, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Predict customer behavior and buying patterns to target marketing efforts effectively&lt;/li&gt;
&lt;li&gt;Identify areas for cost reduction and optimize resource allocation&lt;/li&gt;
&lt;li&gt;Use sentiment analysis to stay on top of market trends and competitors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scale your business confidently with AI as your trusted guide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefit 4: Improve Customer Experience with AI-Driven Personalization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI tools help you deliver personalized experiences to your customers, setting you apart in a crowded market. By:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Analyzing customer behavior and preferences to offer targeted recommendations&lt;/li&gt;
&lt;li&gt;Identifying sentiment and pain points to improve support experiences&lt;/li&gt;
&lt;li&gt;Anticipating needs and delivering seamless, intuitive interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create loyal customers and drive business growth with AI-driven personalization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choosing the Right AI Tool for Your Business&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When selecting an AI tool, consider the specific needs and pain points of your business. If you're a small to medium-sized enterprise (SME), look for user-friendly tools that integrate with your existing infrastructure. If you're a larger business, you may require more advanced features and customization options.&lt;/p&gt;

&lt;p&gt;Some popular AI tools in the market today include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Amazon SageMaker - For businesses looking to build and deploy machine learning models&lt;/li&gt;
&lt;li&gt;Google Cloud AI Platform - Ideal for integrating AI with cloud infrastructure&lt;/li&gt;
&lt;li&gt;Microsoft Azure Machine Learning - Suitable for developing, managing, and deploying machine learning models&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  In an increasingly competitive market, harnessing the power of AI tools has become a must-have for businesses looking to stay ahead of the curve. By automating repetitive tasks, enhancing decision-making, scaling your business, and improving customer experiences with AI-driven personalization, you'll unlock the full potential of your business. So why wait? Explore the best AI tools today, starting with Amazon &lt;a href="https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20&lt;/a&gt; to find the perfect solution for your organization.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Support This Content
&lt;/h2&gt;

&lt;p&gt;If this guide saved you time or money, a crypto tip keeps J.A.M.E.S. running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BTC:&lt;/strong&gt; &lt;code&gt;1B2xp9fu6eVNBiAByikcQYS569LeU1EVL7&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ETH:&lt;/strong&gt; &lt;code&gt;0x3a0419a218078751f4a210d2f3835a672fa4bf91&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOL:&lt;/strong&gt; &lt;code&gt;9Ga6JioPVtGCiuvWfc2VCCbN61WLNCkm6S1qFRVn38sG&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Every tip goes directly toward research, tools, and keeping the lights on. Thank you.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aitools</category>
      <category>productivity</category>
      <category>review</category>
    </item>
    <item>
      <title>AI tools Guide</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Sat, 23 May 2026 15:54:23 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/ai-tools-guide-3goj</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/ai-tools-guide-3goj</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;I Stopped Using 14 Browser Tabs to Manage My Day. Here's What Changed.&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Last March, I tracked how I actually spent a Tuesday. Not how I thought I spent it — how I actually spent it. The results were embarrassing: 47 minutes hunting for files I'd "just saved," 90 minutes in my inbox doing nothing that moved the needle, and maybe three genuine hours of real work. I'm a solo operator running a small agency. That was my whole Tuesday.&lt;/p&gt;

&lt;p&gt;That's when I got serious about AI tools — not the hype version, but the practical, keep-your-sanity version. What follows is what I actually use them for, and why it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. Time Management That Shows You the Ugly Truth&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Most people think they have a productivity problem. What they actually have is a visibility problem — they don't know where the time is going until it's gone.&lt;/p&gt;

&lt;p&gt;AI-driven workflow tools like &lt;a href="https://dev.tolink%20to%20the%20AI%20tool"&gt;https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20&lt;/a&gt; sit on top of your calendar and task list and show you patterns you'd never catch manually. After two weeks of data, mine told me I was scheduling deep work at 2pm — which is, for me, a biologically terrible idea. I'm sharp from 8–11am and again around 7pm. I had it exactly backwards.&lt;/p&gt;

&lt;p&gt;Concrete things these tools surface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which recurring tasks are eating more time than you've budgeted — often by a factor of 2–3x&lt;/li&gt;
&lt;li&gt;Where your week fragments into too many context switches (the real productivity killer, not "not working hard enough")&lt;/li&gt;
&lt;li&gt;Whether your deadlines are realistic given your actual historical pace — not the optimistic version in your head&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't motivational-poster stuff. It's operational intelligence, and once you see it, you can't unsee it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. AI as a Creative Collaborator, Not a Replacement&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There's a version of AI-assisted creative work that makes everything sound the same. That's the wrong way to use it.&lt;/p&gt;

&lt;p&gt;The right way: you bring the idea, the angle, the voice — and the AI fills in the gaps or pressure-tests your thinking. I use it to draft the first ugly version of a proposal so I'm reacting and editing instead of staring at a blank page. I use it to catch logical holes in a pitch before a client does. I use it to generate three alternative framings of the same idea so I can pick the strongest one.&lt;/p&gt;

&lt;p&gt;What this looks like in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feed it your half-formed outline and get back a structure you can tear apart and rebuild&lt;/li&gt;
&lt;li&gt;Paste in a draft and ask what the weakest argument is — the answer is almost always right&lt;/li&gt;
&lt;li&gt;Use it to generate variations on a headline or CTA before you commit to the first thing you wrote&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output is rarely usable as-is. That's not the point. The point is you spend 20 minutes refining instead of 90 minutes starting from zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Automation That Actually Reduces the Cognitive Load&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Collaboration tools promise to streamline communication. Most of them just add another place to check. AI-layered automation is different because it reduces the number of decisions you have to make, not just the number of clicks.&lt;/p&gt;

&lt;p&gt;A few things that genuinely work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Triage-level email sorting that flags the 8 messages that actually need a response today and buries the rest — I check email twice a day now instead of constantly&lt;/li&gt;
&lt;li&gt;Recurring task automation that handles the "did I send the follow-up?" anxiety by just doing it&lt;/li&gt;
&lt;li&gt;Draft responses for common messages that you review and send in 10 seconds instead of composing from scratch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cumulative effect isn't dramatic on any given day. Over a month, I got back somewhere around six hours. That's almost a full workday — recovered from small friction that I'd just accepted as normal.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;4. Making Decisions With Data You Already Have&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The most underused resource in most small operations is the data that's already sitting there. Open rates, response times, which services clients actually ask about, which days proposals close — it's all there, and almost nobody looks at it systematically.&lt;/p&gt;

&lt;p&gt;AI tools can process that backlog in minutes and surface the two or three things worth acting on. For me, that meant discovering that 80% of my closed deals came from referrals I'd followed up on within 24 hours. I'd been treating follow-up as optional. It wasn't.&lt;/p&gt;

&lt;h3&gt;
  
  
  When This Actually Makes Sense to Buy
&lt;/h3&gt;

&lt;p&gt;If you're running a one-person operation, a small team, or managing a side business alongside a full-time job, the calculus is simple: your time is the constraint, and anything that removes low-value decisions from your plate compounds over weeks and months.&lt;/p&gt;

&lt;p&gt;The scenario where I'd most recommend pulling the trigger: you're doing work you're good at, but you feel like the operational layer around that work — scheduling, communication, planning, documentation — is eating you alive. That's exactly the problem these tools are designed for.&lt;/p&gt;

&lt;p&gt;The scenario where I'd hold off: you're still figuring out your actual workflow and priorities. AI tools amplify what you're already doing. If what you're doing is unclear, they'll amplify the chaos too. Get the basics stable first.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;AI tools didn't fix my productivity. I had to fix my habits first. But once the fundamentals were in place — knowing what I was supposed to be doing and when — having a layer of intelligence to handle the surrounding noise made a measurable difference. Not a motivational-speech difference. An actual, trackable, Tuesday-was-better-than-last-Tuesday difference.&lt;/p&gt;

&lt;p&gt;If you're at that point, these tools are worth a serious look.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Ready to see what it can do for your workflow? Check the latest price and reviews on Amazon: &lt;a href="https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20&lt;/a&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Support This Content
&lt;/h2&gt;

&lt;p&gt;If this guide saved you time or money, a crypto tip keeps J.A.M.E.S. running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BTC:&lt;/strong&gt; &lt;code&gt;1B2xp9fu6eVNBiAByikcQYS569LeU1EVL7&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ETH:&lt;/strong&gt; &lt;code&gt;0x3a0419a218078751f4a210d2f3835a672fa4bf91&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOL:&lt;/strong&gt; &lt;code&gt;9Ga6JioPVtGCiuvWfc2VCCbN61WLNCkm6S1qFRVn38sG&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Every tip goes directly toward research, tools, and keeping the lights on. Thank you.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aitools</category>
      <category>productivity</category>
      <category>review</category>
    </item>
    <item>
      <title>Revolutionizing Productivity with AI Tools: AI Writer Pro</title>
      <dc:creator>milton rojas</dc:creator>
      <pubDate>Sat, 23 May 2026 12:11:23 +0000</pubDate>
      <link>https://dev.to/milton_rojas_6bdc219110e9/revolutionizing-productivity-with-ai-tools-ai-writer-pro-2hln</link>
      <guid>https://dev.to/milton_rojas_6bdc219110e9/revolutionizing-productivity-with-ai-tools-ai-writer-pro-2hln</guid>
      <description>&lt;h1&gt;
  
  
  Revolutionizing Productivity with AI Tools: AI Writer Pro
&lt;/h1&gt;

&lt;p&gt;===========================================================&lt;/p&gt;

&lt;p&gt;Are you tired of writing and editing tasks eating into your valuable time? Do you struggle to come up with engaging content that resonates with your audience? If so, you're not alone. As a busy professional, entrepreneur, or small business owner, finding the right tools to streamline your workflow can be a game-changer. In this article, we'll explore the benefits of using AI tools, specifically focusing on AI Writer Pro, a powerful addition to any content creation arsenal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improved Content Generation with AI Writer Pro
&lt;/h2&gt;




&lt;p&gt;AI Writer Pro is an innovative AI tool designed to supercharge your writing and editing processes. This software harnesses the power of artificial intelligence to help you generate high-quality content, from blog posts to social media posts and beyond. What sets AI Writer Pro apart is its ability to learn your writing style and preferences over time, ensuring that the content it generates is tailored to your unique voice and tone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features of AI Writer Pro:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Content Generation&lt;/strong&gt;: AI Writer Pro can generate well-researched and engaging content on a wide range of topics, saving you time and effort.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content Editing&lt;/strong&gt;: The tool's advanced editing capabilities help refine your writing, ensuring that your final product is polished and error-free.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Style Guidance&lt;/strong&gt;: AI Writer Pro learns your writing style and preferences, enabling it to produce content that resonates with your audience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Enhanced Productivity with AI-Powered Tasks
&lt;/h2&gt;




&lt;p&gt;By leveraging AI-powered tasks, you can free up more time to focus on high-leverage activities, such as strategy, creativity, and client engagement. AI Writer Pro helps you tackle tasks like research, outlining, and content optimization, allowing you to:&lt;/p&gt;

&lt;h3&gt;
  
  
  Automate Repetitive Tasks:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Research Assistance&lt;/strong&gt;: AI Writer Pro can quickly gather and summarize relevant information on a given topic, saving you hours of research time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outlining and Organization&lt;/strong&gt;: The tool helps you structure your content, creating a logical and coherent outline that guides your writing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparing AI Writer Pro to Other AI Tools
&lt;/h2&gt;




&lt;p&gt;When choosing an AI tool, it's essential to consider factors like usability, content quality, and flexibility. Compared to other AI writing tools, AI Writer Pro stands out for its ease of use, robust feature set, and ability to integrate with popular writing platforms. Whether you're a seasoned writer or a content beginner, AI Writer Pro is designed to meet your needs and help you achieve your writing goals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Small Businesses&lt;/strong&gt;: AI Writer Pro is perfect for small businesses looking to create engaging blog content, social media posts, or product descriptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freelancers&lt;/strong&gt;: Freelance writers and editors can use AI Writer Pro to generate high-quality content quickly, allowing them to work on multiple projects simultaneously.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion and Recommendation
&lt;/h2&gt;




&lt;h2&gt;
  
  
  In conclusion, AI Writer Pro is a valuable addition to any content creation workflow. By leveraging the power of AI tools, you can significantly improve your productivity, content quality, and overall writing experience. If you're ready to unlock the full potential of AI Writer Pro, check the latest price and reviews on Amazon: &lt;a href="https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20" rel="noopener noreferrer"&gt;https://www.amazon.com/s?k=AI%20tools&amp;amp;tag=james-default-20&lt;/a&gt;. With its intuitive interface, robust features, and excellent content generation capabilities, AI Writer Pro is an investment that will pay dividends for years to come.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Support This Content
&lt;/h2&gt;

&lt;p&gt;If this guide saved you time or money, a crypto tip keeps J.A.M.E.S. running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BTC:&lt;/strong&gt; &lt;code&gt;1B2xp9fu6eVNBiAByikcQYS569LeU1EVL7&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ETH:&lt;/strong&gt; &lt;code&gt;0x3a0419a218078751f4a210d2f3835a672fa4bf91&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOL:&lt;/strong&gt; &lt;code&gt;9Ga6JioPVtGCiuvWfc2VCCbN61WLNCkm6S1qFRVn38sG&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Every tip goes directly toward research, tools, and keeping the lights on. Thank you.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aitools</category>
      <category>productivity</category>
      <category>review</category>
    </item>
  </channel>
</rss>
