<?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: KUSHAL BARAL</title>
    <description>The latest articles on Forem by KUSHAL BARAL (@kushal1o1).</description>
    <link>https://forem.com/kushal1o1</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%2F3891037%2Fca094ef2-6c41-476b-a44e-77a3a61af457.jpeg</url>
      <title>Forem: KUSHAL BARAL</title>
      <link>https://forem.com/kushal1o1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kushal1o1"/>
    <language>en</language>
    <item>
      <title>Haul :) a tiny file organizer daemon for Linux</title>
      <dc:creator>KUSHAL BARAL</dc:creator>
      <pubDate>Sat, 25 Apr 2026 11:21:47 +0000</pubDate>
      <link>https://forem.com/kushal1o1/haul-a-tiny-file-organizer-daemon-for-linux-4a9p</link>
      <guid>https://forem.com/kushal1o1/haul-a-tiny-file-organizer-daemon-for-linux-4a9p</guid>
      <description>&lt;p&gt;I hate messy Downloads folders. You know the feeling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;report.pdf
report(1).pdf
report(2).pdf
screenshot.png
screenshot(1).png
screenshot(2).png
video_final.mp4
video_final_FINAL.mp4
notes.docx
notes_copy.docx
notes_copy_FINAL(1).docx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At some point you just stop caring and let it rot.&lt;/p&gt;

&lt;p&gt;Cron jobs felt overkill — why poll every minute just to watch an empty folder? So I built &lt;strong&gt;haul&lt;/strong&gt;. Drop a file in a watched folder, it moves it to the right place. That's it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trick — zero CPU when idle
&lt;/h2&gt;

&lt;p&gt;haul uses &lt;code&gt;inotify&lt;/code&gt;, a filesystem event API built into the Linux kernel. Instead of running a loop, it just waits for the kernel to say "hey, a file arrived" — sorts it — then exits. systemd restarts it immediately for the next file.&lt;/p&gt;

&lt;p&gt;No polling. No persistent process. Nothing running between events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file lands
    ↓
kernel fires inotify
    ↓
haul wakes up
    ↓
file sorted → ~/Data/subfolder
    ↓
haul exits
    ↓
systemd restarts it
    ↓
(waiting for next file...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;inotify-tools &lt;span class="nt"&gt;-y&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/kushal1o1/haul/main/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;haul install      set up and start
haul sweep        sort files already sitting in watched folders
haul start/stop   manage the service
haul logs         tail the live log
haul uninstall    remove haul (your ~/Data/ is untouched)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Folder&lt;/th&gt;
&lt;th&gt;Extensions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PDFs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.pdf&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Images&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.jpg&lt;/code&gt; &lt;code&gt;.jpeg&lt;/code&gt; &lt;code&gt;.png&lt;/code&gt; &lt;code&gt;.gif&lt;/code&gt; &lt;code&gt;.webp&lt;/code&gt; &lt;code&gt;.svg&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Videos&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.mp4&lt;/code&gt; &lt;code&gt;.mkv&lt;/code&gt; &lt;code&gt;.avi&lt;/code&gt; &lt;code&gt;.mov&lt;/code&gt; &lt;code&gt;.webm&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audio&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.mp3&lt;/code&gt; &lt;code&gt;.flac&lt;/code&gt; &lt;code&gt;.wav&lt;/code&gt; &lt;code&gt;.ogg&lt;/code&gt; &lt;code&gt;.m4a&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.py&lt;/code&gt; &lt;code&gt;.js&lt;/code&gt; &lt;code&gt;.ts&lt;/code&gt; &lt;code&gt;.sh&lt;/code&gt; &lt;code&gt;.json&lt;/code&gt; &lt;code&gt;.yaml&lt;/code&gt; &lt;code&gt;.sql&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zips&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.zip&lt;/code&gt; &lt;code&gt;.tar.gz&lt;/code&gt; &lt;code&gt;.rar&lt;/code&gt; &lt;code&gt;.7z&lt;/code&gt; &lt;code&gt;.deb&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WordFiles&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.doc&lt;/code&gt; &lt;code&gt;.docx&lt;/code&gt; &lt;code&gt;.odt&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Excel&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.xlsx&lt;/code&gt; &lt;code&gt;.xls&lt;/code&gt; &lt;code&gt;.csv&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Others&lt;/td&gt;
&lt;td&gt;everything else&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Screenshots are detected by source folder, not filename — set &lt;code&gt;SCREENSHOTS&lt;/code&gt; to wherever your tool saves them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fully configurable
&lt;/h2&gt;

&lt;p&gt;Everything — watched folders, destination, subfolder names, extension rules — is just bash variables at the top of &lt;code&gt;~/.local/bin/haul&lt;/code&gt;. Open it in any editor and change what you want.&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="nv"&gt;DATA&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Files"&lt;/span&gt;          &lt;span class="c"&gt;# change destination&lt;/span&gt;
&lt;span class="nv"&gt;DOWNLOADS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Desktop"&lt;/span&gt;   &lt;span class="c"&gt;# change watched folder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After editing: &lt;code&gt;haul restart&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Duplicate handling
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Same file arrives again → deleted silently&lt;/li&gt;
&lt;li&gt;Same name, different content → renamed with a timestamp before moving&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Logs
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[2024-01-15 14:30:22] MOVED report.pdf → ~/Data/PDFs/
[2024-01-15 14:31:45] DUPLICATE (identical) skipped: report.pdf
[2024-01-15 14:32:10] CONFLICT renamed: notes_20240115_143210.md
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Requirements:&lt;/strong&gt; Linux with systemd, bash 4+, inotify-tools. Tested on Ubuntu 22.04 / 24.04.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://github.com/kushal1o1/haul" rel="noopener noreferrer"&gt;github.com/kushal1o1/haul&lt;/a&gt; — MIT licensed.&lt;/p&gt;

&lt;p&gt;If you've been living with a messy Downloads folder, give &lt;code&gt;haul sweep&lt;/code&gt; a try first — it sorts whatever's already there without touching the daemon.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>opensource</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Real MCP has a lot going on - but the core idea is this simple</title>
      <dc:creator>KUSHAL BARAL</dc:creator>
      <pubDate>Tue, 21 Apr 2026 17:18:37 +0000</pubDate>
      <link>https://forem.com/kushal1o1/real-mcp-has-a-lot-going-on-but-the-core-idea-is-this-simple-3e6c</link>
      <guid>https://forem.com/kushal1o1/real-mcp-has-a-lot-going-on-but-the-core-idea-is-this-simple-3e6c</guid>
      <description>&lt;p&gt;MCP (Model Context Protocol) is everywhere right now. Claude uses it, Cursor uses it, a ton of AI tooling is being built on top of it. There's an official SDK, servers, transports, capabilities negotiation... it can feel like a lot.&lt;/p&gt;

&lt;p&gt;But when I actually dug into what MCP is doing at its core, I realized — it's just structured JSON going back and forth. That's the whole idea. So I built a minimal version from raw Python, no libraries, to make sure I actually understood it before touching the real thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What MCP actually is
&lt;/h2&gt;

&lt;p&gt;Strip away the SDK and the spec details — here's the mental model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a server exposes tools (functions an AI can call)&lt;/li&gt;
&lt;li&gt;a client discovers those tools and calls them by name&lt;/li&gt;
&lt;li&gt;everything is JSON, every message has a predictable shape&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real MCP spec adds things like capability negotiation, resource types, prompt templates, SSE transport, and more. But that core loop — client asks, server responds with a tool result — is the same.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of it like HTTP but designed specifically for AI agents calling tools. The protocol exists so any agent can talk to any server without needing custom glue code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What I built to understand it
&lt;/h2&gt;

&lt;p&gt;Two versions, zero external dependencies — just Python stdlib:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic version&lt;/strong&gt; — the absolute minimum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;client sends a JSON request&lt;/li&gt;
&lt;li&gt;server reads it from &lt;code&gt;stdin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;server runs a tool&lt;/li&gt;
&lt;li&gt;server replies with JSON on &lt;code&gt;stdout&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Richer version&lt;/strong&gt; — closer to real MCP, adds a JSON-RPC style flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;initialize&lt;/code&gt; — handshake, server returns its name and version&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tools/list&lt;/code&gt; — client asks what tools exist&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tools/call&lt;/code&gt; — client calls a tool by name with arguments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That three-step flow is basically what happens every time an AI agent connects to a real MCP server.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a protocol works (the bit no one explains)
&lt;/h2&gt;

&lt;p&gt;Two processes agree on a message format, then just talk. That's it. In this case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the server sits there reading &lt;code&gt;stdin&lt;/code&gt; line by line&lt;/li&gt;
&lt;li&gt;the client writes one JSON object per line, reads one JSON response back&lt;/li&gt;
&lt;li&gt;no sockets, no framework — just text in an agreed shape&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Real MCP uses stdio transport for local servers and SSE for remote ones. Same idea, just fancier plumbing.&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;python3 basic-mcp-server.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type a raw request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"say_hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"arguments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bro"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello bro"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No library. No magic. Just Python reading and writing JSON — same as what the real SDK wraps.&lt;/p&gt;

&lt;p&gt;Full code here → &lt;a href="https://github.com/kushal1o1/Mcp-basics" rel="noopener noreferrer"&gt;https://github.com/kushal1o1/Mcp-basics&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Now I want to build an actual MCP module on top of this foundation — something useful, something real. A devtool?  A workflow helper for AI agents?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drop your idea in the comments&lt;/strong&gt; — what MCP module should I build next? I'll pick the most interesting one and document the whole thing.&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>kushal1o1</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
