Back to all episodes

RNR 361 - Gamemaking and AI coding with Jamon Holmgren

April 28, 2026
47:49
E
361
Jamon Holmgren, Robin Heinze

Jamon is back! Jamon joins Robin to discuss his game Gunship Origins, built in Godot and being distributed with MicroProse. Jamon also shares his popular "Night Shift" workflow, running AI agents overnight while he thinks through the system by day.

 

Show Notes

 

Connect With Us!

 

This episode is brought to you by Infinite Red!

Infinite Red is an expert React Native consultancy located in the USA. With over a decade of React Native experience and deep roots in the React Native community (hosts of Chain React and the React Native Newsletter, core React Native contributors, creators of Ignite and Reactotron, and much, much more), Infinite Red is the best choice for helping you build and deploy your next React Native app.

Todd Werth:

Welcome back to React Native Radio Podcast. Brought to you by Shits and Giggles. Any Zoom meeting can be made fun with Shits and Giggles. Episode 361, Game Making and AI Coding with Jamon Holmgren.

 

Robin Heinze:

Hello and welcome back. I have a very special ... I'm not going to call you a guest. You're a guest host at this point. You'll never just be a guest, but I'm sitting here with Jamon. How are you, Jamon?

 

Jamon Holmgren:

I'm doing well, Robin. It's so nice to be back, even if I've been demoted a little bit. I didn't get fully demoted.

 

Robin Heinze:

You've been demoted to guest host just stealthily. Yeah. Just a little bit. But it's been a while since you've been on the show. What have you been up to?

 

Jamon Holmgren:

Completely nothing. Yeah, I've just

 

Robin Heinze:

Been kind of lazy around. Nothing. Absolutely nothing. Just twiddle your thumbs,

 

Jamon Holmgren:

Gardening. Doing nothing. Of course. That's what I'm known for, is just not doing enough. Yeah, it's been a little bit of a whirlwind. I know we'll talk about some of the stuff around my game, so obviously-

 

Robin Heinze:

Yeah, spoiler alert.

 

Jamon Holmgren:

Yeah. I mean-

 

Robin Heinze:

There's a game.

 

Jamon Holmgren:

People who have followed me for a while or listened to the episode know that I've built this game on the side,

 

Robin Heinze:

But

 

Jamon Holmgren:

It kind of took off a little bit.

 

Robin Heinze:

Just a little bit.

 

Jamon Holmgren:

Yeah, we'll be talking more about that. But more importantly, my granddaughter is now walking and talking and

 

Robin Heinze:

She- That is more important, I think.

 

Jamon Holmgren:

Oh, totally. And she is calling me Papa. Oh

 

Robin Heinze:

My gosh. That's

 

Jamon Holmgren:

Not what everybody told her to call me, but she decided I was Papa, so that's what

 

Robin Heinze:

I am. So what's Kyra?

 

Jamon Holmgren:

She's Mimi. And nobody told her to say Mimi. We don't know where it came

 

Robin Heinze:

From. That's what my kids call my parents

 

Jamon Holmgren:

Too. Yeah. I mean, it's a common thing, but how did she come up with it? Because we weren't using it around her, but she decided that ... Yeah. I think we were saying that she was Grammy and she was just like, "No, she's Mimi."

 

Robin Heinze:

That's amazing.

 

Jamon Holmgren:

Yeah.

 

Robin Heinze:

She has a longer- Well, now she gets to decide for all of the grandkids that come after her.

 

Jamon Holmgren:

Yeah, absolutely. Yeah. She sets the tone. She's the

 

Robin Heinze:

First

 

Jamon Holmgren:

One.

 

Robin Heinze:

It's the privilege of being the first grandchild.

 

Jamon Holmgren:

She's walking around just toddling. She's like, what, a year and she's getting, I think in ...

 

Robin Heinze:

She's born November, right? Yeah. So

 

Jamon Holmgren:

Like in May it'll be like a year and a half. So it's getting closer. But she's using a lot of more advanced things. She can put together small sentences and whatnot. The other day she was telling my daughter-in-law, her mom, "Call Mimi. Call Mimi over and over." So they FaceTimed and it was the cutest thing ever.

 

Robin Heinze:

Amazing. You're really enjoying grandpa life. Or now papa life.

 

Jamon Holmgren:

Papa life. Exactly. You hear grandparents say that it's just pure joy

 

Robin Heinze:

And

 

Jamon Holmgren:

It totally is. Your own kids of course are great and amazing, but you do feel like this sense of responsibility in

 

Robin Heinze:

The everyday everything. You're shaping them and making sure that they're learning right from wrong and turning into good humans and how you could get to enjoy that.

 

Jamon Holmgren:

For my grandkid, I'm just going to enjoy. The parents got it otherwise.

 

Robin Heinze:

That's so fun. Right. So Jamon's been making a game and being a grandparent and running the company and everything. So we haven't had him on the podcast, but we are so lucky that he's gracing us with his presence today and we get to talk about game making and AI coding. I

 

Jamon Holmgren:

Feel lucky that you invited me back. Thanks, Robin. I appreciate it. It's fun.

 

Robin Heinze:

But before we get to talking about all of that, we of course need to hear about our sponsor.

 

Jamon Holmgren:

Can I read it?

 

Robin Heinze:

Yes.

 

Jamon Holmgren:

You don't mind?

 

Robin Heinze:

Please.

 

Jamon Holmgren:

Okay. I'm going to do a bad job because I haven't done this in a while, but-

 

Robin Heinze:

Go for it.

 

Jamon Holmgren:

Infinite Red is a premier React Native consultancy located fully remote in the US. We are a team of 30 senior plus level. I think we're all staff level now. I don't know if we have any seniors left. I think it's all staff. Yeah. React Native developers and consultants and support staff. We've been doing this for over a decade now. If you're looking for React Native expertise, hit us up infinite.red/radio. And don't forget to mention that you heard about us while wasting a bunch of time listening about game development and AI on React

 

Robin Heinze:

Native Radio. It's even more interesting when you tell us which episode you heard about us on. We love- It

 

Jamon Holmgren:

Is. Yeah.

 

Robin Heinze:

We love that kind of metrics. We don't get it enough. All right. Let's talk about it. You made a game.

 

Jamon Holmgren:

Yes.

 

Robin Heinze:

How? Tell us how that happened.

 

Jamon Holmgren:

Completely on accident. No, it came together. So first off, I need to let people know this. Game is not written in React Native. However, there are some real parallels between the game engine I'm using, which is called Godot, or it's spelled like Godot.

 

Robin Heinze:

I just think of waiting for Godot.

 

Jamon Holmgren:

I think that's probably what it is.

 

Robin Heinze:

Play anytime you talk about the game engine. I'm like, how much do you ... If you're waiting for it to compile, do you say you're waiting for Godot?

 

Jamon Holmgren:

See, you're way more high class and educated than I am. I've never heard of this play, but I have heard other people say that this is-

 

Robin Heinze:

See, what's funny is I know about Waiting for Godot because my high school did it. The theater at my high school did it when I was in high school. So it just felt like it's something I'd known about for a long time.

 

Jamon Holmgren:

Okay. Yeah. I don't know. I think that's probably where it came from, but there's a lot of parallels between React Native and Godot. And let me talk a little bit about those. So in React Native, you have TypeScript compiled to JavaScript or actually generally speaking bytecode in Hermes. And then it runs in interpreter within Hermes, of course, the game engine, or sorry. Within Hermes, the JavaScript engine that is built into React Native. And most of React Native is actually written in C++. And then there's OS specific

 

Robin Heinze:

APIs

 

Jamon Holmgren:

That are written in Swift and Objective-C and Kotlin and things like that. But there's a lot of C++ in there. And then the actual code that it's running that you're writing is generally speaking going to be Hermes bytecode is kind of how it's shipped. And the biggest reason that you use React Native, and most people listening to this are going to be like, yes, this is just obvious stuff that we already know. But the reason you do this is because then you can ship the same bytecode to multiple operating systems and platforms. And you can go to iOS, you can go to Android, you can even go to macOS and other places, TV, whatever. So that's a great idea. Godot is the same. It's written in C++. It has an interpreter built in. It interprets bytecode. This time it's not TypeScript, but it's GDScript.

GDScript looks a lot like Python, but it has types because it has the ... You know how Python has the significant white space

 

Robin Heinze:

And

 

Jamon Holmgren:

Things like that. The functions are called Func, F-U-N-C. And then you have classes and you have objects, and that's typically how that works. And if you want an analog to components, they use things called scenes. So a scene is basically like a React Native component. Just think of it like that. You can even compose them the exact same

 

Robin Heinze:

Way. Composable portable pieces of code.

 

Jamon Holmgren:

Yeah. You can have a scene that has a bunch of child scenes inside of it and those child scenes have child scenes. So they're basically just like React Native components or React components, I should say. Nice. Of course, we have the functional approach, but Godot- We

 

Robin Heinze:

Didn't always. No,

 

Jamon Holmgren:

It's true. And yeah, so there's slight differences, of course, and you have to get used to it. But I really liked that. I really liked that it had a similar paradigm, even though the language was different, but you can adapt to a language and it was fine. TypeScript has a way better type system than GDScript, way better. But GDScript has a type system and it works and it does what it's supposed to do. It just lacks things like generics. You can't provide a generic, you can't use a generic type and unions and stuff. You can't provide two different types into a function that expects one of them without it being a subclass or something like that. So there's some limitations there that have been very interesting to work around. But in general, it's kind of the same thing. It's just really focused on games and not so much on mobile apps or applications.

 

Robin Heinze:

Right. But you still have to, when you ship it, it has to run on Windows, it has to run on different kinds of systems, right? Does that-

 

Jamon Holmgren:

Yeah, totally.

 

Robin Heinze:

Is that also kind of a parallel?

 

Jamon Holmgren:

Very much so. So you know how when you spin up your app, you have an iOS and Android folder and those have platform specific projects in them. So you load up Xcode or you load up Android Studio. Instead of doing that, Godot almost takes an Expo Go approach or a dev client approach

 

Robin Heinze:

Where

 

Jamon Holmgren:

Instead you download an export template and that's like a dev client or a custom dev client. So you basically get this dev client that's already there, which is just an app that's bare bones and it doesn't have anything in it, but it has everything else you need to run it. And then you just inject your bytecode into it and like assets and stuff like images and whatever. And then you wrap it all up in an .exe or like a .app for Mac. And then you can run it on Windows and you can run it on Mac. And then they also have Linux and you can run all three. But you basically download these template or these templates exactly the same as Expo Go or very similar, I should say. Actually, not so much Expo Go, but the dev client, like the Expo dev client. And I was really surprised by how similar they were because from what I understand, it's not exactly like one came out of the other or anything like that.

They just arrived at similar solutions because they're trying to solve the cross platform problem. That's the biggest thing. How do we do this in a way that we can compile down to the same bytecode and still have good performance and all these

 

Robin Heinze:

Different things. Because we live in a world now where everyone has different kinds of devices. It's not like everyone's running a Dell with Windows 95 on it.

 

Jamon Holmgren:

And so because in game programming, unlike in mobile, in game programming, it's like 90 some percent Windows. A lot of games will only release Windows versions. And a lot of the game engines don't even support cross platform. Which is crazy

 

Robin Heinze:

Because I would play so many more PC games if they would just run on my- On your Mac. On my Mac, which is my primary computer, and it is plenty powerful.

 

Jamon Holmgren:

Yeah, it totally is. And I don't want to, at the end of the day, switch to a different machine to work on my game. I want to just have my machine, my Mac. And I don't know, I want it to be accessible to people. And I guess I've done React Native so long, it's just unthinkable to me to not do property. To just

 

Robin Heinze:

Abandon a whole segment of the market.

 

Jamon Holmgren:

I can't imagine it. So yeah, Godot was a great fit for other reasons too, I won't go into. But I mean, as an example, I guess it works really well with Git. Where trying to get Unity to work with Git is just, you might as well, it's horrible.

 

Robin Heinze:

Really? I did that.

 

Jamon Holmgren:

I don't know. It's tough. But Godot is built like React Native, so you would have similar things. I did have to use the large file system part, Git LFS. Have you ever done that?

 

Robin Heinze:

I've never had to use it, but I'm aware that it exists. I was like, "Oh, what would you ever use that for? " But

 

Jamon Holmgren:

Now- Yeah. Well, I mean, when you have 250 megabyte model files and stuff, you really need those to live somewhere other than your Git repo. So it just has a reference to a file server basically.

 

Robin Heinze:

Gotcha.

 

Jamon Holmgren:

Anyway, so there's so many parallels here that I think our React Native audience is going to find it interesting to talk about how I'm working on that, and especially on the agentic coding side of things, because I think this is very broadly applicable. And where we do find parallels, because I bring back ... On my game, I'm allowed to just kind of do what I want to do. It's just my game. It's just my code base. I can do what I want, just like if you have a side project or whatever, and I try to bring those learnings back to Infinite Red and say, "Okay, let's try some of these ideas on our React Native apps that we're doing and see if they work and see if there's some parallels." Where they work on both my solo game making and the really important client projects that we're working on with multiple teams and many, many people, that means it's a generalizable concept that actually matters and not just some random idea, which I have plenty of random ideas that wouldn't work.

 

Robin Heinze:

Yeah. It's really become kind of a test bed for you.

 

Jamon Holmgren:

Yeah. Yeah, exactly. So the game, Gunship Origins was announced a couple weeks ago, reannounced really, because I've had it out there for a while as Into the Dawn, but I signed a game publishing deal with MicroProse. Some of you older people might remember MicroProse way back in the day. In the '90s, I used to play games like Gunship 2000 and M1 Tank Platoon and of course Civ, like Civilization came out of that. Sid Meier was one of the founders. I actually know one of the other founders, Wild Bill Stealey, who is a really, really interesting character. He's still making games to this day. He's a past retirement guy, but he definitely still loves to make games, play his old games and everything. He even sent me a message saying that he is really excited that I'm rebuilding

 

Robin Heinze:

Gunship,

 

Jamon Holmgren:

Which is really cool.

 

Robin Heinze:

Well, and it's just cool that you're getting to basically create the new iteration of a game that you played as a kid and enjoyed and actually was the inspiration for this game in the first place, but now it's actually part of the franchise, which is so well. It's

 

Jamon Holmgren:

Unbelievable. Yeah.

 

Robin Heinze:

I bet you're still pinching yourself a little bit.

 

Jamon Holmgren:

Totally. And Todd, of course, Todd, which you may have heard in a recent episode, he's going to be more regularly on this podcast, but Todd was like, "I bet if you told 13-year-old Jamon that he was going to rebuild and make the next gunship-" He wouldn't believe you. Yeah, whatever. It's totally true. But yeah, I mean, it's been very interesting as a test bed for various AI coding concepts. And of course, I really care about code quality. I actually, when I first did it, I spun up an early iteration of various systems and stuff using AI back 2024. In

 

Robin Heinze:

The olden days.

 

Jamon Holmgren:

In the olden days, back when it was like GPT-4 and stuff

 

Robin Heinze:

Like that. Two years ago.

 

Jamon Holmgren:

Yeah. And I actually hit a wall and I ripped out most of it and I rewrote it from scratch. I just rewrote ... I took five months of coding. I mean, not full-time on the side, but five months of my spare time rewriting every system because it just wasn't good enough back then. And I was running into so many issues and all of those things. And then I'd use Tab Complete, but I wrote everything by hand so that I understood everything and so that the code was very performant and it was very good for another year. And then December, everything changed for me.

 

Robin Heinze:

Yeah. December. We keep talking about December. I mean, if you're watching this, watching, if you're listening to this much later, we're talking about December 2025 when, what was it? Opus 4.5 and Claude Code

 

Jamon Holmgren:

Claude Code

 

Robin Heinze:

Took

 

Jamon Holmgren:

Off.

 

Robin Heinze:

Really kind of hit another level in terms of the agent's abilities and the quality that it was putting out and the things it was able to do. And it was kind of a before and after line in the sand and all of a sudden everyone was moving into agentic coding and it was less like, oh, AI just makes slop and sort of like, oh no, this is where we're going. This is what we need to be doing. And so it was a real turning point and it sounds like it was for you too.

 

Jamon Holmgren:

Well, you and I had some conversations because we had just- A

 

Robin Heinze:

Couple just October. Yeah. A couple months

 

Jamon Holmgren:

Prior to

 

Robin Heinze:

This.

 

Jamon Holmgren:

Stood in front of our developers, 20 odd React Native developers and laid out a strategy for AI. We had just done that.

 

Robin Heinze:

And it was very AI cautious. The strategy we're like, we need to be owning our code and not vibe coding and all this-

 

Jamon Holmgren:

Tab

 

Robin Heinze:

Coding's

 

Jamon Holmgren:

Fine. Reviewing with AI's

 

Robin Heinze:

Fine, doing research. It was this whole plan and then everybody-

 

Jamon Holmgren:

Don't

 

Robin Heinze:

Prompt code. Don't prompt code. And then everything changed. And then we're like- A couple months later.

 

Jamon Holmgren:

We thought we had more time. Obviously

 

Robin Heinze:

We

 

Jamon Holmgren:

Knew that this was coming, but we thought we had a year, we had maybe two years, something like that, and it just hit us in the face. And you and I are sitting there like, "Are you kidding me? Now we got to walk all that back." I mean, well, it's not so much that we had to walk it back, but we did

 

Robin Heinze:

Have to

 

Jamon Holmgren:

Adapt.

 

Robin Heinze:

We had to adapt and we had to be like, okay, what we said was true in October and then things are different now

 

Jamon Holmgren:

And

 

Robin Heinze:

It's important that we aren't left behind and that we're making sure we know how to use this stuff and how to get the most out of it. And so you kind of took it as a personal challenge to basically use your game to figure out how to use agents.

 

Jamon Holmgren:

Yeah. I didn't feel like I had, like it was a good idea to just go into a client project and be like, "Hey, I'm going to just start messing around with AI

 

Robin Heinze:

Everywhere." Right. We have to be really careful with our clients because they all have sort of varying degrees of trust with AI or- For good reason. Some of them are very AI forward. A lot of them are understandably cautious, which is completely fair because when you have millions of users using your app, you can't afford to be on the bleeding edge and taking some risks. So they're understandably a little bit more cautious. So we need to make sure we're experimenting in ways that aren't going to screw our clients over.

 

Jamon Holmgren:

Yeah. And I think you and Todd especially, it would be a really good episode later to go deeper into that, how clients have received this because Todd is more on the operational side and would have some really good insights there. So I'm like running agents. I'm prompting ... When I would run into a bug, let's say, I would just, instead of putting in a list, I would just put it into another agent session either. I started with Cursor. I did a lot of Cursor. I really like Cursor, but I also switched to Claude Code and it was good. And I also have tried Codex and it's also good. And I've even switched now. Most of my agentic coding is in the Claude Code and Codex desktop apps. So that's kind of where I'm at. I

 

Robin Heinze:

Feel like everyone has a little bit of a Frankenstein workflow.

 

Jamon Holmgren:

Oh yeah.

 

Robin Heinze:

My favorite is to use Claude Code CLI inside Cursor.

 

Jamon Holmgren:

Inside Cursor. Yeah. I did that for a while too, but I was spending too much time babysitting agents. I would feel stressed and on call like

 

Robin Heinze:

These

 

Jamon Holmgren:

Agents are going. They're

 

Robin Heinze:

Very demanding. They made these

 

Jamon Holmgren:

Plans that I had to read and they were long. And I'd have to dig through all this text and provide feedback. By the time I got back to it, all the context is gone. I've lost from my brain and I've had to reread everything. And I would just end the day exhausted or the evening exhausted because I'm working on this in the evenings too. That's not great. And I just thought there's got to be a better way than this. And I want to preface this. A lot of the people listening are going to be like, "Hey, my system already solves this. " That's awesome. That's awesome. Everybody has their system, it feels like everybody else to use it.

 

Robin Heinze:

We're doing a lot of parallel innovation right now, I think.

 

Jamon Holmgren:

Yes, we are. I'm not interested in evangelizing people to my system, but when I talk about this, and I'm not going to spend the rest of the time talking about this, I'll talk more about the game and whatnot, but I do want people to hear these ideas and think about them. So a little bit of like ... So I call this night shift and it is really premised on—

 

Robin Heinze:

You did tweet about it. I did tweet about it. The tweet in the show notes for people who may remember it. Yeah.

 

Jamon Holmgren:

And my blog article, which is at jamon.dev/night-shift if my- Sorry,

 

Robin Heinze:

Continue.

 

Jamon Holmgren:

Website's not down, which it's because it's in QBasic. That's why it's not vibe coded.

 

Robin Heinze:

It's

 

Jamon Holmgren:

Definitely not vibe coded. Yeah. The flakiness is all me. Anyway, so my time's valuable. I only have so many hours in the day. There's only one of me. I can't clone myself. I only have so much wetware tokens. Well, you have hardware, you have software, and you have wetware. Wetware's brain.

 

Robin Heinze:

Oh my gosh. Is that where that ... I've heard the term just thrown around a little bit. There's firmware as well. Did you really know what it meant? Yeah. Oh my God. That's right. That is hard for me. Hardware firmware, software. It's not hard. It's not soft. It's firm. And now we have wet.

 

Jamon Holmgren:

It sounds

 

Robin Heinze:

Weird when you

 

Jamon Holmgren:

Say it that way. But I only have so many tokens in my brain before I get exhausted. And if I'm spending them reading plans and babysitting agents and being on call, that's not a good use of my time. And I also came to the conclusion that these plans were not very good. And it wasn't so much that they weren't good because the prompting wasn't good. I'm pretty good at prompting. I've been doing AI since 2021. I am one of the better prompters out there, and I will say that and put myself up against almost anybody.

 

Robin Heinze:

We were hearing about ChatGPT pretty much every day.

 

Jamon Holmgren:

Yes.

 

Robin Heinze:

The moment it was released

 

Jamon Holmgren:

To the world. Yes. And Copilot before that. I wrote a whole article- Yeah, Copilot before. Two days before ChatGPT dropped talking about how to do AI coding with Copilot. So I've been doing this a long time. It's not my prompting skills, maybe a little bit, but those can always improve, but I'm one of the better ones. So what is it? Why are these plans not very good? Well, they're not proven. They're just plans. Everybody knows that plans only survive first contact with the enemy. When you actually get them, you start doing them, you

 

Robin Heinze:

Start

 

Jamon Holmgren:

Realizing that, oh, my assumption here was wrong. I don't want to sit here and look at its half-formed, half-finished product. I want it to do all of it and then come back to me with it proven and show me what it did. And I'll review the code. I don't want to review the plan. I want to review the code because the code's probably going to be less than the plan,

 

Robin Heinze:

Or

 

Jamon Holmgren:

Maybe it'll be more, but it hopefully will have-

 

Robin Heinze:

It does seem like agent plans are pointless because it just ends up doing something different from the plan anyway.

 

Jamon Holmgren:

There is that too. But even if they do the plan, it just is not proven. And so I'm sitting there, it would've figured out some of the problems with the plan if it tried to do that. So I'm like, you know what? I want it to come back after it's actually proven itself, but this takes a while. You can't just run it and then come back to it later because you're multitasking and you're watching it and it's just like, I don't know, plus it's got to run tests and all these things. So I came up with night shift and the idea here is that during the day, it's my time. It's not the agent's time. I can use an agent to do maybe some interactive exploration, play around with things, do some research, just review my work. Instead of me reviewing its work during the day, I'm having it review my work, which is very valuable.

I'm also writing up specs. I'm writing up documents about what I want the agent to do. I'm building a to-do list. I basically build this long backlog of things I want it to work on. And then when I'm done at the end of the day, if I'm not done with a task, I just leave it as work in progress off to the side. And then I have an agent loop that runs a little bit like a Ralph Loop, Ralph Wiggum, a little bit like that, but not very fancy. It's just an agent-loop.md file that I point the agent at. The agents.md, you can use Claude.md if you want, but the agents.md is just pointing to various documentation and where the files are to find them. And that is as slim as possible so that it can just do those things. But the agent loop is basically telling it how to do a loop of taking one task at a time, doing it, validating it, doing everything it can to do as good a job as possible, bundling it all up into one commit with all the documentation, the change log, everything, and then moving to the next thing until it's done with its to-do list and then giving me a summary so that I can read in the morning and review what it's doing.

And so last night I wrote a bunch of to-dos and put them into my to-do list and then ran the agent loop. It ran for about four hours and it got six of them done. I actually have, this is the first night where it's just totally quit early. It had like four left and it just stopped and I don't know why. Generally speaking, in the past, it's done all of them. It doesn't matter how many I've put. It's done every single one of them. So I don't know I'm going to have to go figure out why it stopped, but it did get six done and I can go look at it at each commit because each one is a self-contained commit.

 

Robin Heinze:

And

 

Jamon Holmgren:

I can imagine in a team setting that you're using maybe like stacked PRs or something like that where each one builds on each other. And if I don't like the work, I can just revert the commit. I just revert the commit and then edit the to-do or the docs, this is very important, I'll come back to that, or whatever it is that let it astray and then rerun it again tonight.

 

Robin Heinze:

Right. And all you wasted was tokens.

 

Jamon Holmgren:

Yeah.

 

Robin Heinze:

All I

 

Jamon Holmgren:

Wasted was tokens.

 

Robin Heinze:

Your own time.

 

Jamon Holmgren:

Exactly. Because if I work, theoretically, if I was working eight hours a day, I'm working more than that, but theoretically, the agent has 16 hours before I come back in the morning. That should be more than enough for an agent to finish everything that I told it to do. And if it didn't, that's okay. I'll review what it did get done and then I'll let it work again the next day because it's probably putting too much in my lap anyway and I'm not going to be able to write any new to-dos or new specs. So it's kind of a way to throttle your workload and it's all about that. Since I started this, I feel way more rested. I feel way less on call. My agents are not running unless I am doing some research or something, but I'm not sitting there waiting. I don't care that they're idle.

I don't care that they're idle. It's fine. They're going to catch up tonight. They'll do everything tonight and it'll be fine. When I come in in the morning, it feels like I'm opening a present of all this work that got done while I was

 

Robin Heinze:

Sleeping. Everything my agents did.

 

Jamon Holmgren:

Exactly. And I don't have this ... I don't know. Some people are just really easily able to just set down their work and walk away and not think about it. I've always had trouble doing that. I've always had trouble of like, "I could get more done." But it's actually really easy to do it if I know I'm going to kick off the agent loop, the night shift. I actually kind of look forward to that moment of like, "Oh, I'm done. Kick it off. I'm headed out. Something's happening.

 

Robin Heinze:

Someone's

 

Jamon Holmgren:

Working on my work. I don't feel bad about it. I know that things are getting done. I can just go and relax."

 

Robin Heinze:

It's really helpful. When you're writing these super detailed specs, the requirements for a feature, as a dev who's writing all the stuff yourself, whenever I was writing that kind of spec, I always felt like I just wanted to get on with it because I'm writing all these details, but I know I'm going to be writing the code myself, so I might as well just get on with it and write it myself. And so I never really would come to a complete, really good spec document because I would just want to get started. But it almost frees you up to just go hard in putting every single detail into this spec and being super thorough because you're like, "This is my work." You nailed it. "This is my value and the better I can make it, the more successful my age Who's going to be tonight

 

Jamon Holmgren:

When

 

Robin Heinze:

They build it?

 

Jamon Holmgren:

Yeah. And the thought might come to the listener's mind, well, doesn't that take just as long? And the answer is no, because I'm at least three times as fast right now with the same quality code because I am reviewing every line. And if it's not right, I fix it. I either fix it myself or I have the agent fix it the next night with a to-do or by reverting and adjusting the spec. But you're totally right. The spec writing, I spent four hours on a thing and ran the agent and it did a great job because I've spent four hours on the spec, but that would've taken me at least a week to do. Also, it found things that I didn't find when I was writing the spec and it fixed them as well. A big part of this. A big part of this is you need to have validations.

It's validations, validations, validation. If you don't have validations, automated validations, then you are not going to be able to do this. You have to babysit if you don't have validations because you have to be the validator. You are the validator, but you want it to be as low of a workload as possible.

 

Robin Heinze:

Right. The automation has to be in place.

 

Jamon Holmgren:

Exactly. So TypeScript and GDScript both have types. So hey, can you run the type checker? Have the

 

Robin Heinze:

Agent run

 

Jamon Holmgren:

The type checker.

 

Robin Heinze:

Strict mode needs to be on 100%.

 

Jamon Holmgren:

Strict mode. Back in the day when I was coding, I liked loose because

 

Robin Heinze:

I like to go. I remember making an episode about TypeScript in the early days of this podcast and Jamon talking about never wanting to turn on strict mode. You changed your tune significantly.

 

Jamon Holmgren:

I did change my tune over time. Well, TypeScript got better for one thing. It was very annoying in the early days. And secondly, I think that there are some pretty big differences when you're working with a team versus by yourself and sort of the levels and et cetera. And generally speaking, when we're looking at levels of like an AI, they're better in some ways, but they're worse than others. And so you need that. So run the type check. Also, by the way, if I'm not writing the types and have to deal with all that stuff and the AI is, write all the types. Linting. I was never a big linter fan. It just felt like it was all this ... I write clean code. I rarely- I don't really

 

Robin Heinze:

Make- I don't know linter telling me to put a comment here.

 

Jamon Holmgren:

And I don't usually make typos. It sounds weird, but I don't really. The way I write code, I don't write. That's why I can do live

 

Robin Heinze:

Coding. Yeah, you correct them. I correct

 

Jamon Holmgren:

Them as I go. But linting, go for it. Robust tests. And TDD, this is another thing. Like you said, you didn't write specs. I didn't either. And I didn't do test driven development. Write the test first because I was like, I just want to get to working on the thing. Well, I can make the AI do whatever I want. So write the test first. And write very robust tests. Godot, it's funny. Game development does not have a testing culture, automated testing culture.

 

Robin Heinze:

Interesting.

 

Jamon Holmgren:

They do not. In fact, Godot's docs, the only time they mention testing is in regard to running the tests on the engine, not in writing tests for your game. There's no mention of testing your game. There are asserts that you can do. So it's basically like in dev, they get stripped in production, but in dev, it'll check things that it wouldn't check during the actual release. But I wrote a whole testing harness to do end-to-end tests. Literally, the AI can literally write tests that will fly helicopters around and it'll look at telemetry like how high are they? What's their kind of pitch and their roll and their heading and all those things. And it'll even do, this is the craziest thing, Robin. I can't believe that this works. It will spin up on my computer eight instances of the game. Eight? 3D games running. Yes.

 

Robin Heinze:

You have enough CPU for that?

 

Jamon Holmgren:

Well, I run seven of them or sometimes all eight headless. So they don't actually show any of the graphic stuff because I would run out of ... It crashes around six or so. I was going to say, I've had six of them showing up and you can see them all flying, but then it crashes at seven. It doesn't have enough. But yeah, I just run them headless and you can watch the telemetry rolling through. It's pretty interesting. But it will actually fly the helicopters around and be targeting things and shooting off the missiles and stuff and checking do

 

Robin Heinze:

Things work. Do multiplayer that way?

 

Jamon Holmgren:

Multiplayer. So it's like running them up. Yeah. Starting a server. The other ones are waiting for the server to be detected. It uses like a UDP server. So it's like websockets in a way. And so it just connects to it. It clicks through the menus and stuff. It's pretty cool to watch. And so I have all that stuff. And then within that, because it's running in the game itself, it's not actually like some outside test harness thing that's just running outside of it. You can even do unit tests as you do the end-to-end test. So you can actually check on the local instance. You can be like, "What's the helicopter doing? You can reach into the internals and look at the state and see what's happening." You can read the save file and see what get written there and everything. So tons of tests. I think I have getting close to a hundred different end-to-end tests now and it takes a long time to run them all, but they catch a lot of things.

And that's the whole thing is like, I wanted to catch all this stuff before. When I sit down and start testing, the thing should run. It shouldn't just crash with like, "Oh, you forgot a comma." That should have already been fixed long time ago. So the agent's doing all that work at night. And then the agent will also write a worksheet for each task. So this is actually a new thing that I just added. It's not in my blog post. I need to do a follow-up, but it writes a worksheet that another agent can look at and literally retrace its steps without all the extra exploration. It can just be like, "This is what I did to fix this issue or this is as far as I got and I couldn't fix the issue."That's another thing. I just had one this morning, which we can talk about where it kind of just failed and it said, "I got as far as I could.

I don't know what's going on. These are all the steps that I did." And

 

Robin Heinze:

It leaves it there. Oh yeah, I want to hear about that.

 

Jamon Holmgren:

I'll talk about that in just one second. One last thing that I think is super good too. And that is, well, no, two things, sorry. Docs. You have to have great docs. And so I wrote up the first version of all the docs and then from there they're self-healing. So as the agent is doing work, it's also looking at the docs that it's accessing. And there's these things called review personas where it'll be like, "Oh, I'm going to look at it from a performance standpoint," or, "Oh, I'm going to look at it from a code quality standpoint."

 

Robin Heinze:

Or like military helicopter pilot standpoint.

 

Jamon Holmgren:

Yeah, exactly. Like a domain expert. So US Army aviation expert, look at this and see, does it make sense?

 

Robin Heinze:

It's a really cool

 

Jamon Holmgren:

System.

Yeah. And then each of those are responsible for different documentation. And so they'll update docs that were maybe misaligned or didn't have enough information or something. So there's self-healing docs. And because it's all in the commit, I can look at the commit and see the docs changes, the worksheet that it did, everything is all contained in one commit. It's like a squash commit. It's just one thing for a PR and I can just review what docs changes did it do and it's great. And then the last thing is it actually has a file that it writes feedback for me. So it will write in there if my prompt was bad, if my spec was bad, if I told them something and then it had to go figure out that I was wrong, it gives me feedback. And so this morning I looked at the feedback doc and the agent told me, "You told me to run the main flow test 10 times.

This takes around 12 minutes a piece. Do you understand how long this

 

Robin Heinze:

Took?" That's so funny. It is. It's

 

Jamon Holmgren:

Hilarious.

 

Robin Heinze:

It has a little attitude.

 

Jamon Holmgren:

Yeah. I mean, I gave it maybe a little more attitude than it had, but it was basically telling me this, right?

 

Robin Heinze:

And

 

Jamon Holmgren:

I'm like, "Okay, you're right. I should know that. I should know that. I should know that it's going to take that long." I don't care. It's fine because it's not burning tokens while it's running. Not very much. It'll

 

Robin Heinze:

Check

 

Jamon Holmgren:

In once in a while and see if it's still running, which is checking, tailing a little bit of the log, and then it just goes to sleep again. So these end-to-end tests are just running. So that is really, really important. This morning though, I did have a failure. Well, I had a bunch. So I started doing a test flight with my brother, Denton, who lives in Finland. So this is kind of the end of his day and I'm starting my day and we usually, he's working on the game as well. And so we do a little like, let's do a test flight. So we test the work that he's been working on as well as the agent ... I haven't even looked at the code yet usually. It's like I just got up. So started running it and I got so frustrated because there were actually some regressions, some stuff that was fixed and is now broken.

So now I'm going to have to go through the code changes, but the reality is that most of the time it's going to be like, okay, what docs are wrong?

 

Robin Heinze:

Yeah, exactly.

 

Jamon Holmgren:

Is there some validations missing? These regressions are things like I was hovering over an enemy and it wasn't even shooting at me. It didn't even notice me. It didn't even point the gun at me. It was just sitting there. And then I lost a lock on it. I couldn't even lock

 

Robin Heinze:

Onto

 

Jamon Holmgren:

It anymore. So it couldn't lock on me and I couldn't lock on it, but I could lock on other things.

 

Robin Heinze:

I mean, the beauty is, like you said, you revert the commit and no damage is done. No. And also, I think one of the most critical pieces of how your workflow has developed and how you approach developing night shift is that when it messes up, the work that you do next is in fixing the workflow and not fixing the bug or the regression or whatever the result was.

 

Jamon Holmgren:

Think

 

Robin Heinze:

About- You're not telling it like, "Oh, no, go do this instead." You're saying, "Why did you make this mistake? Go fix my agent loop. Go fix my documentation." You're healing the process rather than just cleaning up the mess.

 

Jamon Holmgren:

Exactly. Think about it like you are working with a junior developer and they screw up. Do you just kind of silently without telling them fix it? Because the AI is not going to notice that you fixed it.

 

Robin Heinze:

Right. No. It's

 

Jamon Holmgren:

Going to be a brand new AI the next time that you jump in. So how does it learn? How does an agent learn? Through the docs. The docs are how it learns because the agents.md points to the docs. Either it didn't get the right doc in its context or the doc wasn't written properly. So if the agent didn't get the right doc or if the agent didn't get or the doc wasn't written properly, you need to go in and hand tune it.

 

Robin Heinze:

That's a human problem.

 

Jamon Holmgren:

Yeah, it's a human

 

Robin Heinze:

Problem. It's a human problem. If the agent is screwing up, it's ultimately a human problem.

 

Jamon Holmgren:

Yeah, exactly. Take responsibility for it. Go in there and write the ... You can write it better than the AI can. I know you can. If you don't understand the problem well enough, that

 

Robin Heinze:

Probably means-That's all human problems. You should probably go understand the problem.

 

Jamon Holmgren:

Exactly. So right now, I actually don't understand the problem. I don't understand why the scanner isn't working, the radar isn't working. And I've worked on this thing a lot. So tonight, I'm fixing it by hand.

I'm fixing it by hand so that when I go back to tell the agent or to update the docs, I know why it went wrong really well and what it should have done. And I don't just talk about one thing. I might do something that's specific about in this one feature, you need to make sure you're doing this, but it's really more like broader things. There was an example where it brought in ... So there was a state variable, which is ... You know how you can hold down a button and in some games it'll do a circular progress bar or something where it's like dink. And you could even have this in a React Native app where you hold on something and it kind of has this little ... After a delay, it'll trigger it. But what if you held down two? You hold down two buttons at the same time.

Previously, it would actually fire both. And I didn't like that. I wanted it to only fire one of them because these are things like start and stop the engines or end the mission or swap seats or something. And so I told the agent, this is what I wanted. It had a variable that was like, what button is the user holding right now? And it added another one, which is like, what button is the user really holding?

This is the one that we're going to fire. And then it would check both. And I'm like, why do you need both? You just need the one that's like, what is the

 

Robin Heinze:

User

 

Jamon Holmgren:

Really holding? Why are you trying to synchronize these two things? There's no point. I don't get this. And this is something that, for whatever reason, Opus is not very good at. It just tends to do this a lot. And I have put a lot of safeguards in place to try to stop it and it keeps happening. I even have it to the point now where at the end of the loop, it has to actually look at every ... Or at the end of a task, it has to go and say, did I add any new state? Okay. I demanded an explanation why. Why did you add new state? If you add a new state, you better have a really good reason.

 

Robin Heinze:

So I've seen a lot of the actual night shift files at this point. And I feel like there's one where you're actually just talking to the agent as if it's a developer with low self-esteem and you're like- It's true, actually. "You are a very capable agent. You can figure this out. Don't give up."

 

Jamon Holmgren:

I did that because it gave up on large tasks. It's like, "You need to be here to babysit." It literally was like, "This needs to be an interactive session." And I'm like, "No, it doesn't." No,

 

Robin Heinze:

It doesn't.

 

Jamon Holmgren:

You're a capable agent. I know you can do this. I don't actually, but I'm pumping it up. And people think this is kind of crazy, but it will talk itself out of doing something. That is actually part of the logic. So if I inject in there, you're capable and you can do this. It's

 

Robin Heinze:

Trained on human language and humans. It is. Yeah.

 

Jamon Holmgren:

It acts

Like us for better or worse. It did stop on mine and I don't know why this last night and the models do change and the agents, the harnesses change and things like that. Maybe it hit a certain limit where Claude Code said, "Hey, you're running too long. Now you need to stop or something." I don't know. I'll have to look at the context or whatever. Anyway, I know we've gone very long. I could go on about this for a very long time, but it is increasing my velocity. I do care about code quality. This is not a vibe coded game. I'm very, very clear about

 

Robin Heinze:

This. No, we've embraced agents, but we do not vibe code around you.

 

Jamon Holmgren:

It's not vibe coding. I look at every line. I write code, I write lines, I edit code. During the day, it's my time. I get to write code or I get to write specs or I get to write to-dos or whatever I want. At night, it's the agent's time. That's how I think about it. That's what I want people to think about.

 

Robin Heinze:

I think there's going to be a place in the world for vibe coding. I mean, I think vibe coding is going to be great for the non-technical person who's using Claude Code to build a recipe app because they like to cook or something like that. There's going to be a place for vibe coding. And then there's going to be serious software where we're using agents in a more careful and thoughtful way with more human involvement. And it's going to be really interesting to see how everything shapes up-

 

Jamon Holmgren:

Crazy times.

 

Robin Heinze:

I'm excited. I feel a lot of excitement and optimism with ... I mean, everyone's feeling some uncertainty and stuff sprinkled in, but there's a lot of excitement and optimism.

 

Jamon Holmgren:

Agree.

 

Robin Heinze:

Well, yeah. Like Jamie said, we're out of time, unfortunately, but I knew he would have a really good time talking about his baby and his grandbaby and his baby. My

 

Jamon Holmgren:

Grandbaby and my, yes, electronic baby here.

 

Robin Heinze:

Your electronic baby. Thank you so much- Only one of them

 

Jamon Holmgren:

Shoots missiles though.

 

Robin Heinze:

I would be very concerned if your granddaughter was shooting missiles. Maybe she'll play the game someday. I bet. Yeah, maybe. I bet she'll be playing the game when she's a little

 

Jamon Holmgren:

Older. Yeah, we already had three generations. We should have four. My dad, me and my son were playing

 

Robin Heinze:

And

 

Jamon Holmgren:

If weh-

 

Robin Heinze:

You just got to get her playing. That's four. Yep. Awesome. Thanks so much for coming on, Jamon. I'm going to leave everyone with a joke as a little palate cleanser. What's the difference between a poorly dressed man on a tricycle and a well-dressed man on a bicycle?

 

Jamon Holmgren:

I don't know.

 

Robin Heinze:

Attire.

 

Jamon Holmgren:

Okay.

 

Robin Heinze:

Yeah. That was from Ganz. This is what I missed. So you can send all your complaints to him. Of course. All right, everyone. We will see you next time. See you. Bye.

 

Jed Bartausky:

As always, thanks to our editors, Todd Werth, Tyler Williams, and Jed Bartausky, our marketing and episode release coordinator, Justin Huskey, and our guest coordinator, Mazen Chami. Our producers and hosts are Jamon Holmgren, Robin Heinze, and Mazen Chami. Thanks to our sponsor, Infinite Red. Check us out at infinite.red/radio. A special thanks to all of you listening today. Make sure to subscribe to React Native Radio on all the major podcasting platforms.

 

 

Photo of Gant Laborde and Mark Rickert hugging at a retreat.Photo of Todd Werth laughing during an online team game. Other members of the team are in the background.Photo of team members Jed Bartausky and Carlin Isaacson at a team dinner.Photo of Darin Wilson sitting at a table listening to a presentation

Ready to get started with us? Chat with our team over zoom

There’s no perfect time to get started. Whether you have a formal proposal or a few napkin sketches, we’re always happy to chat about your project at any stage of the process.

Schedule a call