<?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: Positive Matician</title>
    <description>The latest articles on DEV Community by Positive Matician (@positive_matician).</description>
    <link>https://dev.to/positive_matician</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1799782%2Fae3c1419-0039-4493-9311-0553f12ee96d.jpg</url>
      <title>DEV Community: Positive Matician</title>
      <link>https://dev.to/positive_matician</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/positive_matician"/>
    <language>en</language>
    <item>
      <title>I got tired of watching my terminal, so I built GuGa</title>
      <dc:creator>Positive Matician</dc:creator>
      <pubDate>Fri, 03 Apr 2026 12:02:25 +0000</pubDate>
      <link>https://dev.to/positive_matician/i-got-tired-of-watching-my-terminal-so-i-built-guga-f8j</link>
      <guid>https://dev.to/positive_matician/i-got-tired-of-watching-my-terminal-so-i-built-guga-f8j</guid>
      <description>&lt;p&gt;I lost count of how many times I've started a long training run, gone to make coffee, come back ten minutes later, and found it had crashed thirty seconds after I left. Or worse — left it running overnight, woken up, and had no idea if it finished two hours ago or is still grinding away.&lt;/p&gt;

&lt;p&gt;The usual suggestions are: set up a Discord webhook, use a Slack bot, write a wrapper script that sends an email. All of which require accounts, tokens, configuration, and maintenance. I just wanted my phone to buzz when my code was done.&lt;/p&gt;

&lt;p&gt;So I spent last weekend building GuGa Nexus.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;You prefix any terminal command with &lt;code&gt;guga&lt;/code&gt; and when it finishes, a notification hits your phone or browser with the exit status, elapsed time, and the last line of output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;guga python train.py &lt;span class="nt"&gt;--epochs&lt;/span&gt; 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When training finishes, you get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ python train.py done — 2h 14m
Epoch 100/100 — accuracy: 0.9431
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if it crashed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❌ python train.py failed (exit 1) — 43s
CUDA out of memory. Tried to allocate 2.00 GiB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last line of stdout is the part I find most useful. You don't have to go back to the terminal to find out what happened — the relevant output is right in the notification.&lt;/p&gt;

&lt;p&gt;It also works as a plain pipe for quick messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Deploy done"&lt;/span&gt; | guga
guga &lt;span class="s2"&gt;"Checkpoint saved"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;GuGa runs a small Flask + Socket.IO server on your Linux machine as a systemd daemon. When you call &lt;code&gt;guga&lt;/code&gt;, it POSTs to that local server, which relays the message over an encrypted WebSocket to whatever clients are connected.&lt;/p&gt;

&lt;p&gt;For internet access it uses a Cloudflare Tunnel — so your phone can receive notifications even when you're not on the same network, with no domain purchase, no port forwarding, and no VPS. The tunnel URL is ephemeral and everything is AES-256-GCM encrypted end to end.&lt;/p&gt;

&lt;p&gt;The server exposes a browser client too, so you don't need to install anything on your phone if you don't want to. Open the URL in any browser and notifications stream in real time. There's also an Android app for persistent background notifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;guga
guga &lt;span class="nt"&gt;--install-service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--install-service&lt;/code&gt; asks two questions — LAN or internet mode, and whether you want OS notifications forwarded — then sets up the systemd daemon, downloads cloudflared if needed, and prints the pairing QR code. That's the entire setup.&lt;/p&gt;

&lt;p&gt;After that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;guga &lt;span class="nt"&gt;--qr&lt;/span&gt;         &lt;span class="c"&gt;# get your connection URL / QR code&lt;/span&gt;
guga &lt;span class="nt"&gt;--show-pin&lt;/span&gt;   &lt;span class="c"&gt;# get your pairing PIN for first connection&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the URL in a browser or scan it with the Android app, enter the PIN, and you're live.&lt;/p&gt;

&lt;h2&gt;
  
  
  The OS notification forwarding
&lt;/h2&gt;

&lt;p&gt;One feature that surprised me by being more useful than I expected: if you enable it during setup, GuGa listens to your Linux desktop's D-Bus notification bus and forwards every system notification to your phone in real time. Calendar reminders, build completions, anything your OS surfaces. It runs alongside the server automatically.&lt;/p&gt;

&lt;p&gt;I'm planning urgency-based filtering for this — critical alerts instant, low-priority ones bundled into a digest — but for now it forwards everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's not perfect yet
&lt;/h2&gt;

&lt;p&gt;I want to be upfront about one limitation: &lt;code&gt;guga --show-pin&lt;/code&gt; retrieves the latest pending pairing PIN from the server. This assumes only one device is trying to pair at a time. If multiple devices hit the pairing endpoint simultaneously, multiple PINs get generated and &lt;code&gt;--show-pin&lt;/code&gt; would only show the latest one.&lt;/p&gt;

&lt;p&gt;The fix I'm working on inverts the model — the connecting device generates and displays its own PIN, sends it to the server, and the user confirms the one they see on their own screen. This way the server never generates PINs and concurrent attempts can't interfere with each other. Until that lands, pairing over LAN first is the safe approach.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/PositiveMatician/GuGa-Nexus" rel="noopener noreferrer"&gt;github.com/PositiveMatician/GuGa-Nexus&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PyPI: &lt;a href="https://pypi.org/project/GuGa" rel="noopener noreferrer"&gt;pypi.org/project/GuGa&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Android app: in the &lt;a href="https://github.com/PositiveMatician/GuGa-Nexus/releases" rel="noopener noreferrer"&gt;releases section&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you try it I'd genuinely like to know where the setup flow breaks or what's confusing — this is still early and real feedback is more useful than stars right now.&lt;/p&gt;

</description>
      <category>python</category>
      <category>linux</category>
      <category>android</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
