I built a programming language, compiler and virtual machine with Claude in 5 days.
Most people take years to build a programming language. I built one in 5 days, with Claude AI as my co-architect.
This exercise was both for fun and a necessity. The orchestration system powering ScrumBuddy, my AI tool, had gotten messy. Think duct tape everywhere; C#, JSON configs, string substitutions. It worked, but it wasn’t scalable.
So I decided to test my knowledge and build a new AI-first language using Claude AI.
Together, we built:
- My own assembly language
- An assembly to bytecode compiler
- A bytecode virtual machine
- Support for syscalls with a stdlib containing 20 initial functions
- A high level programming language
- A full compiler supporting a type system that runs a multi-phased pipeline compile including full AST built and assembly generation
Picture: Commits from start to finish
It was quite the journey – so I wanted to share it.
But Why?
Maitento is the AI orchestration platform that I’ve been building for the last few months. It’s in C# and designed to tackle a bunch of problems we’ve had with other AI platforms. I didn’t want to tape together Langgraph, MCP proxies, RAG pipelines and dozens of AI platforms. I wanted something that will allow us to rapidly develop enterprise AI flows.
One area that’s a real pain is workflows. The abstraction level that lets us code AI flows. For example; we may call one AI model, perform some JSON manipulation on it, feed it into a code generation pipeline, take the output and trigger a web hook.
What started as a great idea has become a mess of complex types defined in C#.
Picture: Parts of an example flow
Prompts in code. String substitutions. Data munging. Conditional logic. Testing. Deployment. Loops and enumerations.
They’ve all become cumbersome and unwieldly as our flows have grown.
I had a crazy idea: why not create our own AI-first programming language? One that takes the concepts of models, prompts, interactions, document flows and code generation as first-class citizens. We get the leverage from the orchestrator separation but keep our normal dev flows.
That’s when Cogniscript started to develop. The idea to create a programming language specifically for AI, built inside our orchestrator and removing all the janky duct-tape between layers.
The Journey
Day One: Assembly Language, Bytecode and Virtual Machine
I get the basics of a compiler. I’ve never written one, but I understand CPU architectures, I’ve dabbled in assembly, I’d heard of abstract syntax trees and find recursive concepts fun. I’ve been using .Net for 20 years and understand how IL and the .Net VM work. But I’ve never developed a system like this.
I couldn’t shake this idea the night before. It had been in my head for a few weeks but now I suddenly felt ready.
Control flow was the biggest pain in our current system. An early attempt at scripting workflows gave me something more akin to BASIC – simple GOTO statements and no scope. This became a problem fast when dealing with things like enumerating arrays and changing prompts dynamically.
I knew I needed stacks. I needed conditionals. It felt like the right place to start was a solid assembly language and a virtual runtime on top of it.
I had a 30-minute voice-chat with ChatGPT on way home from dropping my daughter at school. I validated the core concepts I knew about assembly structure, core operations and an approach to development. I asked a few questions about things I wasn’t sure about and decided to jump in.
I fired up Claude and used it continuously for five days but barely let it write a single line of code. It was there as my co-architect and pair programmer.
I created a quick and dirty assembly language, an assembler that created binary output from it and a basic virtual machine. I then started adding core operations. I wanted to leverage as much as .Net as I could everything ends up as a string with typing applied at a higher level. Variable storage, conditionals and sys call implementations were all done by the end of my first day.
Picture: Our own assembly language
Picture: Compiles down to byte code
Day Two: SysCalls and Compiler Tokenization
My second day was spent finishing off several new syscalls and rearchitecting some early bad smells I encountered. I could then get started on the compiler.
Picture: A selection of SysCalls
That night was tokenization and AST node definitions. I had some code I’d used before in my simple BASIC language that I leveraged initially to get started on the tokenizer and then started to draft out high-level node structure that I’d use to build the AST.
Day Three: AST Creation
This is when the fun started; with AST parsing from tokens. This is where the limit of my knowledge really hit and where Claude started to shine.
We discussed approaches to parsing. We disagreed quite a lot. I got into a sleep deprived hole on day three trying to figure out where tokens were going missing when parsing blocks. I was fairly sure the issue was that we needed to create new token readers as we went down recursively and only advance the primary reader “when we were happy”. Claude wanted to take a different approach to pattern matching.
The actual bug was trivial but at the point of exhaustion, I committed and pushed my code, removed Claude’s ability to push and gave it total unfettered permissions to “just get on with it”. I left Claude to do its thing while I finally had dinner and came back ever so often to ask it to proceed several times.
Two hours later, Claude had completely broken the parsing logic. It highlighted my original approach was right. Revering the changes and fix took 30 seconds.
Claude cannot write a compiler.
But it blew my mind how good Claude was at helping me walk through the process of creating the tree in the first place. By the end of day three we were pretty much done with everything except expressions.
Unfortunately, expressions are pretty much 90% of code.
Day Four: Expression Parsing
This is where Claude shone the most. It came up with a plan on how to parse complex nested expressions.
I knew we had to go up and down a tree of expressions to determine precedence, but four days into a sleep-deprived, Monster-Ultra fueled coding binge, I wasn’t able to pull all the pieces together clearly in my mind.
Left to right? Precedence? Forward and back?
Claude and I walked through the logic of how a descendent parser worked, what precedence orders mattered and how to deal with token advancement and retreat as we walked the tree.
That was probably the most valuable hour I spent on the project.
I felt like I had the knowledge to grill a compiler expert. It was able to help me figure out my approach, to determine how to split it up nicely from an OO perspective, and to confirm precedence order and syntax.
Claude definitely couldn’t write this code, but it sure as hell helped me.
We went from nothing to a working expression parser in a single day – the abstract syntax tree was complete.
Picture: What a thing of beauty!
At the peak of exhaustion came one of the most beautiful coding hacks I’ve done in a while. I wanted to output a proper tree structure without rewriting the simple “recursive nested spacing” that I’d already created. I didn’t want to go and write full hierarchy tracking… so the solution? Output the whole lot as a simple nested string, iterate that from top to bottom and determine where to start drawing lines. This was a beautiful moment of madness.
Picture: I am both horrified and delighted by this code
The Final Slog
The last day was assembly output. Compared to AST expression parsing this was the easy bit. Generate some strings with some registers, deal with depth tracking and debug.
The coding wasn’t that hard – testing it was. As we wrote more advanced programs, my debug logging grew to billions of log entries that were incomprehensible.
This is where Claude proved itself.
First, it wrote me a complex test script in my own programming language to deal with various scenarios – recursive calls, nesting, complex expressions, etc.
Picture: Claude Code's Cogniscript test suite
This led to revealing dozens of bugs that were difficult to trace and couldn’t be reproduced with single line tests.
Claude’s ability to digest the output assembly was a huge time saver – root causes of bugs were found in minutes, not hours, and fixes often took me seconds when I understood the cause.
Just before 5pm on day five we were done. The test suite passed. We had a full programming language, compiler, assembler, virtual machine and stdlib. We were done.
Picture: Claude was pretty happy with itself too
The Takeaway
This wasn’t about testing AI and it’s capabilities, this was about solving a real business problem; scripting AI flows as first-class citizens inside our orchestrator.
You’re not going to vibe code yourself to a compiler, but AI tooling is the biggest change I’ve seen in 30+ years of being a dev.
You need to know how to get the most out of it for you.
For me, Claude works best as an authoritative sparring partner rather than a developer. This project would have taken twice as long without Claude – and that’s huge.
But no, it can’t write a production-ready compiler all by itself.
Whether you’re orchestrating AI manually or context engineering yourself – it’s all about knowing how to use the tools you have in the best way.
Where are your gaps? Where do you need support? Where do you work well?
Don’t forget, it’s going to look very different if you’re a junior developer compared to a tech lead.
This project was all about delivering real value. This orchestration platform is the backbone of ScrumBuddy. How we manage flows through different agents is the difference between us creating a tool that ships real code for customers versus just being another vibe-coding wrapper. We can now iterate and test more advanced AI flows faster than ever and that gives us the chance to respond to our users.
That’s what AI tooling should ultimately be about.
You can test ScrumBuddy’s orchestration now. Sign up for our beta test and experience what AI tooling should ultimately be about.
Top comments (0)