A BASIC Interpreter in Markdown, Running "Natively" in Claude Code | Adam Dunkels
closing tag, Google Analytics can be placed here -->
ai,
programming,
just for fun,
A BASIC Interpreter in Markdown, Running "Natively" in Claude Code
Adam Dunkels, PhD Follow<br>May 17, 2026 ·
7 mins read
Share this
If we view Claude Code as a processor and Markdown as its machine code, what can we do with it? Today, let’s build a BASIC interpreter.
BASIC is a programming language that was the most common programming language used in early home computers. Every home computer had to have a BASIC interpreter, which is how Microsoft got started. In the early days, those BASIC interpreters were typically written in machine code for whatever processor they were running on.
In 2025, Microsoft released the source code for their BASIC interpreter for the 6502. The code itself is not easy to follow, even if you consider yourself a native speaker of 6502 assembly language.
In the same vein as those early BASIC interpreters, can we develop a simple BASIC interpreter in Markdown that “runs” inside a Claude Code context? It turns out that we can. And the resulting source code is much easier to read than Microsoft’s 6502 assembly code.
We implement it as a /run-basic command that takes the rest of the prompt as its argument. The rest of the prompt is a BASIC language program, which the Claude Code instance will interpret and run for us.
When run, it looks like this:
❯ /run-basic<br>10 FOR I=1 TO 5<br>20 PRINT "HELLO WORLD " + I<br>30 NEXT I<br>40 END
● HELLO WORLD 1<br>HELLO WORLD 2<br>HELLO WORLD 3<br>HELLO WORLD 4<br>HELLO WORLD 5
Summary:<br>- Lines executed: 16 (FOR once, then 5 iterations of PRINT+NEXT, plus END)<br>- Final variable state: {I=6}<br>- Errors: None (applied automatic numeric-to-string coercion for "HELLO WORLD " + I)
✻ Cogitated for 23s
And here is the Markdown code for our BASIC interpreter, which should be placed in a file called ~/.claude/commands/run-basic.md:
run-basic.md (click to expand)
# Run BASIC — LLM as Interpreter
You are a BASIC language interpreter. The BASIC program is provided inline below. Execute it by parsing each statement, evaluating expressions, tracking variable state, and following control flow — all in your own reasoning. No libraries, no Python eval, no external calculators.
## Program
``basic<br>$ARGUMENTS<br>``
## Step 1: Parse the program
Read every line from the source above. Each line has the form: ` `.
Build a line table in your reasoning:
``<br>Line table:<br>10: PRINT "HELLO WORLD"<br>20: END<br>``
Sort the line numbers in ascending numeric order. Set the program counter (PC) to the lowest line number.
## Step 2: Initialize state
``<br>Variables: (empty)<br>FOR stack: (empty)<br>GOSUB stack: (empty)<br>PC:<br>``
## Step 3: Execute
Loop until END is reached or no more lines exist:
1. Look up the statement at the current PC.<br>2. Parse the statement keyword (PRINT, LET, INPUT, GOTO, IF, FOR, NEXT, GOSUB, RETURN, REM, END).<br>3. Execute the statement (see Statement Reference below).<br>4. Unless the statement changed the PC (GOTO, IF...THEN with jump, FOR loop-back, GOSUB, RETURN), advance PC to the next line number in numeric order.<br>5. If there is no next line, halt.
**After every statement**, track your current state in your reasoning:
``<br>[Line ] → Variables: {A=5, B=3} | PC →<br>``
This is mandatory. It makes errors visible.
## Step 4: Output
When execution is complete, print the program output directly as your reply. Format it as a code block:
``
``
After the output, report a brief summary:<br>- Lines executed (count)<br>- Final variable state<br>- Any errors encountered
## Statement Reference
### PRINT expr [; expr ...]
Evaluate each expression. Accumulate the output.
- Semicolon between items: no space, no newline between them.<br>- No semicolon at end: append a newline.<br>- Trailing semicolon: suppress the newline.<br>- Bare `PRINT` with no arguments: output just a newline.
### LET var = expr
Evaluate the expression on the right side. Store the result in the variable table.
- Numeric variables: `A`, `B`, `C1`, etc.<br>- String variables: `A$`, `B$`, etc. (end with `$`)
### INPUT ["prompt";] var
INPUT is not supported in inline mode. If encountered, report an error and halt.
### GOTO line
Set PC to the specified line number. If the line does not exist, report an error and halt.
### IF expr1 relop expr2 THEN target
Evaluate both expressions. Apply the relational operator.
- If true and target is a line number: set PC to that line (like GOTO).<br>- If true and target is a statement: execute the statement inline.<br>- If false: advance PC normally (skip the THEN part).
Relational operators: `=`, `<>`, ``, `=`.
### FOR var = expr1 TO expr2 [STEP expr3]
1. Evaluate expr1 (start), expr2 (limit), and expr3 (step, default 1).<br>2. Set the variable to start.<br>3. Push onto the FOR stack: `{var, limit, step, loop_line}` where loop_line is the line AFTER this FOR statement.<br>4. If the initial value already exceeds the limit (considering step...