Leo Dion (host): Welcome to another episode of Empower Apps.
I'm your host, Leo Dion.
Today, I'm joined once again with five-timer Donnie Walls.
Donnie, thank you for coming back.
It's been a while.
Donny Wals (guest): Yeah, thanks for inviting me back.
It's a always a pleasure to be on
Leo Dion (host): Before we begin what have you been up to lately?
Donny Wals (guest): Oh, I've been up to a bunch of things
since the last time we spoke.
I don't remember exactly when I was on last time, but basically last year
I didn't do too much of conferencing.
I was just working on client work, my apps, my blog, and everything.
And then this year came around and everything was different with AI
suddenly eating a lot of traffic.
So I decided to double down on my workout tracking app which
I've been working on a lot.
It's called Magazine.
I've been doing just more of client work.
I've updated my Swift concurrency book in the meantime.
And yeah, mainly a lot of trying to figure out what to do in this age of AI
and how it will change the way I work, how it will change the content that I
make, the content that I want to make.
So been thinking about that a lot as well.
Hasn't really turned into anything to create yet.
But thinking is being done a lot.
Yeah
Leo Dion (host): So how, what surprised you the most over the
last year or so as far as like where AI, how AI has affected you?
Donny Wals (guest): Yeah.
So it's been something that was, I think, on my mind probably somewhere around
late 2024, where we had Cursor, and it became easier and easier to use AI,
and it was still very much not great.
But you could see that this was something that a lot of very smart
people were interested in, and you could see that, that there was
going to be a use for it, right?
At that point, I was pretty sure that it would impact the way that I work,
it would impact the work that I did.
I just had no idea how.
And then somewhere through 2025, I feel like things started to fade a little bit.
People seemed to almost lose interest.
We were just resuming work as normal, and we had these cool tools, but
real developers wouldn't use it.
You know what I mean?
So everyone's like: "Oh, it's not great.
It doesn't do anything exactly the way I want it to." But then, So I, I was pretty
comfortable during that time, and then suddenly late 2025 all these new models
came out, and we didn't just have Cursor as a harness, we also had Claude Code,
we also had Codex, and all of a sudden, almost overnight I felt like it happened
over Christmas, over the New Year's break.
A lot of people were off talking to friends and family, and we all
came back mid-January, and suddenly nobody wanted to write code anymore,
at least not in, in my environment.
Everybody was like: "Okay, I'm not writing code. I'm going to prompt it.
I'm gonna use agents because now an agent can work on my full project,
and it might not be perfect code, but it's good enough to keep it."
And it's almost just like that.
It was a long time coming.
It almost felt like it might never happen, and then suddenly it just happened.
Agentic coding was there.
Nobody wanted to read blogs anymore.
Nobody wanted to read books anymore.
Nobody wanted to learn anything anymore other than how do I prompt
this thing efficiently, and how do I just make it magically do what I want?
And so the way it impacted me was it changed the way that I work, and
it's really made the blog take a hit.
It's really made the books take a hit.
It's really hard to sell workshops now to, to companies because they're…
Like, nobody seems, especially for the first five, six months of the
year, nobody seems very interested anymore in deeply learning something.
Everybody just wants to get the agent to do stuff.
Leo Dion (host): Let's see, where do I go with this?
So do you think we're gonna see a rebound at some point?
Because I mean, at some point you do kinda have to know how this
stuff works behind the scenes
Donny Wals (guest): Yeah, I'm not exactly sure about that.
In a way, I think so.
It actually feels like the magic has worn off over the past couple months,
and a lot of people are tired of not writing code, tired of this crazy new
multitasking that we're all having to do.
We're all being encouraged by companies, by managers, by
CTOs to spend tokens, right?
To make sure that we
Leo Dion (host): a lot of pullback from that, like
Donny Wals (guest): it's been starting to happen, yeah.
I was about to say the beginning of the year was like do as
much as you can with AI.
We were all very much almost forced to try and almost like multitask into the
point where it seemed like higher-ups and enthusiasts were almost trying to
spend like an hour in the morning to tell like as much agents as possible
to perform as many tasks as they possibly could, and then you would go
off and do other stuff, and you'd come back in the afternoon, and you would
just click approve on a bunch of PRs.
And the reality has been that's not the way it works, right?
Like I, I think more and more people are just seeing okay, we're producing more
PRs, but reviewing them is more tedious.
It's harder.
It takes longer if we want to do it correctly.
We have feedback.
We have suggestions, but whoever put up the PR doesn't really know how
to properly implement the feedback because they didn't really write
all of the code in the first place.
And so in the end, we're producing more, but we're not always shipping faster.
We're just having more PRs sit in review for longer.
I think that's the reality for a lot of what I'm seeing at least
and what I'm hearing as well.
Leo Dion (host): That makes a lot of sense, especially in a big company.
Donny Wals (guest): Yeah
Leo Dion (host): to have human eyes on stuff.
Donny Wals (guest): Absolutely.
And I actually read this study as well where for that particular company
that they examined an AI-assisted PR would sit in non-reviewed state, like
waiting for review state, like two to three times longer than other PRs.
People would be afraid to post feedback because that would essentially
make them own that feedback.
So it's "Oh, I don't agree with the architecture here." And they were
afraid that whoever made the PR didn't fully support the architecture,
so they'd be like, "Okay, well, tell me how to do it," or "Help
me prompt the agent how to do it."
So they would suddenly become part owner of that PR.
But then once they did run through the PRs that were made by humans and they
had to start reviewing the AI PRs, they would spend less time reviewing the PR
because of complexity, because of just the perceived, How did they put that?
They didn't perceive that the writer put so much effort in and so they weren't
compelled to put in the same effort that they would for a human-written PR.
Leo Dion (host): Interesting
Donny Wals (guest): yeah, it was quite interesting to read that,
especially because I would've expected the review itself to take longer.
But it seems like once, for that company, they would put themselves to
actually reviewing it, they actually didn't really care about the PR so
much, so they just approved it and "If there's a bug, we'll have the agent
fix it 'cause it's all AI code anyway.
Who gives a crap?"
Leo Dion (host): Right.
Donny Wals (guest): quite interesting
Leo Dion (host): I mean, a few thoughts from me is shouldn't we be
doing smaller PRs then so that way they're easier to manage and review?
Donny Wals (guest): Yeah.
I mean, that probably helps 'cause the average PR made by an
agent is larger than a human PR.
I j- I just wonder, like, at what point… if you're, right, insistent
on using agents for everything, and you've given it a task, and that
task should, in theory, produce a manageable PR, I wonder how compelled
people would be to look at the code the agent made, see that it implemented
the feature, it didn't refactor half the code base, so it's probably fine.
I'm not sure, like, how compelled people are to then be like, "Okay, this is kind
of big. Let's split that up into per screen or per first the network call,
then the UI," or however you might have done that as a person writing this.
And that's also an interesting, I'm not even sure who said it or where
I, where exa- I read this, but I didn't come up with this at least.
The beauty of a human writing code is that the human at some point
goes, "Wait, should I be doing this?"
Leo Dion (host): Yeah.
Donny Wals (guest): An agent doesn't do that.
An agent just goes.
"I have a task, I'm gonna go do it." Whereas as a human, at-- when
you're working on something, at some point you just kind of feel
like the vibes are not there.
You're coding, it's this feels like too much work.
This feels like it's getting out of hand.
This feels like it wasn't scoped properly." And you stop working, and
you go back to your manager or whatever, and you go "Okay, maybe this ticket
needs to be two or three tickets.
I can work on them in parallel, but we're gonna make three PRs out of
this because it's too much otherwise."
Leo Dion (host): The way okay, like I don't know how you've been doing Maxine,
but like the way I've been doing stuff is kind of like I'll have a main branch, I'll
have the version I'm releasing, and then I'll have features, and if those features
need to be split up, I'll split those up.
And then like basically everything I ever tell Claude to do is its own PR,
and that way it's all manageable and easy for me to look at the PR, be like…
and quite frankly, like I think one of the things we're afraid of but we shouldn't
be s- we shouldn't be especially now, is ripping out code that is excessive.
I forgot which library I had been working on, but I just wanted something simple
and it gave me like fallback retries, networking caching, all this crap that
was just like maybe it works, maybe it doesn't, but it's crap I have to
maintain and I have to be responsible for.
And it's like we should be okay with saying no to too much code from a
agent
Donny Wals (guest): Yeah I totally agree with that.
I've been dealing with that myself in two ways.
One is I do the same thing you do.
Ev-every prompt basically becomes a PR.
Maybe there's a follow-up prompt to clean something up, but generally
speaking, one task is one PR.
I have agents working in worktrees so I can have multiple in parallel.
And then before I tell it to make a PR, I always tell it to do a review
where it will scrutinize every line of code that it added as is this
absolutely necessary to achieve the goal?
And basically encouraging it to do the same result with less code.
I always ask it like, "Is there anything in there for backwards compatibility?
If so, rip it out because you're building a new feature.
Don't be
Leo Dion (host): Yeah.
Oh my gosh, I get that a lot.
I've got libraries that are in beta and it's "Oh, you sure
this is okay?" No, I don't care.
Donny Wals (guest): Exactly.
So it's and sometimes I have to point it to compare this to main because we're
like five commits deep and like maybe multiple PRs stacked on top of each other.
So it's "Oh, but you already had this feature and we're changing
it now, so maybe it's not a user." But it's "No, compare it to main.
If it's not on main, it doesn't exist, and you're fine to break
everything and anything you want.
If there's anything I want preserved, I will let you know."
Leo Dion (host): Have you tried to put any of this guidance in
a Claude MD or Agents MD file?
Donny Wals (guest): It's in the agents file.
I find that most of the time it works okay.
The problem is that it becomes like a blanket thing, where if I
do want backwards compatibility, I have to be explicit about it.
So I'm always trying to balance, like, how annoying is it to pull it
back on this, and how annoying is it if it's too strict with this rule?
Or if… Right?
So th- that's a trade-off that I always have to that I'm always trying to make.
Leo Dion (host): What kind of, So let's take one step back.
What are you using now for your Nginx coding, and what are you using as far as
p- managing PRs, reviewing PRs, et cetera?
Donny Wals (guest): So I'm using Cursor.
It's one that I started using early on.
I've always liked it.
I like that it allows me to switch models really easily and not just
the two big players, but any model.
And actually Composer, which is Cursor's own model is pretty good nowadays.
It's all I need.
And it's super cheap compared to the API usage for ChatGPT or or
Leo Dion (host): How much is it?
Donny Wals (guest): I mean, the plan itself is really expensive.
I'm on a $200 plan, but I never run out of tokens.
On a $20 one I used to run out of tokens, but I haven't tried it with
only Composer, 'cause Cursor subsidizes usage with their own model, obviously,
Leo Dion (host): Yeah.
Donny Wals (guest): Heavily.
If you use ChatGPT through Cursor, it's quite expensive
because you're paying API pricing.
Leo Dion (host): Yep
Donny Wals (guest): So it's a bit of a trade-off but it's
been working really well for me.
I've been using it for, I think, exclusively for six months now.
And for my PRs I'm still just reviewing them on GitHub.
I am somewhat changing the way I look at the code.
I mainly kinda spot check it for is this what I would expect versus is
this what I would have written myself?
Which has not always been great.
I mainly do this on Magazine, by the way.
On client work I'm still a lot more scrutinizing, but Magazine is my
playground essentially, where I just wanna see how far I can push this.
So just it's different ways of working.
Basically Magazine is almost like… I've almost blind merged PRs but I'm still
not confident enough to do that, 'cause almost every time there's a subtle bug
Leo Dion (host): Let me ask you a question.
What APIs im- so you're pretty good with I don't know, Swift data.
You've written books about core data.
You've written books about certain libraries that involve reacting to
information which we won't c- name.
W- you've, you're quite experienced in certain APIs and not experienced in some.
When it comes to Maxine's work, are there particular areas where "Yeah,
I don't really know how this works, and I'm just gonna let Cursor have its
Donny Wals (guest): Oh, yeah.
I would say half the
Leo Dion (host): an example?
Donny Wals (guest): so I had never done a watch app before and so I
basically just told it "Make me a watch app. Here's what it needs to
do." And like it did a decent job of setting up, like, all the essentials,
mainly communicating with the phone.
'Cause like I was reading it.
I was looking at the sample.
I was like, "Okay, this is a lot of work.
Leo Dion (host): Did you try my library for watch communication?
Donny Wals (guest): I did not, no.
Leo Dion (host): Okay, we'll talk about Sundial K afterwards.
Donny Wals (guest): We'll talk about that.
I might wanna integrate that.
But like I just told it like, "Hey, make me this. It needs to communicate that."
And it just gave me a bunch of code.
And I think the main part that I went back and forth with was, like,
how do we communicate data, right?
Do we use structs?
Do we just send Swift data objects?
Do we send encoded messages that aren't that are strings or whatever?
It came up with a bunch of ideas, and we ended up deciding
that structs was the way to go.
So the only place that touches my actual database is the phone the
watch, live activities, widgets, app intents, they all talk to snapshots.
So bas- every time the user does a workout, I generate a snapshot of it that
exists on the file system only the parts that would be needed by other parts.
And if, for example, an app intent wants to communicate back to the
watch or to the phone it will make a snapshot, same for the watch.
It will send a specific message to the phone app.
The phone app then processes it, updates the database, and sends
information back to the watch.
The watch updates its UI.
Leo Dion (host): Okay
Donny Wals (guest): And look, I had never done that before.
I figured it would be a lot of work, and I wanted it fast
so that I could start testing.
And it's I think it took four hours for me to have it on my watch, on
my phone, and to go to the gym and actually have a first version to test.
Leo Dion (host): Yeah.
Tell the story you had about the app crashing mid-workout,
'cause that was pretty good
Donny Wals (guest): Oh, yeah.
That's a nice thing about Cursor also is that they have a web interface, right?
That sort of was a reason that I liked it so much as well.
And as I was testing the… I don't remember which particular feature I
was testing, but I was testing the app, and I did something, and it crashed.
And I tried it again, and I could get it to crash a second time.
Okay, perfect.
I have reproduction steps.
So I just went to cursor.com, fired off an agent.
I, in detail, described what I did in the app and that it crashed.
And luckily, I was on a TestFlight build, so as I was typing that,
I got an email from TestFlight saying a user submitted feedback.
So I had a crash report, and I just copied that over, attached it to my
prompt and was like, "Here's everything that I did. Here's the crash report.
Go figure it out." And the funny thing is that Cursor runs on Linux,
so it wasn't able to build my iOS app.
So it basically just completely went by vibes.
It was just like, "Okay, here's what the user told me. Here's probably what
went wrong." And I got back home, and a PR was sitting there waiting for me.
Bitrise had run, had ran a build.
It had ran my tests.
It was all green.
It was all good.
And all I needed to do was install it on my device, check that the crash
was resolved, and it actually worked.
There were a few minor nitpicks that I wanted to fix in the code,
but yeah, it was pretty good.
Especially because it was so in the moment no thinking of "Oh, what did
I do exactly?" No first writing a crash report on my phone and then
forgetting it when I got home.
I have that all the time, right?
I write something down in a note.
I go home after the gym.
Kids are there.
Kids need to be picked up, whatever, and I forget all about that note until
I've found my next bug in the gym.
I say, "Oh, crap, I forgot about that one thing." So sending it immediately to an
agent and having a PR to review was… Yeah, that was really a very cool moment
for me to, to, "Okay, so here's how we could be working on some of these things."
Leo Dion (host): Do they have Swift?
So Cursor has you can run stuff on the web.
Can it run Swift?
Donny Wals (guest): I think it should be able to install and run Swift.
You can build your own containers.
So if I had made all of this into
Leo Dion (host): Cl- Claude Code doesn't have that, so you can't even run Swift.
So I am one who has also on occasion coded on my phone by going into the
Claude app and telling it to create a PR for something I just remembered.
So I totally get it, but like every time I've tried to get Swift to work, it's "No,
we can't install Swift on this server."
It's or you can't do like a Docker container.
It's pretty limited right now
Donny Wals (guest): Yeah.
I think Cursor does allow you to configure containers, but they launched
an iOS app two or three days ago, and I haven't tried it yet, but the
app can actually connect to your computer, and then you can run agents
on your computer which is really nice.
I've been running a setup with a Mac Mini for basically just to try it, where I
can just SSH into my Mac Mini at home, and then instead of using the Cursor
website, I can just fire up a Cursor agent on the Mac Mini I have at home.
Which is also quite nice 'cause then I have the simulator and, Actually,
just last weekend, I was at a festival and they didn't have offline access
for their timetable thing, and the internet was, like, non-existent there.
So when I got back to my hotel, I told Cursor on the Mac Mini to make
me an app based on the website.
I just gave the URL for the timetable.
And since I wouldn't be able to install it 'cause I was not with my
MacBook at that time I did have it close, but I wasn't… I was at the
breakfast thing so I told it that.
I was like, "Okay, take these screenshots of every state of the app
and put them on the GitHub README.
Make me a repo and everything.
Put the screenshots there.
Build me the app." And then basically just on those screenshots,
I iterated for a bit. I was like, "Okay, this needs to change.
That needs to change."
Leo Dion (host): Wait, th- where were you when you were doing this?
Donny Wals (guest): I was having breakfast with my wife at the hotel.
We were talking about how annoying it was that we couldn't
do the timetable the day before.
Leo Dion (host): W- what did Mrs. Walls think about this?
Donny Wals (guest): She thought it was amazing.
She was so happy because she was very annoyed at, like I was, with the lack
of timetable at the venue itself.
So we were just trying to figure out, like, how should this thing work, and
just talking to the agent, and then we go back to the hotel room, plug
in our phones, install the app, and we used it for the next two days.
It was amazing.
And I haven't even seen the code.
I didn't even check anything.
Just as long as it worked, installed on my phone, solved
my problem, I was happy with it
Leo Dion (host): Yeah.
Yeah I have a few Mac Minis.
I need to do that and take advantage of that.
I haven't gotten to that part yet, but that makes total sense.
I wanted to hop back and talk about architecture.
Is there anything you're changing as far as your architecture and your…
let's talk Maxine, but also let's talk your other jobby-job stuff.
Is there a way you're changing the way you're architecting your apps in any way?
Donny Wals (guest): Not necessarily.
I'm mostly less concerned about repetitive code and boring stuff.
Like when I would write code by hand, I would be writing the same kind of
thing like over and over, and it's 99% the same, but it's slightly different.
I would start thinking about like, how do I abstract that?
Like, how do I make it so that I don't have to repeat this
little dance every single time?
And I think more often than not, that would actually lead to like clever code
where it's like it it's 99% the same, so you still have to account for the
differences, but most things are the same, so you can come up with something
with generics and do smart stuff.
And,
Leo Dion (host): Ah, I get it
Donny Wals (guest): almost always that sort of bites you in the end.
And I do like that when I tell an agent to do the boring thing, it will just do it.
And yes, there is some repetitive pieces of code, but it's repetitive
not because it's doing the same thing every single time.
It's just repetitive because that's just the way it is.
Leo Dion (host): I think that's one of those over optimization
things that developers do.
We hear don't repeat yourself, the DRY method.
And we like I think it's been overdone because like I think until
you g- have like several copies of something it's not worth refactoring
into like you said, being clever with generics and protocols and
Donny Wals (guest): Yeah.
And especially
Leo Dion (host): I was just gonna say, it also depends if you're coding for
an app or coding for developers too
Donny Wals (guest): Yeah, absolutely.
And it's also when, like, when something is the same because it's
doing literally the exact same thing over and over again, or if it's the
same just because it happens to do the same thing, if you know what I mean.
Leo Dion (host): Yep.
I know exactly what
Donny Wals (guest): like d- decoding JSON, it feels so repetitive.
It's the same thing over and over and every time you do it by hand, it's
like it's screaming for an abstraction.
Whereas, like, when you're done and six months go by, probably all of these
objects will have diverged in subtle ways and they're not exactly the same.
And so even though the initial writing was incredibly boring and
repetitive, it wasn't like you did the same thing over and over again.
It's just it was kinda the same thing.
Leo Dion (host): Yep
Donny Wals (guest): so yeah.
I like that an agent doesn't care about that.
It'll just do whatever you told it to, and it doesn't care about abstractions.
The downside, on the other hand, is that it doesn't realize when an
abstraction would be a good idea.
So for example, with Magazine, I have a lot of places where I show weights,
and I convert from pounds to kilograms.
Actually, the other way around.
I store everything in kilograms, and sometimes I present pounds for US folks.
And,
Leo Dion (host): way.
Anyways, go ahead
Donny Wals (guest): the wrong… Yeah.
There's just a couple places where we have to show labels for things,
and an AI will just happily reinvent the same helper or reinvent the same
string interpolation every single time, where I do have to tell it "Hey,
look, you know what we really need?
We need a unified way to just ask the weight data object for a display
weight and then use that everywhere instead of figuring out how to
display it locally every single time."
Leo Dion (host): It seems I mean, you could have both issues with an agent
where it over-abstracts as well, and I think the issue with repeating usually
is just a simple context window issue of there's just so much code that
it's like har- it's like difficult for it to even know that existing
code already exists somewhere in your
app.
So yeah, that's usually the case with repeating code is like you need
somewhere Claude MD or whatever that says, "Hey, if you ever need to do
this is what you need to do," and save it in the memory somewhere.
Donny Wals (guest): Yes.
I think you're touching on a really interesting point there as well, where
it's possibly even more important than before to kind of know your way around
the code base that you're working on.
Because you… The better you are at telling the agent examples
of what you've done before, the better the output's going to be.
'Cause if you just let it run freely, it might never discover that you've
done the exact same thing mostly or solved the exact same problem before.
And so it will come up with its own way to do it, and it might not be the right way.
And then nudging it to do it the right way without telling it how it was
done before is really frustrating.
So if you can just tell it "Hey, look at this file.
We have helpers for all the weight stuff.
If there's anything missing, add a new function using the exact same sort of API
styling, and make sure that you never ever do inline conversion of weights." If you
can add that to your agent file or to your prompt if it's not relevant enough for the
entire file, then yeah, that's great, and it's going to do a much, much better job
Leo Dion (host): Isn't there like a measurements API that Apple provides?
Donny Wals (guest): There is,
Leo Dion (host): was it using that or was it doing its own or what exactly was
Donny Wals (guest): So it's basically because I wasn't using measurements
I started building this thing without knowing that it existed.
So I just have a multiplier for kilograms to, to pounds and that's it.
It's super
Leo Dion (host): that… Yeah, but we need that practical measurements
book in the next year or two.
Donny Wals (guest): I guess so.
I should probably
Leo Dion (host): It'd be like a pamphlet, but still, you
know, it wouldn't be too bad
Donny Wals (guest): I mean, just knowing how to store stuff and how to normalize
it in general is a really good idea.
Like storing currency and stuff, I've seen so many people mess that up
Leo Dion (host): what are some tips you have for people who are
just getting into Nginx coding?
Like I say, like context window management is still, I think,
important in some ways, I think.
Yeah, just being able to document stuff properly so it knows how things work.
What are some other tips you might have?
Donny Wals (guest): So just I just want to reiterate the documenting.
Like having an agents file or a claude.md or I think Gemini uses gemini.md or
whatever your agent of choosing uses.
Make sure you have one of those.
It helps your agent navigate your code base, make sure that
it contains the important parts.
Tell it, like, where to find certain things.
And a nice trick that you can actually use is you can also nest them.
So you can have an agents.md file at your root or a claude.md, and then
if you have your folder structure, like for example, like your models,
your networking, your UI, and then per, like in UI you have features.
Every folder can have its own agents.md or its own claude.md and
Leo Dion (host): also have a .Claude folder in the root, for instance, I
don't know how the other ones do it, where you can provide even more general
documentation to guide the agent
Donny Wals (guest): Exactly.
A cursor has something similar as well.
But just the fact that you can stack them and then do progressive disclosure is
really useful, because that means that you can keep your root agents file relatively
small, and then the agent can just discover what it needs to find as it goes.
Great way to manage your context window.
Also, I have a sort of file that my agent has to maintain on its
own, which I call agent notes.
So in my agent's file, I tell it that it must, for every correction that I make or
every time I tell it to always or never do something, it must add a line to agent
notes where it will teach itself what to do, and then it loads that as rules
Leo Dion (host): I like that a lot.
Do
Donny Wals (guest): 'cause
Leo Dion (host): that file through the whole process?
Do you ever, like, when you merge it, We'll, we can get into worktrees
later, but then how do you deal with merge conflicts with that or
Donny Wals (guest): You keep everything.
So everything it writes down is valid.
So if there's a merge conflict, you just resolve it by keeping both changes,
'cause it never changes an existing line.
It just, it's just, like appending.
Leo Dion (host): right,
Donny Wals (guest): so also like conflicts, I don't think I've ever had a,
an actual conflict on it 'cause Git will figure out like nothing changed the same
line, it's just everybody adding stuff.
But then every once in a while I look at it and I go "Okay, so there's a
bunch of stuff there," and I'll just tell the agent like, "Okay, find me
like the general lessons in there.
Find me the overarching rules and update your agent's file so
Leo Dion (host): Oh, I love
Donny Wals (guest): now matches that." And then ev- every month or so, like
I end up with a clean agent notes and it's so much better than trying to
remember because sometimes you have a session where you have to correct it
like 10 times on the exact same thing and it feels so important to add to your
agent's file, but it turns out it was just the agent having a bad day and it
never again messes that one thing up.
And other times it feels like it's not such a big deal, but you've
corrected the agent like 10 times over the course of a month and it
was always like a small, tiny thing.
But then you see like the same thing in the agent notes file or variations
of it, and it's "Oh, hold on.
I'm actually very often telling it to do something in a specific way.
So maybe we should, you know, make sure that we generalize a nice rule out of this
so that it always does it the right way."
Leo Dion (host): So what, do you ever go through it and clean it, not clean
it up, but you know what I mean.
Like 'cause it's just gonna grow continually.
Do you ever like you just keep them all in there?
Like it's gonna end up getting big pretty quick
Donny Wals (guest): Yeah so every once in a while I'll tell the agent to go through
it and then update the agent's file.
And in the beginning it got really big every single time.
And as time goes on, it gets smarter about what I want and the way I
Leo Dion (host): Very good.
Very clever
Donny Wals (guest): almost… Now it adds maybe two lines in a month.
And almost always those are just one-time things where the agent was
just having a bad day or sometimes even I look back at those and "Oh yeah, I
was really not setting the agent up for success, I think, on that day."
I was just very vague and very changing my mind all the time trying to work
with an 80% full context window.
Of course you're gonna get bad results.
And then I'll just delete those lines by myself.
"Okay, fine. We don't want this." Another one that I use that's
also like a self-learning thing is a skill called Grill with Docs.
Leo Dion (host): Okay
Donny Wals (guest): from a skill called Grill Me, and now it's Grill with Docs.
So what it does is every time you prompt it the Grill part of it
is actually like really basic.
It basically says, "Analyze what I say, scrutinize every part of it, keep
asking questions until we mutually agree on what the feature actually is.
Do not make assumption.
Ask a question for literally everything you want to do." And it's quite tedious
in the beginning especially 'cause it'll ask you like the dumbest things.
But in a way that it feels dumb to you, but at the same time it's okay,
so you're going to assume that when I said move the button to the top, you
assumed that you meant set Y to zero.
Which might not have been true if I flipped the coordinate system
or I might have meant to move it to 20 points or whatever.
So it'll ask "What do you mean by top? What do you mean by this?" And
so when it was just a Grill Me doc, it would do that every single time.
Now, the guy that wrote it introduced a new skill called Grill with Docs, and
that looks for a file called context.md.
And as it asks these questions, it will find out like what is the specific
terminology that you use for your app?
What is the specific way that you refer to things in your natural language?
What is it-- what are certain-- What's the main color in your app?
When you say, "Use the main color," it has to go and find a variable
called main color every time.
So when it finds things like that, it goes "Okay, let's add that to context.md."
And so context.md then becomes part of what Grill with Docs loads as it
starts deciding what the feature is.
And as time goes by, it becomes smarter and smarter, and it
understands you and your app and your field of business much better.
And so I use that paired with Plan Mode.
So basically it's like I go to Plan Mode in Cursor, I use Grill
with Docs, I tell it what I want, I get a bunch of questions.
And sometimes it's really smart about it.
It's just the other day I told it when I finished the last set on my
watch and I log the set and I have nothing else to log in my plan, it
will suggest me to end the workout.
I don't want that.
I want it to allow me to add another set.
And then it was like, "You know what? You actually have this flow throughout
the watch where you planned three sets of an exercise, you press next, next, next,
and then you go into the next exercise immediately. Don't you want a step there
as well so that you can add another set?"
It's "Wow, I didn't actually think of that," 'cause it never annoyed
me, but you're absolutely right.
So that's… Yeah it's for those kinds of things it's really good 'cause it…
it becomes that annoying developer in the sprint planning that asks a question
for every single sentence in a ticket.
But in the end, they're the ones that ship without no bugs.
They're the ones that just ship exactly what was meant be, to be shipped
because they didn't assume anything.
And 90% of the time the assumption is correct, right?
So the grill scale basically tells you "I would recommend you do
this," or, "I would assume this."
It's "Yep,
Leo Dion (host): yeah.
Donny Wals (guest): But every once in a while it's like, "Oh, hold up.
That's a good idea," or, "I didn't think of that," or, "That's not what
I meant," or, "That's gonna break something." So highly recommend that
Leo Dion (host): You were just talking about sprints and stuff.
What are you using for managing tasks or issues or sprints and stuff?
Especially when it comes to Maxine
Donny Wals (guest): oh I went through a whole cycle with that.
So I first set up GitHub projects, right?
Where I made tickets every time.
The problem was it was a lot of friction for me to make tickets because it's the
kind of app where I can test it at my desk for hours and hours, but I have
no idea how it works until I actually go to the gym and try to use it.
So I, I have to go out and use it to actually know does this truly work?
Does this feel right?
Does this look right in the context of, you know, me being sweaty, me being busy?
So every time I found an issue, I would have to go to GitHub,
which on my phone, I don't know.
The app's fine, but I don't like trying to navigate GitHub issues on my phone.
It feels like too much effort, especially if you want to write down a quick
line of something you didn't like.
Leo Dion (host): Yeah, 100%.
Donny Wals (guest): So I had that.
I was like, "Okay, that might be overkill, the project set up," 'cause like it…
I was reluctant to write things down.
I would just write down in my notes app.
Okay they'll just copy it over later, which I never did.
Then I went to Notion, which I still use every once in a while.
I was like, "Maybe Notion is a bit more lightweight." It was pretty much the same
thing as GitHub, like just as annoying.
Also, the Notion mobile app isn't that great in my experience.
It's fine, but it's not good for doing like ticket-based stuff.
Leo Dion (host): Great
Donny Wals (guest): Then I decided that note list that I had, like
just Arraycast note, was fine.
So it's just everything I wanna do is a line in that notes thing.
And when I do it, I just remove it.
And basically what I try to do is if I write down a problem now as I'm working
out, I either just feed it to an agent directly and I don't even make a note,
or if it's more of a feature I want to think through, I start writing a
prompt that I would give to an agent.
And it becomes like this whole couple sentences on what I have in mind.
And then I go back to it when I'm at my desk.
And that's kind of it.
I don't really have a ticket system or an issue tracker.
Leo Dion (host): There's task tools out there, like Task Manager and SpecKit
and stuff, and I always have just been going back to just doing GitHub issues
rather… 'Cause I don't like the idea of keeping a bunch of markdown files
for every single issue and doing that as far as like planning things out.
And then, yeah, I just use milestones and GitHub issues as far as that's concerned,
and then make sure that Claude knows how to use the GitHub CLI so it can
just create the issue for me every time.
And then whenever I have time to go back to it, I will
Donny Wals (guest): Yeah.
Yeah, I mean, that works.
I use it on other projects.
It's just for this particular one because in most of my bug filing
and reporting and coming up with features happens in the gym.
It's for some reason Notes app just works best
Leo Dion (host): that makes a lot of sense.
Yeah.
One thing I wanted to mention before we switch topics that you kind of went into
is with a lot of this stuff, you can use these tools to help you with this stuff.
So if you're like, "Hey I need a prompt," you know, it can write the prompt for
you and you can help write the prompt.
If you need help creating your agents file, your context file, in a lot
of these cases, the, these tools can help you with those items, I
guess is what I'm trying to say.
And yeah, like it'll be freely like, "Yeah, we can edit your
agents.md so we know about this context file," or whatever it is.
It's usually pretty good about that
Donny Wals (guest): Absolutely, yeah.
I use it a lot for those kinds of things
Leo Dion (host): Before we close out let's talk about APIs, dub.
Where do you think Core Data, Swift Data, where are you at with that right now?
Donny Wals (guest): So Maxine is all Swift data and I'm not hating it.
Mainly because… I wasn't expecting to hate it at all because it's a
pretty simple app database-wise.
No multithreading, no multiple axes, no iCloud sync.
Just, you know, it's just on a phone, local database, model
changes every once in a while.
Migrations work fine.
A couple things that are a little bit annoying around migrations,
but once you know how they work it's not that big of a deal.
Mainly, like, when you want to remove a property from a model and
then move it to some other entity.
Pretty vague, I know.
So what I wanted to do at some point I had an integer, like three integers
somewhere on an object, and I wanted to make those three integers parts
of a new entity, and then the old entity didn't have the three numbers
anymore, just one field that pointed to
Leo Dion (host): This is migration stuff?
Okay.
Donny Wals (guest): And Swift data cannot do that in one pass, so you need two
model versions, one to copy, and then the other one to remove the old property.
In Core Data, I could do that in one pass.
So when I ran into that, it was really annoying 'cause I
was like, How do I do this?
I cannot do this.
Okay, fine, two model versions it is." Turns out
Leo Dion (host): Or they should…
Donny Wals (guest): the way I had to do it
Leo Dion (host): Yeah, you think they'd have a tempor- like I, I don't know
if you were a SQL person, but there's always the idea of a temporary table.
Like you'd think there'd be a way to script something like that up
Donny Wals (guest): Yep.
Yeah, and Cordata does that, right?
Cordata gives you old context and new context, so you can query anything you
had in your old database, and you can query anything you have in your new
one, and you can link stuff together.
SwiftData gives you old context and new context but not in the same
function, so not in the same pass.
And because it spins up a new container for each you cannot go "Okay, so I
want this object by object identifier," because in the new database it doesn't
exist, 'cause it's changing that stuff.
I don't know exactly how it works, but you cannot get old
objects into the new database,
Leo Dion (host): Would you be like, "Yeah, SwiftData all the way, all the time"?
Or where would you think SwiftData just, where are the rough edges right now?
Donny Wals (guest): I think mainly when you want to have sharing support
from NSPersistentCloudKitContainer.
That doesn't exist in SwiftData.
I would say if you need advanced compound predicates and everything,
which I think iOS 27 will have.
So that's quite nice, but at the same time, it's iOS 27 plus, so quite
older iOS versions won't have it, so you're gonna have to probably figure
out a way to use Core Data anyway.
I would say in a heavily multi-threaded environment as well, where you want
to make use of scratch contexts make sure that things run in the background.
I found that you can do it with SwiftData.
It's… And I haven't been bitten by it yet, but I feel like SwiftData's
model relies on trust a lot in the sense that you can pass your models to
any thread, and the Core Data thread checker isn't going to fail on them.
Leo Dion (host): Okay
Donny Wals (guest): But I'm not exactly sure that your models are fully threat
safe and sendable, and it all gets a little bit like, it should work.
I've been told that it should work.
It's just Core Data has given me a lot of trust issues around these things.
Like whenever they would say "With Core Data, just trust us, it'll work."
It's i'm gonna,
Leo Dion (host): You're saying core data you trust less or Swift
data
Donny Wals (guest): I would say, so I don't trust either, but in Core
Data I have a way to take control
Leo Dion (host): Okay.
Donny Wals (guest): that I know what I'm doing.
Swift Data, on the other hand they're like, "Oh, no this should work fine. This
should be managed in a model container."
Core Data has this annoying problem if you have a widget and an app, and they both
operate on the same SQLite store, that you can easily get crashes when both want to
write or both want to read, 'cause there's only supposed to be one connection active.
Swift Data says you can do that now.
Leo Dion (host): Okay.
Donny Wals (guest): I don't trust that
Leo Dion (host): Yeah, I agree
Donny Wals (guest): because I have trust issues.
There-- I haven't had actual problems, but I have trust issues, right?
Core Data bit me too many times with those kinds of things.
And it's also in Swift Data, there's bits and pieces scattered out there on,
like, how it should work, but there's no official guidance, especially on
complex topics, where you're like I
Leo Dion (host): Would you go like a, with a SQLite type or
SQLite adjacent library instead?
Or what's your position now?
So like in my case, I don't want to keep going with SwiftData in my apps.
I actually would want to migrate away from it w- especially with Bushel.
But maybe, like there's a couple of apps which are, they're fairly
simple where SwiftData would make more sense, but I'm not like super
happy with SwiftData and how it works.
It's very SwiftUI tied and not like database tied, I guess.
I don't know how to put it,
Donny Wals (guest): yeah I get that.
It's definitely a UI abstraction over SwiftData in some way,
o- over SQLite in many ways.
I… Especially for a magazine, I don't hate it to the point where
I would want to switch off of it.
Do you know what I mean?
It's fine.
It's not causing me any problems.
I don't have any performance issues with it.
Leo Dion (host): Benefits to using Core Data with an app like Magazine either,
Donny Wals (guest): There's also no benefits to switching
to something like GRDB.
I did try GRDB in the beginning.
Interestingly, 'cause everybody told me like, "Oh, it's so much
easier." Interestingly enough, I found it so much harder
Leo Dion (host): Okay.
Donny Wals (guest): than SwiftData and Core Data, maybe because I've been using
both of those for such a long time that using something else to me felt like,
"Oh why do I have to relearn database?"
I know how to do
Leo Dion (host): my chief experience is with Fluent, which is the server side
Swift library, and I'm used to that.
So there was some adjustment to be made when I switched over to
SwiftData, and I haven't done Core Data in at least a decade, so yeah
Donny Wals (guest): Oh, yeah.
Yeah, I can imagine if you were to come from a more, let's say ORM style thing to
SwiftData, which is like its own… it's not, I guess it's not technically an ORM.
I think Core Data was pitched as like a graph management tool or something
Leo Dion (host): right.
It's like a abstraction layer.
Yeah, I get it.
Donny Wals (guest): Yeah.
Leo Dion (host): Yeah
Donny Wals (guest): I can totally see like how that would be
Leo Dion (host): Annoying?
Donny Wals (guest): To deal with when you're used to a certain level of
control and certain level of doing things
Leo Dion (host): Before we close out, I guess this is the second
time I've said that maybe, but I could, I, What's next for Donny?
What kind of books should we expect, if any, in the next couple of years?
And has there… And additionally I'm gonna ask, was there anything out
of Dub that you were like, "I wanna write a book about that," or something
that really caught your attention?
Donny Wals (guest): So I don't know.
I started working on a Swift data book, which I think I'm, I
might not finish, I might finish.
I have no idea right now where I'm at with that.
So whether I'm gonna do more books I really don't know at this point.
I think for me to do more books, the concurrency book has to pick up again
'cause that was in demand a lot.
And then somewhere in the last quarter of 2025, that sort of just took a nosedive,
Leo Dion (host): Wow.
Okay
Donny Wals (guest): which very clearly says to me people are not interested in
learning the details of how this works.
They want their agents to know the details, and there are skills
out there that people can use.
And I th- I do feel like eventually people will come back from that because they
have no idea what the agent is doing.
Concurrency is really hard.
Even with skills, it might still make poor decisions because of,
probably because the user doing a poor job explaining what they want.
So yeah, maybe we'll come back to that.
So I have no idea.
In terms of what's next, I'm still very heavily thinking what do I do next?
I am dabbling in indie apps shipping my own stuff, which I chose the
hardest niche to get into, I think, which is health and fitness.
But it's fun.
I'm liking it a lot.
So yeah, that's good.
Maybe other apps, maybe other ideas will come at some point.
I have no idea.
YouTube, I do want to pick that up again.
I've been putting that on hold as well while I figure out what am
I gonna do exactly content-wise.
Leo Dion (host): Mm-hmm
Donny Wals (guest): I'm leaning more towards maybe a live stream
format where just co-working or more workflow, higher level stuff, like
not tutorials, not here's how to do X or not here's how I like to do this
this UI part or how I architect this.
But a lot more high level, like how do I work with agents?
Like how do I manage context windows?
How do I describe architecture?
How do I review code?
How do I recognize when my agent's going after rails?
Those kinds of things.
But I have no
Leo Dion (host): like off the rails, like it's going crazy, not Ruby, right?
Donny Wals (guest): Yeah.
Like how do I recognize that I should probably stop the agent mid-task?
'Cause like you can just leave it running and sometimes… I do still
think there's a ton of value in deeply understanding what the agent is doing
in terms of how should the code look and
Leo Dion (host): There was a way in Claude Code where you could have it
tell you what it's thinking while it does something, and I don't know if they
got rid of it or it's no longer there.
I need to re-enable it because it's really helpful
Donny Wals (guest): I've, used that many times.
I've had that when You have your plan.
Plan mode is great.
Everything looks fine.
The files, it lists it.
It looks good.
Then it starts doing the work and it's "Oh, we need to remove
the old model version because there's a new model version."
No, don't remove anything.
Don't do that.
Do not remove anything.
You're making new model versions.
Model versions are additive, not destructive.
And if I had let that run, it could've spent like 30 minutes to an hour
doing work, and then I come back, it's why does nothing work anymore?"
Leo Dion (host): Right, right.
Yeah, thinking mode is what it's called.
So yeah.
Well, Donnie let's do this again before the AI apocalypse or AI bubble.
One or the other, we'll see.
We'll flip a coin and we'll
see which way it
Donny Wals (guest): something will happen
Leo Dion (host): where can people find you online?
Donny Wals (guest): On X, Donny Walls.
On, I think Mastodon also Donny Walls.
On all the social networks, just find Donny Walls.
And if you cannot find me by Donny Walls, find me by Donny Walls Dev,
which I think is what I had to use on Instagram because somebody stole Donny
Walls, and they're not even a Donny Walls
Leo Dion (host): what does that Donny Walls do?
Do you
Donny Wals (guest): steal my stuff.
Leo Dion (host): Oh, man.
Donny Wals (guest): Like literally it's I tried many times.
No so what they did is they posted like some weird picture, then three
pictures that they stole on my page, and then one other picture, and then they
haven't posted for six or seven years.
And every once in a while write to Instagram yeah, I write them
like, "Hey, that's my name.
That's my photos." And they ended up taking down my photos, but they're
like, "Yeah, well nothing we can do about them using your name."
Leo Dion (host): What?
Donny Wals (guest): was like, "Okay." They're not even using the account.
Like it, it sucks.
Yeah.
Leo Dion (host): Thank you again for coming on the show.
It was fantastic.
Donny Wals (guest): for having me
Leo Dion (host): people can find me online @leogdion, @leogdion.c.im
on Mastodon YouTube, we're at BrightDigit is the name of the channel.
If you're watching this on YouTube, and subscribe, and also and
subscribe to Donnie's channel too.
If you're on a podcast player, please go ahead and post a review.
I'd really appreciate it.
Oh, one more thing.
I have a newsletter again.
Yay.
I'm gonna post a link to the newsletter.
I finally m- moved from MailChimp to Buttondown, and it's a lot
nicer definitely check that out.
And check out the Patreon.
Thank you to Patreon supporters like Steve Lipton for helping support the show.
Oh, right.
So I'm gonna be installing Windows and learning about Windows.
I haven't touched Windows in over 12 years.
So if you have any questions for Selim, the I don't know, founder,
principal motivator of Swift for Windows drop me a line and let me
know what you want me to ask him, 'cause he'll be in the next episode.
We'll be talking about that story.
Thank you again, and I look forward to talking to you again.
Bye, everybody.
Donny Wals (guest): See ya