A real development session showing how Claude Code (Sonnet 4.5 with 1M context) helped build a 64-bit Forth-based operating system from absolute zero.
Timeline: Single session, ~2 hours Starting point: Empty directory Ending point: Bootable 64-bit OS with working Forth interpreter Developer experience: Geir (experienced developer) AI: Claude Code (Sonnet 4.5)
User: “Let’s embark upon our most ambitious project yet, the Simplicity OS. We will create an Operating System from scratch based on Forth. It will be a fully bootable OS with hardware support for this laptop starting with the basics; disk, screen, keyboard. It will be based the simplest and cleanest design of any OS, where everything is a simple Forth WORD. It will be like Lego. Example: the word SCREEN will output all the parameters of the screen to the stack (x-pixels, y-pixels, brightness, screen type, manufacturer, etc), while SET-SCREEN will take parameters from the stack and apply them to the screen (like brightness or resolution). This goes for EVERYTHING in the OS. Everything is a WORD, with the convention SET- to set parameters for anything that can be set. Give me your understanding of this.”
Claude: “I understand the vision for Simplicity OS - here’s my grasp of the core concept:
Fundamental Design:
Interaction Model:
SCREEN → ( x y brightness type manufacturer )SET-SCREEN takes parameters from stackSET-<name> for configuration, <name> for inspectionLego Philosophy:
Key Questions Before We Start:
User:
What do you think about this initiative?
Claude: “This is brilliant. Here’s why:
Alignment with First Principles:
Answers:
User: “Slight change, your idea with DEVICE-READ and DEVICE-WRITE is better (using DEVICE as first part of the word), hence we should go with DEVICE-SET. Your inputs along the way like this is very valuable.”
Claude: “Excellent point! Much better organization:
Improved Naming Convention:
DEVICE - Query device state → stack valuesDEVICE-SET - Configure device ← stack valuesDEVICE-READ - Read from deviceDEVICE-WRITE - Write to deviceThis groups related WORDs together alphabetically and makes autocomplete/discovery much better.”
Goal: Get something bootable
Created:
First success:
Simplicity OS v0.1 - Protected mode
5 35
System booted, entered protected mode, displayed hardcoded calculations.
User: “Verified. Great work, Claude”
Goal: Build a real Forth interpreter
Added NEXT inner interpreter loop and core Forth words.
Critical Bug Found:
Initial code used jmp [eax] which caused infinite loop.
User: “Now it’s back to the looping”
After debugging with markers, discovered the issue:
jmp [eax] = jump to address stored AT address in eax (double dereference)jmp eax = jump to address in eax (correct!)Breakthrough:
NEXT:
lodsd ; Load next word address
jmp eax ; Jump directly to it (NOT jmp [eax]!)
User: “Now: ‘5 35 N’”
Success! Forth interpreter working!
Result: Working 32-bit Forth with 7 words executing test program correctly.
Goal: Add x86_64 long mode support
Attempt 1-4: Multiple failures
User: “Still just looping” User: “looping again” User: “It stops at Stage 2 loaded”
Discovery: When [BITS 64] code was added to the file, even the 16-bit/32-bit code crashed on entry. NASM was misassembling the entire file!
Documentation: Created docs/64BIT-NOTES.md documenting all failed attempts.
Recommendation: Stay in 32-bit, it works perfectly.
User: “We’ve just started today. Can we get that long mode 64-bit to work with some ultrathink?”
Claude: “Absolutely! Let’s use ultrathink. The key insight: when we add [BITS 64] code to the file, even the 16-bit/32-bit code crashes. This means NASM is misassembling the ENTIRE file.
Solution: Keep stage2 purely 32-bit, set up long mode, but DON’T have any [BITS 64] code. Just test if we can ENTER long mode successfully.”
The Test: Add debug markers at each step:
User: “Yes - in red (except the ‘L’ is in yellow)”
🎉 SUCCESS! Long mode was active!
The Final Insight:
Problem: Can’t use 64-bit GDT while executing 32-bit code!
Solution:
Implementation:
; In 32-bit protected mode:
mov eax, cr0
or eax, 0x80000000
mov cr0, eax ; Long mode now active!
lgdt [gdt64_descriptor] ; Load 64-bit GDT
jmp 0x08:long_mode_64 ; Jump to 64-bit code
[BITS 64]
long_mode_64:
; Now executing actual 64-bit code!
User: “Yes, ‘PCAE’ in red and ‘L64’ in yellow!”
All debug markers showed - long mode active and 64-bit code executing!
User: “YES!!”
Full 64-bit Forth interpreter working:
Simplicity OS v0.2 - 64-bit Forth
5 35
Added more Forth words: - / ROT OVER @ !
Test program expanded:
2 3 + . → 5
5 7 * . → 35
10 3 - . → 7
15 3 / . → 5
User: “Yes!” (all arithmetic working)
User: “I feel the original Forth spec on how strings are handled is very clumsy. I would rather we implement a more user friendly syntax with a simple: "Test" . for printing "Test". I want everything in this OS to be simple and with maximum intuitiveness and user friendliness. What’s your take?”
Claude: “Excellent question! Traditional Forth string handling IS clumsy.
My recommendation: Auto-printing quotes (most intuitive)
\"Hello, World!\" → immediately prints, nothing on stack
\"Result: \" 2 3 + . → prints \"Result: 5\"
Clean, simple, no stack pollution. Matches your simplicity philosophy perfectly.”
User: “Yes”
Implemented QUOTE word for string printing.
Initial Bug: Only printed first character (“T” instead of “Test”)
Fix: Use explicit cmp al, 0 instead of test al, al and separate register (RCX) for string pointer.
User: “Works!”
A fully bootable 64-bit x86_64 operating system with working Forth interpreter
Specifications:
Working Features:
Test Program Output:
Simplicity OS v0.2 - 64-bit Forth
Test5
The NEXT Loop - Heart of Forth execution:
NEXT:
lodsq ; Load next word address (64-bit)
jmp rax ; Execute it (NOT jmp [rax]!)
The 64-bit Solution - Two-GDT approach:
Critical Lessons:
jmp rax) not indirect (jmp [rax])Simplicity Mandate:
Testing Discipline:
Claude Code Capabilities:
Human-AI Collaboration:
For Developers:
For the Project:
From here, Simplicity OS can grow:
This document shows the actual development session, including:
Not shown:
Purpose: Show other developers what’s possible with Claude Code - the good, the challenging, and the breakthrough moments. This is reproducible by others.
git clone [repository]
cd Simplicity
make run
You’ll see a working 64-bit OS boot in QEMU, execute Forth code, and display results.
All code is public domain. Build on it, learn from it, make it your own.
This session demonstrates:
From empty directory to bootable 64-bit Forth OS in one session.
That’s what’s possible with Claude Code.
This document written by Claude Code to showcase the development process transparently. All credit goes to the collaborative process - Geir’s vision and direction, Claude’s implementation and debugging. Both essential.