<?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>Forem: Anas Abuelhaag</title>
    <description>The latest articles on Forem by Anas Abuelhaag (@a_elhaag).</description>
    <link>https://forem.com/a_elhaag</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%2F1345241%2F350253a3-9f91-4548-a4fa-c56b13d6cf41.jpeg</url>
      <title>Forem: Anas Abuelhaag</title>
      <link>https://forem.com/a_elhaag</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/a_elhaag"/>
    <language>en</language>
    <item>
      <title>Build for Your Community: CampusOps - Event Management for Student Activities</title>
      <dc:creator>Anas Abuelhaag</dc:creator>
      <pubDate>Mon, 02 Mar 2026 00:34:31 +0000</pubDate>
      <link>https://forem.com/a_elhaag/build-for-your-community-campusops-event-management-for-student-activities-4f9h</link>
      <guid>https://forem.com/a_elhaag/build-for-your-community-campusops-event-management-for-student-activities-4f9h</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/weekend-2026-02-28"&gt;DEV Weekend Challenge: Community&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Community
&lt;/h2&gt;

&lt;p&gt;I built this for university student activities and campus clubs. Managing events as a student organizer is often chaotic. You have to juggle marketing, logistics, catering, and keeping track of RSVPs—usually scattered across WhatsApp groups, Google Forms, and messy spreadsheets. This app is dedicated to the incredible community of student leaders who tirelessly organize events, workshops, and gatherings on campus, making student life vibrant and engaging.&lt;/p&gt;

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

&lt;p&gt;CampusOps is a sleek, premium event management and operation dashboard designed specifically for student organizations to solve the friction of planning events. It provides a centralized hub to manage every aspect of an event without forcing users to go through tedious signup processes.&lt;/p&gt;

&lt;p&gt;It features a streamlined three-level access model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Public View:&lt;/strong&gt; A beautiful landing page where students can discover upcoming campus events and RSVP seamlessly (with built-in duplicate prevention).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organizer Dashboard:&lt;/strong&gt; Accessed via a secure, easily shareable &lt;code&gt;organizer_code&lt;/code&gt;, this view gives event staff a real-time Kanban board to track tasks (across teams like Logistics, Marketing, Registration) and manage attendee check-ins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admin Control:&lt;/strong&gt; Accessed via an &lt;code&gt;admin_code&lt;/code&gt;, admins can create new events, dynamically generate access codes for their organizing team, and oversee all global operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rapid Deployment Form:&lt;/strong&gt; From the homepage, any authorized student can 'Initialize a Hub' by filling out a quick, elegant form (event title, date, location, and capacity) to instantly spin up a completely new event dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Portability (Export Everything):&lt;/strong&gt; At any point during or after an event, organizers can click the Export Excel button in their attendee table to instantly download all RSVP and check-in data to a CSV. This makes it insanely easy to generate post-event reports or sync lists with campus administration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To top it off, CampusOps features a modern, "liquid glass" neumorphic UI that makes organizing events feel less like a chore and more like a premium software experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;You can try out the live web application here: &lt;a href="https://campus-ops.vercel.app" rel="noopener noreferrer"&gt;https://campus-ops.vercel.app&lt;/a&gt;&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%2Fxwh4qzyxu1cgrowji1fk.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%2Fxwh4qzyxu1cgrowji1fk.png" alt=" "&gt;&lt;/a&gt;&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%2Ffcbhbbdiqnqe828zrlkq.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%2Ffcbhbbdiqnqe828zrlkq.png" alt=" "&gt;&lt;/a&gt;&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%2Ficqbeh9yckcbolnp33yi.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%2Ficqbeh9yckcbolnp33yi.png" alt=" "&gt;&lt;/a&gt;&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%2F2ctda32azs7tae77uwdd.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%2F2ctda32azs7tae77uwdd.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Here is the full source code for the project: 

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/a-elhaag" rel="noopener noreferrer"&gt;
        a-elhaag
      &lt;/a&gt; / &lt;a href="https://github.com/a-elhaag/campus_ops" rel="noopener noreferrer"&gt;
        campus_ops
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;This is a &lt;a href="https://nextjs.org" rel="nofollow noopener noreferrer"&gt;Next.js&lt;/a&gt; project bootstrapped with &lt;a href="https://nextjs.org/docs/app/api-reference/cli/create-next-app" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;create-next-app&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Getting Started&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;First, run the development server:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run dev
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or&lt;/span&gt;
yarn dev
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or&lt;/span&gt;
pnpm dev
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or&lt;/span&gt;
bun dev&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Open &lt;a href="http://localhost:3000" rel="nofollow noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; with your browser to see the result.&lt;/p&gt;
&lt;p&gt;You can start editing the page by modifying &lt;code&gt;app/page.tsx&lt;/code&gt;. The page auto-updates as you edit the file.&lt;/p&gt;
&lt;p&gt;This project uses &lt;a href="https://nextjs.org/docs/app/building-your-application/optimizing/fonts" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;next/font&lt;/code&gt;&lt;/a&gt; to automatically optimize and load &lt;a href="https://vercel.com/font" rel="nofollow noopener noreferrer"&gt;Geist&lt;/a&gt;, a new font family for Vercel.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Learn More&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;To learn more about Next.js, take a look at the following resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org/docs" rel="nofollow noopener noreferrer"&gt;Next.js Documentation&lt;/a&gt; - learn about Next.js features and API.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org/learn" rel="nofollow noopener noreferrer"&gt;Learn Next.js&lt;/a&gt; - an interactive Next.js tutorial.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can check out &lt;a href="https://github.com/vercel/next.js" rel="noopener noreferrer"&gt;the Next.js GitHub repository&lt;/a&gt; - your feedback and contributions are welcome!&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Deploy on Vercel&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;The easiest way to deploy your Next.js app is to use the &lt;a href="https://vercel.com/new?utm_medium=default-template&amp;amp;filter=next.js&amp;amp;utm_source=create-next-app&amp;amp;utm_campaign=create-next-app-readme" rel="nofollow noopener noreferrer"&gt;Vercel Platform&lt;/a&gt; from the creators of Next.js.&lt;/p&gt;
&lt;p&gt;Check out our &lt;a href="https://nextjs.org/docs/app/building-your-application/deploying" rel="nofollow noopener noreferrer"&gt;Next.js deployment documentation&lt;/a&gt; for more…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/a-elhaag/campus_ops" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;CampusOps was built with a modern, full-stack ecosystem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; Next.js (App Router) for seamless full-stack React development and API routes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; PostgreSQL hosted on Neon, which provided fast, reliable, and incredibly smooth serverless database provisioning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ORM:&lt;/strong&gt; Prisma for elegant, type-safe database schema and queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling:&lt;/strong&gt; Tailwind CSS combined with custom CSS rules to achieve the sophisticated liquid glass / neumorphic UI design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Package Manager:&lt;/strong&gt; pnpm for fast dependency resolution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture:&lt;/strong&gt; The app uses zero-auth, code-based access control. This makes it incredibly fast to deploy and share among student teams with zero onboarding friction.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Built with Google Gemini: Handheld Arcade Console with Raspberry Pi Pico</title>
      <dc:creator>Anas Abuelhaag</dc:creator>
      <pubDate>Thu, 26 Feb 2026 13:06:58 +0000</pubDate>
      <link>https://forem.com/a_elhaag/built-with-google-gemini-handheld-arcade-console-with-raspberry-pi-pico-4iki</link>
      <guid>https://forem.com/a_elhaag/built-with-google-gemini-handheld-arcade-console-with-raspberry-pi-pico-4iki</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/mlh-built-with-google-gemini-02-25-26"&gt;Built with Google Gemini: Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built with Google Gemini
&lt;/h2&gt;

&lt;p&gt;For this project, I designed and implemented a handheld arcade console powered by a Raspberry Pi Pico (RP2040) and developed entirely in MicroPython. Instead of building another web-based application, I focused on a physical embedded system that integrates hardware interfacing, real-time rendering, and structured game logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Hardware Architecture
&lt;/h3&gt;

&lt;p&gt;The console architecture consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RP2040&lt;/strong&gt; (Raspberry Pi Pico)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ST7789 240×240 SPI TFT Display&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analog joystick&lt;/strong&gt; connected via ADC0 (GPIO26) and ADC1 (GPIO27)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two action buttons&lt;/strong&gt; using internal pull-ups (GPIO3, GPIO10)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PWM-driven buzzer&lt;/strong&gt; on GPIO21&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of this hardware layer, I developed &lt;strong&gt;seven fully playable games&lt;/strong&gt;: Snake, Pong, Space Shooter, Flappy Bird, Dodger, Cave Flyer, and Dino Runner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardware Planning, Wiring, and Pin Configuration
&lt;/h2&gt;

&lt;p&gt;Before wiring the system, I used Gemini to reason through GPIO selection and ensure the wiring scheme aligned directly with the MicroPython initialization code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pin Mapping Table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pico GPIO&lt;/th&gt;
&lt;th&gt;Peripheral&lt;/th&gt;
&lt;th&gt;Connection&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPIO6&lt;/td&gt;
&lt;td&gt;SPI SCK&lt;/td&gt;
&lt;td&gt;ST7789 SCK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPIO7&lt;/td&gt;
&lt;td&gt;SPI MOSI&lt;/td&gt;
&lt;td&gt;ST7789 MOSI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPIO13&lt;/td&gt;
&lt;td&gt;SPI CS&lt;/td&gt;
&lt;td&gt;ST7789 CS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPIO11&lt;/td&gt;
&lt;td&gt;Data/Command&lt;/td&gt;
&lt;td&gt;ST7789 DC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPIO12&lt;/td&gt;
&lt;td&gt;Reset&lt;/td&gt;
&lt;td&gt;ST7789 RST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPIO26&lt;/td&gt;
&lt;td&gt;ADC0&lt;/td&gt;
&lt;td&gt;Joystick X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPIO27&lt;/td&gt;
&lt;td&gt;ADC1&lt;/td&gt;
&lt;td&gt;Joystick Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPIO3&lt;/td&gt;
&lt;td&gt;Digital Input&lt;/td&gt;
&lt;td&gt;Button A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPIO10&lt;/td&gt;
&lt;td&gt;Digital Input&lt;/td&gt;
&lt;td&gt;Button B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPIO21&lt;/td&gt;
&lt;td&gt;PWM Output&lt;/td&gt;
&lt;td&gt;Buzzer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  ST7789 Driver Framework and Implementation
&lt;/h2&gt;

&lt;p&gt;Rather than copying fragmented examples, I designed a structured LCD driver framework. To support efficient graphics rendering, I implemented a framebuffer-based display driver class (&lt;code&gt;ST7789_FB&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;framebuf&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ST7789_FB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;spi&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reset&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dc&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init_display&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Allocate Full Framebuffer
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bytearray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;framebuf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FrameBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;framebuf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RGB565&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;write_cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bytearray&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;write_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x2A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bytearray&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="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="n"&gt;self&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;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x2B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bytearray&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="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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&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="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x2C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Memory Considerations on RP2040
&lt;/h2&gt;

&lt;p&gt;A 240×240 display using 16-bit RGB565 color requires 115,200 bytes (~112.5 KB) for a full framebuffer. The RP2040 provides 264 KB of SRAM, meaning nearly half of the available RAM is consumed by the framebuffer alone. This constraint influenced several architectural decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fixed Allocation:&lt;/strong&gt; The framebuffer is allocated once during initialization to prevent heap fragmentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Buffer Loops:&lt;/strong&gt; No large temporary buffers are created inside game loops.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selective Rendering:&lt;/strong&gt; Rendering logic avoids unnecessary full-screen redraws to save clock cycles.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Debugging Screen Orientation (The Real Fix)
&lt;/h2&gt;

&lt;p&gt;One major issue involved mirrored output and inverted color mapping. I prompted Gemini:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"In MicroPython on RP2040, my ST7789 display is mirrored horizontally and colors look swapped. I'm using SPI and setting MADCTL to 0x00. What configuration should I check?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gemini pointed toward &lt;strong&gt;MADCTL bit flags&lt;/strong&gt; and RGB/BGR order.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Initial (incorrect):&lt;/strong&gt; &lt;code&gt;self.write_data(bytearray([0x00]))&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Corrected:&lt;/strong&gt; &lt;code&gt;self.write_data(bytearray([0x40]))&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;(Setting the register to &lt;code&gt;0x40&lt;/code&gt; specifically flips the MX/Row Address Order bit, correcting the hardware-level mirroring).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&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%2Fzcyt5ica22z6sn65gus3.jpg" 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%2Fzcyt5ica22z6sn65gus3.jpg" alt="A photo of the completed Pico Arcade Console showing the menu screen with 7 games"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Build It Yourself
&lt;/h2&gt;

&lt;p&gt;Full source code including the &lt;code&gt;ST7789_FB&lt;/code&gt; driver, all 7 game implementations, and the menu system is available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/a-elhaag/Pico-Arcade-Console" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Check out the source code on GitHub&lt;/a&gt;
&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI generates quickly. Hardware validates ruthlessly.&lt;/strong&gt;&lt;br&gt;
AI accelerates engineering, but embedded systems enforce discipline.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clear constraints&lt;/strong&gt; produce better AI responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep hardware understanding&lt;/strong&gt; is required to verify AI-generated suggestions.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>geminireflections</category>
      <category>gemini</category>
    </item>
    <item>
      <title>Drift CLI - Terminal-Native AI Assistant for Safe Command Execution</title>
      <dc:creator>Anas Abuelhaag</dc:creator>
      <pubDate>Sun, 15 Feb 2026 22:54:14 +0000</pubDate>
      <link>https://forem.com/a_elhaag/drift-cli-terminal-native-ai-assistant-for-safe-command-execution-4m4n</link>
      <guid>https://forem.com/a_elhaag/drift-cli-terminal-native-ai-assistant-for-safe-command-execution-4m4n</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Drift CLI&lt;/strong&gt; is a terminal-native, safety-first AI assistant that integrates directly into your shell. Powered by local LLMs via Ollama — it requires no cloud dependency and maintains full privacy.&lt;/p&gt;

&lt;p&gt;Drift transforms how developers interact with their terminal by translating natural language queries into safe, executable shell commands. Press &lt;code&gt;Ctrl+Space&lt;/code&gt; to convert English into commands like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;drift find all python files modified today
drift explain &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-czf&lt;/span&gt; archive.tar.gz src/
drift /commit  &lt;span class="c"&gt;# Generate commit messages from staged changes&lt;/span&gt;
drift /test    &lt;span class="c"&gt;# Auto-detect and run project tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Natural Language to Shell&lt;/strong&gt;: Press &lt;code&gt;Ctrl+Space&lt;/code&gt; to get executable commands with rich previews&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety First&lt;/strong&gt;: Automatic blocklists, risk scoring (🟢 LOW, 🟡 MEDIUM, 🔴 HIGH), dry-run defaults, and confirmation prompts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local-First Privacy&lt;/strong&gt;: Runs entirely on your machine via Ollama (no API keys, no cloud tracking)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Workflows&lt;/strong&gt;: Plan → Preview → Confirm → Execute → Explain → Undo keeps every run recoverable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;18+ Slash Commands&lt;/strong&gt;: &lt;code&gt;/git&lt;/code&gt;, &lt;code&gt;/commit&lt;/code&gt;, &lt;code&gt;/test&lt;/code&gt;, &lt;code&gt;/build&lt;/code&gt;, &lt;code&gt;/find&lt;/code&gt;, &lt;code&gt;/clean&lt;/code&gt;, &lt;code&gt;/lint&lt;/code&gt; and more with contextual awareness&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory System&lt;/strong&gt;: Tracks your preferred tools, risk tolerance, and workflows with export/import utilities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System Maintenance&lt;/strong&gt;: &lt;code&gt;drift doctor&lt;/code&gt;, &lt;code&gt;drift config&lt;/code&gt;, &lt;code&gt;drift setup&lt;/code&gt;, &lt;code&gt;drift update&lt;/code&gt; keep your environment healthy&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&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%2Ffnm6117vwyt5mh1qvhj8.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%2Ffnm6117vwyt5mh1qvhj8.png" alt="demo q1" width="800" height="202"&gt;&lt;/a&gt;&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%2F1ey5nyu9pic7g15h4vcf.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%2F1ey5nyu9pic7g15h4vcf.png" alt="demo q2" width="800" height="279"&gt;&lt;/a&gt;&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%2Fctm9dj18gnl2moo4flxw.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%2Fctm9dj18gnl2moo4flxw.png" alt="demo q2 followup" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation &amp;amp; First Run (Zero Setup)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/a-elhaag/drift-cli.git
&lt;span class="nb"&gt;cd &lt;/span&gt;drift-cli
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Auto-installs Ollama, starts server, and pulls the model on first use&lt;/span&gt;
drift what is the &lt;span class="nb"&gt;time &lt;/span&gt;now
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Safe Command Execution with Preview
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ drift reorganize my project to use src layout

╭─ Plan ────────────────────────────────────────────────╮
│  Summary: Reorganize project to src/ layout            │
│  Risk: 🟡 MEDIUM                                       │
│                                                        │
│  $ mkdir -p src                                        │
│  $ mv *.py src/                                        │
│  $ mv tests/ src/                                      │
│    → Restructure project files                         │
╰────────────────────────────────────────────────────────╯
Execute? [y/N]: y
✓ Command executed successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Slash Command Integration (ZSH)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/commit    &lt;span class="c"&gt;# Generates commit message from staged changes&lt;/span&gt;
/test      &lt;span class="c"&gt;# Auto-detects test framework and runs tests&lt;/span&gt;
/build     &lt;span class="c"&gt;# Detects build system and creates build commands&lt;/span&gt;
/git       &lt;span class="c"&gt;# Analyzes repo status and suggests next actions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  History &amp;amp; Undo Safety
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;drift &lt;span class="nb"&gt;history&lt;/span&gt;              &lt;span class="c"&gt;# Browse all past queries&lt;/span&gt;
drift undo                 &lt;span class="c"&gt;# Restore files from last snapshot&lt;/span&gt;
drift cleanup &lt;span class="nt"&gt;--keep&lt;/span&gt; 5     &lt;span class="c"&gt;# Free space while keeping backups&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Memory &amp;amp; Learning
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;drift memory show          &lt;span class="c"&gt;# Your learned preferences&lt;/span&gt;
drift memory stats         &lt;span class="c"&gt;# Usage totals and risk distribution&lt;/span&gt;
drift memory &lt;span class="nb"&gt;export &lt;/span&gt;backup.json  &lt;span class="c"&gt;# Portable preferences&lt;/span&gt;
drift memory insights      &lt;span class="c"&gt;# Reveal context sent to LLM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  My Experience with GitHub Copilot CLI
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot CLI was instrumental in accelerating the development of Drift CLI. Here's how it transformed my workflow:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Rapid Implementation of Complex Features&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When building the safety engine, I used Copilot CLI to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate the risk-scoring algorithm based on command patterns&lt;/li&gt;
&lt;li&gt;Create Pydantic validation models for JSON responses from Ollama&lt;/li&gt;
&lt;li&gt;Build the snapshot/undo system for file recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Command&lt;/strong&gt;: &lt;code&gt;github copilot explain&lt;/code&gt; to understand shell command syntax before wrapping them in Python&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This helped me write more secure subprocess calls and handle edge cases&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Testing &amp;amp; Debugging Efficiency&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Used Copilot CLI to generate comprehensive pytest test suites for command execution&lt;/li&gt;
&lt;li&gt;Asked for help writing integration tests for the Ollama client&lt;/li&gt;
&lt;li&gt;Quickly stubbed out test fixtures for different command scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Full test coverage completed 3x faster than manual writing&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Documentation Generation&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Generated inline code documentation and docstrings using Copilot&lt;/li&gt;
&lt;li&gt;Created comprehensive README sections and API docs&lt;/li&gt;
&lt;li&gt;Drafted slash command catalogs with descriptions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Architecture &amp;amp; Design Decisions&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When designing the modular system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;drift_cli/
├── core/        (executor, safety, history, ollama client)
├── ui/          (display, progress)
├── commands/    (history_cmd, memory_cmd, etc.)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used Copilot CLI to explore design patterns, ask "what's the best way to structure this?" and get instant guidance on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to properly handle subprocess execution with safety&lt;/li&gt;
&lt;li&gt;Caching strategies for LLM responses&lt;/li&gt;
&lt;li&gt;Async patterns for long-running commands&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Error Handling &amp;amp; Edge Cases&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Used Copilot CLI to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handle malformed Ollama responses gracefully&lt;/li&gt;
&lt;li&gt;Implement timeout logic for stuck processes&lt;/li&gt;
&lt;li&gt;Create meaningful error messages for users&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;CI/CD &amp;amp; Deployment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Asked Copilot CLI for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Actions workflow for automated testing&lt;/li&gt;
&lt;li&gt;Installation script best practices&lt;/li&gt;
&lt;li&gt;Version management strategies&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Impact
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before Copilot CLI&lt;/strong&gt;: Manual context switching between documentation, Stack Overflow, and trial-and-error&lt;br&gt;
&lt;strong&gt;After Copilot CLI&lt;/strong&gt;: Stay in terminal, ask questions, get answers instantly, implement features without context loss&lt;/p&gt;

&lt;p&gt;The AI assistance helped me focus on &lt;strong&gt;what&lt;/strong&gt; to build (the safety-first architecture, the memory system, the slash commands) rather than &lt;strong&gt;how&lt;/strong&gt; to write boilerplate code. This improved code quality and reduced development time by approximately 40%.&lt;/p&gt;

&lt;p&gt;Drift CLI itself is a testament to what's possible when AI meets the terminal — and building it &lt;em&gt;with&lt;/em&gt; GitHub Copilot CLI showed me how powerful terminal-based AI assistance truly is.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Language&lt;/strong&gt;: Python 3.9+&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI Framework&lt;/strong&gt;: Typer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM&lt;/strong&gt;: Ollama (local, privacy-first)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation&lt;/strong&gt;: Pydantic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI&lt;/strong&gt;: Rich (beautiful terminal rendering)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shell Integration&lt;/strong&gt;: ZSH hotkey binding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: Pytest&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Package Dependencies&lt;/strong&gt;: httpx, setuptools&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Try Drift CLI&lt;/strong&gt;: &lt;a href="https://github.com/a-elhaag/drift-cli/" rel="noopener noreferrer"&gt;https://github.com/a-elhaag/drift-cli/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
  </channel>
</rss>
