1. X
  2. Andrew Healey
Log inSign up
Andrew Healey
881 posts
Andrew Healey profile banner
user avatar

Andrew Healey

@healeycodes
software engineer @vercel β€’ I write about performance, compilers, puzzles, &more on my website β€’ @recursecenter alum
πŸ‡¬πŸ‡§
healeycodes.com
Joined January 2019
913
Following
1,371
Followers
RepliesRepliesMediaMedia
  • user avatar
    Andrew Healey
    @healeycodes
    Aug 16
    I wanted to write a blog post titled (provocatively) "We Could Have Had Coding Agents in 2019" I used the GPT‑2 XL weights (no post-training) and backported several later agent-design breakthroughs (action/observation loops, filesystem tools, etc.)
    screenshot of terminal:

 β†’ ./run.sh
GPT-2 XL CODING AGENT
Model: openai-community/gpt2-xl  Device: mps  Seed: 419

INITIAL PROMPT β†’ GPT-2
────────────────────────
You are a programmer controlling a tiny project. Choose one action at a time.
Use exact filenames from Computer. After a FAIL names a file, READ that file next.

Actions:
ACTION: LIST
ACTION: READ filename.py
ACTION: WRITE filename.py
CONTENT:
complete file contents
END
ACTION: RUN
COMMAND: python check.py
ACTION: FINISH

Example:
Task: Fix the project so all checks pass.
Programmer:
ACTION: LIST
Computer:
check.py
message.py
names.py
  • user avatar
    Andrew Healey
    @healeycodes
    Aug 2
    I added πšπšŽπšπšŽπš› to the typescript compiler but along the way, I realised that what I want is different syntax for πšžπšœπš’πš—πš I just want to be able to write: πšžπšœπš’πš—πš πšŠπš πšŠπš’πš πšœπšŽπš–πšŠ.πšŠπšŒπššπšžπš’πš›πšŽ() but you can't ↧ healeycodes.com/adding-defer-t…
    Screenshot of blog post:

So the goal is to be able to write TypeScript code like this:

async function readFile(path: string) {
  await sema.acquire();
  defer sema.release(); // New!

  // ... use resource
}
The TypeScript Compiler
The TypeScript compiler (tsc) is mostly a static analysis engine. Its complexity lies in type-checking a fundamentally dynamic language, and supporting extremely incremental compilation to meet latency expectations in an IDE.

Lucky for us, we don't need to worry too much about types or other analysis in order to add our defer statement. tsc already has the machinery for "recognize syntax X, replace it with equivalent syntax Y."
  • user avatar
    Andrew Healey
    @healeycodes
    Jun 27
    two sum in lisp is actually really cute
    (defun two-sum (xs target)
  (let ((seen (make-hash-table)))
    (loop for x in xs
          for i from 0
          for need = (- target x)
          do (multiple-value-bind (j ok)
                 (gethash need seen)
               (when ok
                 (return (list j i))))
             (setf (gethash x seen) i))))
  • user avatar
    Andrew Healey
    @healeycodes
    Jun 25
    new post! I wrote a tiny compiler that lowers simple kernel loops into explicit data-parallel code (lanes! masks!) ofc I made up a language to make the input/output code easier to read
    Screenshot of post:

A Tiny Compiler for Data-Parallel Kernels
Jun 2026

A lot of fast code starts as a boring loop.

Modern hardware can perform the same operation on multiple values at once (e.g. SIMD and SIMT), and sometimes we write code directly for those execution models but other times, a compiler starts with regular-looking code and rewrites it so multiple loop iterations can run together. I built a tiny compiler (~180LOC of Python) to understand what that transformation looks like.

My compiler lowers kernels (rewrites them into a simpler, more explicit form where data parallelism is visible). The input is a small hand-written AST, and the output is a lowered IR that I print as Python-like code. Rather than going all the way from source code to instructions, think of this compiler as an intermediate step in a larger compiler.

Let's take a look at an example. Scaling audio is easy to parallelize, but it is still common to write non-explicitly parallel code like this:
  • user avatar
    Andrew Healey
    @healeycodes
    Mar 26
    quickjs is GOATed delightful API surface I was able to hack together a tiny runtime and event loop v quickly with it
    Screenshot of:

Building a Runtime with QuickJS
Mar 2026

A JavaScript engine (e.g. V8, JavaScriptCore) executes JavaScript code. It doesn't know about things like files, HTTP requests, or timers.

On the other hand, a JavaScript runtime (e.g. Node.js, Bun) is a more complete environment where JavaScript runs. It contains a JavaScript engine, extra APIs, an event loop and task queues, and platform-specific features.

That's what I'm hacking on today: a tiny runtime with console.log, process.uptime(), setTimeout and clearTimeout, fs.readFileSync and fs.readFile, as well as an event loop and worker pool for file I/O. Built on top of QuickJS.

Here's an example program it can run:

const startedAt = process.uptime();

Log in or sign up for X

See what’s happening and join the conversation

Continue with phone
or
Log in with username or email
TermsΒ·PrivacyΒ·CookiesΒ·AccessibilityΒ·Ads InfoΒ·Β© 2026 X Corp.
Advertisement
Advertisement