<?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: Manraaj Singh</title>
    <description>The latest articles on DEV Community by Manraaj Singh (@umbradomini).</description>
    <link>https://dev.to/umbradomini</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%2F3875548%2F64efe825-f29f-4b47-9255-8f4b9eeb2aaf.png</url>
      <title>DEV Community: Manraaj Singh</title>
      <link>https://dev.to/umbradomini</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/umbradomini"/>
    <language>en</language>
    <item>
      <title>I Got Tired of Flashing My Pico Manually, So I Built a GUI</title>
      <dc:creator>Manraaj Singh</dc:creator>
      <pubDate>Sun, 12 Apr 2026 22:15:35 +0000</pubDate>
      <link>https://dev.to/umbradomini/i-got-tired-of-flashing-my-pico-manually-so-i-built-a-gui-373</link>
      <guid>https://dev.to/umbradomini/i-got-tired-of-flashing-my-pico-manually-so-i-built-a-gui-373</guid>
      <description>&lt;p&gt;If you've ever set up a &lt;a href="https://github.com/dbisu/pico-ducky" rel="noopener noreferrer"&gt;pico-ducky&lt;/a&gt; — a Raspberry Pi Pico turned into a USB Rubber Ducky — you know the process. Hold BOOTSEL, plug in, copy a nuke file, wait for it to remount, copy CircuitPython, wait again, copy all the project files and libraries, then arm a payload. Every. Single. Time.&lt;/p&gt;

&lt;p&gt;It's not hard. It's just annoying.&lt;/p&gt;

&lt;p&gt;I was doing this enough that I wrote a bash script to automate it. That helped. But then I started wanting a payload manager, a built-in editor, a live device indicator — and at that point a bash script wasn't cutting it anymore. So I rewrote the whole thing as a desktop app.&lt;/p&gt;

&lt;p&gt;That's pico-flash-gui.&lt;/p&gt;




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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fve033qqe6k0mt6zwhbwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fve033qqe6k0mt6zwhbwg.png" alt="First-time Setup" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's an Electron app for Linux that automates the full pico-ducky flash workflow. You click &lt;strong&gt;Start Flash&lt;/strong&gt;, hold BOOTSEL on your Pico and plug it in, and the app takes over:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Detects the Pico in BOOTSEL mode&lt;/li&gt;
&lt;li&gt;Wipes the flash with &lt;code&gt;flash_nuke.uf2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Flashes the latest stable CircuitPython for your board&lt;/li&gt;
&lt;li&gt;Copies all pico-ducky project files and Adafruit libraries&lt;/li&gt;
&lt;li&gt;Asks you to pick a payload to arm — or skip&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole thing runs unattended. You don't touch anything between steps 2 and 5.&lt;/p&gt;

&lt;p&gt;On first launch it also downloads every dependency automatically — CircuitPython firmware, pico-ducky source files, Adafruit libraries. Everything is cached so subsequent flashes are instant.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhwj1eewaqe1fw0v4bdd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhwj1eewaqe1fw0v4bdd.png" alt="Automatic Dependency Download" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Supports Pico, Pico W, Pico 2, and Pico 2 W.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setup Mode
&lt;/h2&gt;

&lt;p&gt;Flash Mode is for when you want to wipe and reflash. But sometimes you just want to swap the armed payload, or grab a file off the device without nuking it.&lt;/p&gt;

&lt;p&gt;That's what Setup Mode is for. Bridge GP0 to GND before plugging in (this suppresses payload execution so the Pico mounts as a normal drive), and the app detects the CIRCUITPY volume and gives you four options:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48a5u0kbe6g72bwbdn4c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48a5u0kbe6g72bwbdn4c.png" alt="Flash Mode" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Swap Payload&lt;/strong&gt; — replace the active &lt;code&gt;.dd&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Download File&lt;/strong&gt; — pull any file off the Pico to your computer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eject&lt;/strong&gt; — safely unmount before unplugging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full Reflash&lt;/strong&gt; — go back through Flash Mode&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Payload management
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexly43w23xlqygyeq16w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexly43w23xlqygyeq16w.png" alt="Payload Management" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a full payload panel built into the app. You can import &lt;code&gt;.dd&lt;/code&gt; or &lt;code&gt;.txt&lt;/code&gt; files, write payloads from scratch in a built-in editor, edit existing ones, and delete them. The armed payload is tracked across sessions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3r4qfiw9nyvrjpjtupb6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3r4qfiw9nyvrjpjtupb6.png" alt="Payload Editor" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Pico W boards there's also a Wi-Fi settings panel — you can update the SSID and password on an already-flashed device without reflashing it.&lt;/p&gt;




&lt;h2&gt;
  
  
  How it's built
&lt;/h2&gt;

&lt;p&gt;It's Electron with plain HTML/CSS/JS — no frontend framework. The backend (main process) handles all the hardware interaction: file copies, shell commands for mounting/unmounting, polling for device status every 2 seconds.&lt;/p&gt;

&lt;p&gt;The Electron security setup is done properly — &lt;code&gt;contextIsolation: true&lt;/code&gt;, &lt;code&gt;nodeIntegration: false&lt;/code&gt;, and a &lt;code&gt;contextBridge&lt;/code&gt; preload that only exposes specific named functions to the renderer. No raw IPC access from the frontend.&lt;/p&gt;

&lt;p&gt;One thing I'm reasonably happy with is how clean the flash sequence ended up. The flasher waits for mounts and unmounts using a polling loop rather than arbitrary timeouts, so it actually adapts to how long the hardware takes rather than just hoping a fixed delay is long enough.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Umbra-Domini/pico-flash-gui.git
&lt;span class="nb"&gt;cd &lt;/span&gt;pico-flash-gui
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requires Linux, Node.js v18+, and &lt;code&gt;unzip&lt;/code&gt;. Tested on Ubuntu 22.04 and 24.04.&lt;/p&gt;

&lt;p&gt;An AppImage build is coming soon so you won't need Node at all.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This tool is for use on devices you own.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/Umbra-Domini/pico-flash-gui" rel="noopener noreferrer"&gt;Umbra-Domini/pico-flash-gui&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built because I was tired of doing it by hand. Happy to hear feedback or answer questions in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>cybersecurity</category>
      <category>raspberrypi</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
