<?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: Aryan S Rao</title>
    <description>The latest articles on DEV Community by Aryan S Rao (@aryansrao).</description>
    <link>https://dev.to/aryansrao</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%2F3686511%2F2b1f06ec-9513-4619-b53b-8f4ebf5f3107.jpeg</url>
      <title>DEV Community: Aryan S Rao</title>
      <link>https://dev.to/aryansrao</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aryansrao"/>
    <language>en</language>
    <item>
      <title>Ig my own operating system? CottonOS</title>
      <dc:creator>Aryan S Rao</dc:creator>
      <pubDate>Thu, 11 Jun 2026 10:39:22 +0000</pubDate>
      <link>https://dev.to/aryansrao/ig-my-own-operating-system-cottonos-5hb2</link>
      <guid>https://dev.to/aryansrao/ig-my-own-operating-system-cottonos-5hb2</guid>
      <description>&lt;h2&gt;
  
  
  I'm Building an OS From Scratch in Rust — And It Already Has a Desktop, Filesystem, and Networking
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;A deep dive into CottonOS: a hobby OS written entirely in Rust with a custom filesystem, GUI, preemptive multitasking, and experimental in-kernel TLS.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;There's a specific kind of madness that strikes some programmers: the urge to not just use an operating system, but to &lt;em&gt;build one&lt;/em&gt;. From the bootloader all the way up to the window manager. No Linux underneath. No BSD. Just you, your CPU, and a whole lot of page faults.&lt;/p&gt;

&lt;p&gt;That's what CottonOS is.&lt;/p&gt;

&lt;p&gt;I've been building it as a hobby project and learning experiment — a full OS kernel written in Rust for x86_64, featuring a custom filesystem I call CottonFS, a graphical desktop environment with working windows and a taskbar, preemptive multitasking, and an experimental in-kernel HTTPS stack. It's nowhere near production-ready, but it boots, it renders windows, it reads and writes files, and it can make HTTP requests — entirely from scratch.&lt;/p&gt;

&lt;p&gt;The long-term vision is bigger: I want CottonOS to eventually run an on-device LLM, lightweight and fast, fully self-contained. That's miles away, but every subsystem I write brings it closer.&lt;/p&gt;

&lt;p&gt;This post is a technical walkthrough of what I've built, the decisions I made, the hard parts, and where I want to take it. I'm actively looking for contributors who want to dig into low-level systems programming.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Rust for an OS?
&lt;/h2&gt;

&lt;p&gt;The obvious answer: memory safety without a garbage collector. In kernel code, a use-after-free isn't just a bug — it's a privilege escalation or a hard crash with no recovery. Rust's ownership model catches entire classes of these mistakes at compile time.&lt;/p&gt;

&lt;p&gt;But the real answer is more personal: I wanted to learn Rust deeply, and there's no deeper environment than bare metal. No allocator. No standard library. No OS to catch your mistakes. Just &lt;code&gt;no_std&lt;/code&gt; and a custom target spec pointing at hardware.&lt;/p&gt;

&lt;p&gt;The kernel is &lt;strong&gt;95.4% Rust&lt;/strong&gt;. The remaining ~3% is a small &lt;code&gt;boot_stub.asm&lt;/code&gt; — a Multiboot2 header, minimal GDT, early page tables, and a long mode entry point. Once we're in 64-bit mode, it's Rust all the way down.&lt;/p&gt;




&lt;h2&gt;
  
  
  Boot Sequence: Getting to Rust as Fast as Possible
&lt;/h2&gt;

&lt;p&gt;CottonOS uses GRUB with Multiboot2 as the bootloader. GRUB loads the kernel ELF at the 1MB physical mark and hands off to &lt;code&gt;boot_stub.asm&lt;/code&gt;, which does just enough to get into long mode:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sets up a stack&lt;/li&gt;
&lt;li&gt;Initializes a flat 64-bit GDT&lt;/li&gt;
&lt;li&gt;Creates identity-mapped PML4 page tables covering the first 1GB&lt;/li&gt;
&lt;li&gt;Sets &lt;code&gt;CR4.PAE&lt;/code&gt;, loads PML4 into &lt;code&gt;CR3&lt;/code&gt;, sets &lt;code&gt;EFER.LME&lt;/code&gt;, enables paging via &lt;code&gt;CR0.PG&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Far-jumps into the 64-bit code segment&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;_start64&lt;/code&gt; — our Rust entry point&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From there, &lt;code&gt;_start64&lt;/code&gt; initializes serial output first (so we have debug logging even if the screen isn't up yet), parses the Multiboot2 info structure to find the framebuffer and memory map, then brings up each subsystem in order: interrupts → memory → filesystem → processes → drivers → GUI.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory Management: Three Layers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Physical Allocator
&lt;/h3&gt;

&lt;p&gt;A bitmap allocator that tracks 4KB frames. On boot, we parse the Multiboot2 memory map, mark everything the kernel and framebuffer occupy as used, and the rest is available. Simple and predictable — no fragmentation at the physical layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Virtual Memory
&lt;/h3&gt;

&lt;p&gt;Standard x86_64 4-level paging: PML4 → PDPT → PD → PT. The kernel sits in the lower half for now (higher-half support is ready but not yet wired up). Pages carry the standard permission flags: Present, Writable, User-accessible, No-Execute. On-demand mapping means we only create page table entries when they're actually needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kernel Heap
&lt;/h3&gt;

&lt;p&gt;Built on top of the &lt;code&gt;linked_list_allocator&lt;/code&gt; crate. Initial size is 4MB at &lt;code&gt;0x02000000&lt;/code&gt;, expandable to 16MB. This registers as the global allocator, which unlocks &lt;code&gt;alloc&lt;/code&gt; — meaning &lt;code&gt;Vec&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Box&lt;/code&gt;, &lt;code&gt;Arc&lt;/code&gt;, and the rest of the heap-allocated collection types work normally inside the kernel.&lt;/p&gt;




&lt;h2&gt;
  
  
  CottonFS: A Custom Persistent Filesystem
&lt;/h2&gt;

&lt;p&gt;This was one of the most involved parts to build. CottonFS is a simple but real persistent filesystem with a design influenced by ext2.&lt;/p&gt;

&lt;h3&gt;
  
  
  On-Disk Layout
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Block Range&lt;/th&gt;
&lt;th&gt;Content&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Superblock&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1–31&lt;/td&gt;
&lt;td&gt;Inode bitmap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32–63&lt;/td&gt;
&lt;td&gt;Data block bitmap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;64–127&lt;/td&gt;
&lt;td&gt;Inode table&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;128+&lt;/td&gt;
&lt;td&gt;Data blocks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Block size is 4096 bytes. The magic number is &lt;code&gt;0x43544653&lt;/code&gt; ("CTFS"). The superblock tracks total/free blocks and inodes, mount count, last mount time, and the root inode (always inode 1).&lt;/p&gt;

&lt;p&gt;Inodes are 128 bytes on disk, holding file metadata and 12 direct block pointers plus one indirect pointer (giving a max file size of ~4MB per file — enough for a hobby OS).&lt;/p&gt;

&lt;h3&gt;
  
  
  VFS Layer
&lt;/h3&gt;

&lt;p&gt;Above CottonFS sits a VFS abstraction using Rust traits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;FileSystem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Send&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Sync&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="n"&gt;Inode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&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;fn&lt;/span&gt; &lt;span class="nf"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&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;fn&lt;/span&gt; &lt;span class="nf"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FsStats&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Inode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Send&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Sync&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&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;fn&lt;/span&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&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;fn&lt;/span&gt; &lt;span class="nf"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="n"&gt;Inode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&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;fn&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FileType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="n"&gt;Inode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&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;fn&lt;/span&gt; &lt;span class="nf"&gt;unlink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&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;fn&lt;/span&gt; &lt;span class="nf"&gt;readdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DirEntry&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;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;This means mounting a DevFS at &lt;code&gt;/dev&lt;/code&gt; was straightforward — it implements the same traits, presents &lt;code&gt;/dev/null&lt;/code&gt;, &lt;code&gt;/dev/zero&lt;/code&gt;, and &lt;code&gt;/dev/random&lt;/code&gt; as virtual inodes, and the rest of the kernel doesn't need to know the difference.&lt;/p&gt;




&lt;h2&gt;
  
  
  Process Management and the Scheduler
&lt;/h2&gt;

&lt;p&gt;CottonOS has a preemptive round-robin scheduler running at 1000Hz, driven by the PIT (Programmable Interval Timer).&lt;/p&gt;

&lt;p&gt;Each process is represented by a &lt;code&gt;Process&lt;/code&gt; struct with a PID, parent PID, name, priority (5 levels), state, and exit status. States are &lt;code&gt;Ready&lt;/code&gt;, &lt;code&gt;Running&lt;/code&gt;, &lt;code&gt;Blocked&lt;/code&gt;, and &lt;code&gt;Zombie&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Threads are supported at the kernel level with per-thread stacks and thread-local storage ready for use.&lt;/p&gt;

&lt;p&gt;The scheduler sits on top of this: on each timer tick (every 1ms), the current process is preempted and the next ready process in priority order gets scheduled. There's also an idle process that runs when nothing else is ready.&lt;/p&gt;

&lt;p&gt;The synchronization primitives — &lt;code&gt;Mutex&lt;/code&gt;, &lt;code&gt;Semaphore&lt;/code&gt;, and &lt;code&gt;CondVar&lt;/code&gt; — are all custom-implemented. The mutex uses a wait queue so blocked threads yield the CPU rather than spinning, which actually matters at 1000Hz.&lt;/p&gt;




&lt;h2&gt;
  
  
  System Calls
&lt;/h2&gt;

&lt;p&gt;The syscall interface is exposed via both &lt;code&gt;int 0x80&lt;/code&gt; and the &lt;code&gt;syscall&lt;/code&gt; instruction. There are 40+ calls covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Process&lt;/strong&gt;: &lt;code&gt;exit&lt;/code&gt;, &lt;code&gt;fork&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;wait&lt;/code&gt;, &lt;code&gt;getpid&lt;/code&gt;, &lt;code&gt;yield&lt;/code&gt;, &lt;code&gt;sleep&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File I/O&lt;/strong&gt;: &lt;code&gt;open&lt;/code&gt;, &lt;code&gt;close&lt;/code&gt;, &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;write&lt;/code&gt;, &lt;code&gt;seek&lt;/code&gt;, &lt;code&gt;stat&lt;/code&gt;, &lt;code&gt;fstat&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Directory&lt;/strong&gt;: &lt;code&gt;mkdir&lt;/code&gt;, &lt;code&gt;rmdir&lt;/code&gt;, &lt;code&gt;unlink&lt;/code&gt;, &lt;code&gt;readdir&lt;/code&gt;, &lt;code&gt;chdir&lt;/code&gt;, &lt;code&gt;getcwd&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory&lt;/strong&gt;: &lt;code&gt;brk&lt;/code&gt;, &lt;code&gt;mmap&lt;/code&gt;, &lt;code&gt;munmap&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System&lt;/strong&gt;: &lt;code&gt;uname&lt;/code&gt;, &lt;code&gt;time&lt;/code&gt;, &lt;code&gt;uptime&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Userspace is still largely planned — the interesting parts right now live in kernel space — but the interface is there and the handlers are implemented.&lt;/p&gt;




&lt;h2&gt;
  
  
  Networking: From ARP to In-Kernel TLS
&lt;/h2&gt;

&lt;p&gt;The networking stack is the newest and most experimental part of CottonOS. Here's what's implemented:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Driver layer:&lt;/strong&gt; An RTL8139 NIC driver that handles PCI discovery, initialization, and RX/TX frame handling. Works in QEMU with &lt;code&gt;-nic user,model=rtl8139&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;L2/L3:&lt;/strong&gt; Ethernet framing, ARP (cache + request/reply), and IPv4 parsing and dispatch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transport:&lt;/strong&gt; ICMP echo (ping), UDP send/receive, and basic TCP client connections.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application layer:&lt;/strong&gt; DHCP for auto-configuration, DNS resolver for A records, and two shell commands — &lt;code&gt;httpget&lt;/code&gt; for plain HTTP and &lt;code&gt;httpsget&lt;/code&gt; for HTTPS.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;httpsget&lt;/code&gt; command performs TLS negotiation entirely in-kernel. This is very experimental — the current implementation uses encrypted TLS transport but does not yet validate server certificates. Trust model hardening is planned, but getting the handshake and record layer working in a bare-metal Rust kernel with no OS underneath is already a significant milestone.&lt;/p&gt;

&lt;p&gt;Stability work included bounded poll loops to prevent livelock, a non-blocking IRQ lock path, and ARP auto-resolution with retries on normal TCP/UDP flows so you don't have to manually ARP before connecting.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Desktop Environment
&lt;/h2&gt;

&lt;p&gt;This is what surprises people most when they see CottonOS: it has a real graphical desktop.&lt;/p&gt;

&lt;p&gt;The framebuffer comes from GRUB's video mode. A double-buffer handles rendering to eliminate flicker. The font is an 8×16 bitmap font drawn character by character. Mouse input comes from the PS/2 driver.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Window Manager:&lt;/strong&gt; Windows have titles, z-order, focus, and dragging via the title bar. The controls are macOS-style (red/yellow/green circles). Keyboard and mouse events route to the focused window.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Applications bundled in the kernel:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terminal&lt;/strong&gt; — A full shell emulator with scrollable output history, backspace support, and working directory tracking. Runs all the shell commands listed below.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File Manager&lt;/strong&gt; — Graphical CottonFS browser with folder icons, file sizes, double-click navigation, back button with history, and scrollable listings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text Editor&lt;/strong&gt; — Multi-line editor with cursor positioning, arrow key navigation, undo/redo, file open/save/save-as dialogs, modified indicator, and line numbers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System Info panel&lt;/strong&gt; — Real-time display of kernel version, memory stats, filesystem usage, process count, and uptime.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Shell Commands
&lt;/h3&gt;

&lt;p&gt;The integrated shell (available both in the terminal app and as the kernel shell before GUI loads) supports:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Commands&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Filesystem&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;pwd&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;touch&lt;/code&gt;, &lt;code&gt;mkdir&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;write&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;mem&lt;/code&gt;, &lt;code&gt;df&lt;/code&gt;, &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;uptime&lt;/code&gt;, &lt;code&gt;info&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;net&lt;/code&gt;, &lt;code&gt;netstats&lt;/code&gt;, &lt;code&gt;arptable&lt;/code&gt;, &lt;code&gt;arp&lt;/code&gt;, &lt;code&gt;ping&lt;/code&gt;, &lt;code&gt;dhcp&lt;/code&gt;, &lt;code&gt;dns&lt;/code&gt;, &lt;code&gt;setip&lt;/code&gt;, &lt;code&gt;setmask&lt;/code&gt;, &lt;code&gt;setgw&lt;/code&gt;, &lt;code&gt;setdns&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TCP/UDP&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;tcpconnect&lt;/code&gt;, &lt;code&gt;tcpsend&lt;/code&gt;, &lt;code&gt;tcprecv&lt;/code&gt;, &lt;code&gt;tcpclose&lt;/code&gt;, &lt;code&gt;httpget&lt;/code&gt;, &lt;code&gt;httpsget&lt;/code&gt;, &lt;code&gt;udpsend&lt;/code&gt;, &lt;code&gt;udprecv&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Utilities&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;echo&lt;/code&gt;, &lt;code&gt;clear&lt;/code&gt;, &lt;code&gt;help&lt;/code&gt;, &lt;code&gt;sync&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;reboot&lt;/code&gt;, &lt;code&gt;halt&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The Architecture at a Glance
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-------------------------------------------------------------------+
|                        User Space (Planned)                       |
+-------------------------------------------------------------------+
|                       System Call Interface                       |
+-------------------------------------------------------------------+
|                          Kernel Space                             |
|  +-----------------+  +------------------+  +------------------+ |
|  |       GUI        |  |      Shell       |  |  Syscall Handler | |
|  | Window Manager   |  | Command Parser   |  |                  | |
|  | Desktop + Apps   |  | Builtins         |  |                  | |
|  +-----------------+  +------------------+  +------------------+ |
|  +-----------------+  +------------------+  +------------------+ |
|  |   Filesystem     |  |    Process       |  |     Memory       | |
|  |  VFS / CottonFS  |  | Scheduler        |  | Physical/Virtual | |
|  |  DevFS           |  | Threads          |  | Heap             | |
|  +-----------------+  +------------------+  +------------------+ |
|  +------------------------------------------------------------+   |
|  |  Drivers: Graphics | Keyboard | Mouse | ATA | Serial | PIT |   |
|  +------------------------------------------------------------+   |
|  |  x86_64: GDT | IDT | Paging | PIC | APIC | PIT | I/O Ports |  |
|  +------------------------------------------------------------+   |
+-------------------------------------------------------------------+
|                           Hardware                                |
+-------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Building and Running It
&lt;/h2&gt;

&lt;p&gt;You'll need &lt;code&gt;rustup&lt;/code&gt; (nightly), &lt;code&gt;nasm&lt;/code&gt;, &lt;code&gt;qemu-system-x86_64&lt;/code&gt;, &lt;code&gt;grub-mkrescue&lt;/code&gt;, &lt;code&gt;xorriso&lt;/code&gt;, and &lt;code&gt;x86_64-elf-ld&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ubuntu/Debian:&lt;/strong&gt;&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;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;qemu-system-x86 nasm grub-pc-bin xorriso mtools
rustup override &lt;span class="nb"&gt;set &lt;/span&gt;nightly
rustup component add rust-src llvm-tools-preview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Then:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/aryansrao/cottonos
&lt;span class="nb"&gt;cd &lt;/span&gt;cottonos
make iso      &lt;span class="c"&gt;# Build bootable ISO&lt;/span&gt;
make disk     &lt;span class="c"&gt;# Create 64MB persistent disk image&lt;/span&gt;
make run      &lt;span class="c"&gt;# Boot in QEMU&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Networking quick start (inside CottonOS):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;net
dhcp
dns example.com
httpget example.com /
httpsget example.com /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The roadmap for CottonOS includes several tracks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Near term:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher-half kernel migration (page tables are ready, needs wiring)&lt;/li&gt;
&lt;li&gt;Certificate validation for the TLS stack&lt;/li&gt;
&lt;li&gt;ANSI color support and command history in the terminal&lt;/li&gt;
&lt;li&gt;Proper userspace ELF loading and isolation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Medium term:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SMP (multi-core) support — the APIC code is stubbed in&lt;/li&gt;
&lt;li&gt;Extended filesystem features (larger file sizes via double/triple indirect blocks)&lt;/li&gt;
&lt;li&gt;More device drivers (USB, virtio)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Long term (the real goal):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running an on-device LLM entirely within CottonOS — lightweight inference, no external dependencies, fully self-contained&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last one is ambitious. But the point of a hobby OS is that ambition is the whole point.&lt;/p&gt;




&lt;h2&gt;
  
  
  I'm Looking for Contributors
&lt;/h2&gt;

&lt;p&gt;CottonOS is open source under GPL-3.0. I'm one person working on this in my spare time, and there's a lot of surface area. If any of this sounds interesting — low-level Rust, OS internals, graphics, networking, filesystem design — I'd love contributions at any level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where to start:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📁 GitHub: &lt;a href="https://github.com/aryansrao/cottonos" rel="noopener noreferrer"&gt;github.com/aryansrao/cottonos&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Good first areas: ANSI color support in the terminal, command history, certificate validation for TLS, documentation improvements&lt;/li&gt;
&lt;li&gt;Bigger challenges: Higher-half kernel, SMP, virtio drivers, userspace ELF loading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even just opening issues, leaving feedback on the architecture, or asking questions helps me think through the design better. OS development can feel lonely when you're doing it from scratch — the community is the part I'm most looking forward to building.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you've built something similar, or just have thoughts on the architecture decisions — I'd genuinely love to hear them in the comments. This is a learning project at heart, and every perspective helps.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>rust</category>
      <category>webdev</category>
    </item>
    <item>
      <title>NEX terminal, I created a terminal recording and sharing application.</title>
      <dc:creator>Aryan S Rao</dc:creator>
      <pubDate>Tue, 30 Dec 2025 19:01:14 +0000</pubDate>
      <link>https://dev.to/aryansrao/i-created-a-terminal-recording-and-sharing-application-317d</link>
      <guid>https://dev.to/aryansrao/i-created-a-terminal-recording-and-sharing-application-317d</guid>
      <description>&lt;p&gt;Hey everyone, I’m new to the dev.to platform and I want to share something I’ve been building for a while. I created an open-source Rust tool called NEX. It’s a terminal recorder and real-time collaboration tool. I noticed that terminal workflows are powerful but often poorly documented in software engineering. We spend hours in the CLI deploying servers, fixing production issues, running migrations, teaching juniors, pair programming, or experimenting locally. However, once a terminal session ends, most of that context is lost. Command history doesn’t tell the whole story, screenshots miss timing and interactivity, logs lose intent, and screen recordings can be heavy, noisy, and hard to analyse.&lt;/p&gt;

&lt;p&gt;NEX was designed to address these issues by recording terminal sessions with PTY-level accuracy. It captures exactly what the terminal sees and does, including interactive programs like vim or htop, ANSI colours, cursor movements, and precise timing information. Instead of just dumping text, NEX saves an accurate representation of the entire session. You can replay it later exactly as it happened, with commands and outputs appearing at the same speed as the original run. Additionally, NEX extracts structured metadata such as command execution timelines, exit codes, and timestamps. This allows you to inspect and export terminal activity as real data instead of static logs. You can convert recorded sessions into CSV or JSON and use them in spreadsheets, dashboards, audit reports, or automation pipelines, which is something I missed when analysing or documenting complex CLI workflows.&lt;/p&gt;

&lt;p&gt;Another major reason I built NEX is for collaboration. Explaining terminal issues over chat or screen-sharing can be frustrating and ineffective. NEX lets you share a live terminal session over the network, so others can watch or collaborate in real time. Each participant can also keep their own local recording of the session. There’s even a web mode that allows people to view the session from a browser without needing to install anything, which is great for demos, workshops, or non-technical stakeholders.&lt;/p&gt;

&lt;p&gt;Compared to existing tools like script, asciinema, or traditional screen recording, NEX aims to combine the best features of all of them while avoiding their limitations. It’s lightweight, accurate, replayable, analysable, and fully open source and best of all it can serve it on website where they could just directly catch it in their phone or any device which has access to that network and have a web browser. I chose Rust for its performance, safety, and reliability, which are crucial when intercepting PTY streams and managing long-running sessions. NEX is designed to have minimal overhead, so you can leave it running without worrying about resource use. If you’re into DevOps, backend engineering, teaching, onboarding, compliance, or care about terminal craftsmanship, NEX could genuinely improve your workflow. You can record a session, replay it later to see what happened, share it live with teammates while debugging remotely, or export the data for further analysis, all with a straightforward CLI-first experience.&lt;/p&gt;

&lt;p&gt;I built NEX because I believe terminal work represents knowledge, and that knowledge deserves better tools than fragile logs or unclear recordings. The project is actively developed and fully open source. I’d love feedback, ideas, or contributions from anyone interested. If you want to check it out, the site is &lt;a href="https://nex-terminal.netlify.app" rel="noopener noreferrer"&gt;nex-terminal.netlify.app&lt;/a&gt; and the repository is on GitHub at &lt;a href="https://github.com/aryansrao/nex" rel="noopener noreferrer"&gt;github.com/aryansrao/nex&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>rust</category>
      <category>tooling</category>
      <category>cli</category>
    </item>
  </channel>
</rss>
