<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.2">Jekyll</generator><link href="https://www.coryzue.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.coryzue.com/" rel="alternate" type="text/html" /><updated>2026-03-06T15:08:09+00:00</updated><id>https://www.coryzue.com/feed.xml</id><title type="html">Cory Zue | Full-Stack Developer, Maker of Products, and Solopreneur</title><subtitle>Cory Zue is a software developer, aspiring entrepreneur, and occasional blogger. He&apos;s currently working at Dimagi and launching projects on the side.
</subtitle><author><name>Cory Zue</name></author><entry><title type="html">Software got weird</title><link href="https://www.coryzue.com/writing/software-got-weird/" rel="alternate" type="text/html" title="Software got weird" /><published>2026-03-06T00:00:00+00:00</published><updated>2026-03-06T00:00:00+00:00</updated><id>https://www.coryzue.com/writing/software-got-weird</id><content type="html" xml:base="https://www.coryzue.com/writing/software-got-weird/"><![CDATA[<!-- {:.cz-image-smaller} -->
<p><img src="/images/ai-weird/ai-train-smash-meme.png" alt="AI Train Smash" /></p>

<p>In the last few months AI hit software engineering like a train.</p>

<p>We went from “huh, this is getting pretty good” to “lol, claude do my job pls” in a matter of weeks.
Every engineer I know is now going through some sort of dramatic transition.
Some are loving it. Many hate it.
Most begrudgingly accept that it is the future and try to keep up.</p>

<p>Regardless of how you’re handling it,
what’s true is that AI has fully arrived,
and it is completely changing how we write software and build products.</p>

<p>These are my raw, disjoint thoughts on the topic.
And I hate that I have to even say this, but I—a human—wrote this.
And yes, I know I just used emdashes—I love them and refuse to let AI take them away from me.</p>

<h2 id="everything-is-easy-for-everyone">Everything is easy (for everyone)</h2>

<p>The great news for builders is that <strong>everything is now easy</strong>.
We can all take on more and do it better.
Companies are taking on projects that were previously deemed too big to tackle.
Indie hackers are shipping products from idea to production in days.
There are no speed limits any more. It’s an incredible time to build.</p>

<p>On the flip side, everything is easy <em>for everyone else too</em>.
That app you spent six years lovingly crafting? Cloned by a 19-year-old on a Saturday afternoon.</p>

<p>It used to be that to have the best product in the market you needed good taste and a lot of effort.
Now the effort side is almost negligible.</p>

<p>In other words…</p>

<h2 id="there-are-no-code-moats-anymore">There are no code moats anymore</h2>

<p>Your code today is a few prompts away from being someone else’s code tomorrow.
This applies to anything, from SaaS products to frameworks.
Cloudflare <a href="https://blog.cloudflare.com/vinext/">rebuilt Next.js in a week</a> for funsies.
Yes, it’s harder to clone Figma than your favorite todo app, but the gap is narrowing quickly.</p>

<p>As someone who—up till very recently—made a living <a href="https://www.saaspegasus.com/">selling a codebase</a>,
this is not a statement I make lightly.
But code is getting cheaper by the day, to the point that it could soon be completely disposable.
There still are moats: deep data integrations or having a big audience, for example.
But it’s no longer the tech.</p>

<h2 id="the-golden-age-of-indie-businesses-might-be-over">The golden age of indie businesses might be over</h2>

<p>I’m not sure if this is a personal problem or a broader one,
but it feels impossible to build durable indie businesses anymore.</p>

<p>I’ve spent a lot of time brainstorming new products to build and none of them excite me.
Everything is too copyable. The world is too unpredictable.
All the best ideas use AI,
and are one Anthropic feature announcement away from getting obsoleted overnight.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>

<p>And it’s not just a product problem.
Getting people to care about your app—even if it’s great—is impossible
when no one can tell the difference between quality and slop and everyone is drowning
in a sea of AI-generated content.</p>

<p>Yes, there are still ways to make money online, and plenty of people are doing well
riding short-term trends or going viral.
But the path I used to recommend—the one of slow-and-steady growth, climbing up the long, slow SaaS ramp of death—feels
like a relic of a bygone era.</p>

<h2 id="rois-have-gotten-weird">ROIs have gotten weird</h2>

<p>I’m going to shift gears from the impact of AI to my experience <em>using</em> AI.</p>

<p>One of the many strange effects of LLMs being superhuman code writers
is that the return on investment of how you spend your time has gotten extremely non-linear.
Three-minute prompts can become complete features or products.
But you can also spend hours tweaking how things work till you’re happy.</p>

<p>Or another example—I spent several hours writing this post.
Was that a good use of time when I could have dumped six bullets into Claude and
instantly had something that said 80% of what I wanted to?
I don’t know. But every time I do anything by hand now, I wonder if I’m being inefficient.</p>

<h2 id="we-are-the-bottleneck">We are the bottleneck</h2>

<p>Because the agents can do so much work without us, we become the speed limit of execution.</p>

<p>There are really only two bottlenecks to productivity now, and they’re both human.
The first is our ability to come up with useful things for agents to do.
The second is our ability to review and accept their work.</p>

<h2 id="choosing-what-to-do-is-still-hard">Choosing what to do is still hard</h2>

<p>Of the two bottlenecks, the bigger issue is tasking your agents.</p>

<p>There’s a weird pressure to always be getting the most out of your agent as possible.
But using an agent requires giving it a task, and good tasking remains unsolved.
After you burn through your bug backlog and feature roadmaps it’s easy to get stuck on what to do next.
Choosing what to do has always been hard, but agents—being the task-clearing maniacs they are—have made it much harder.</p>

<p><img src="/images/ai-weird/couple-agent-meme.png" alt="AI Couple" /></p>

<p>Maybe agents eventually just start making roadmaps for themselves?
It’s one of those things that sounds nonsensical and may be commonplace in a short time.</p>

<h2 id="we-might-stop-reviewing-code-soon">We might stop reviewing code soon</h2>

<p>The other bottleneck is trying to assess the agents’ work—e.g. code review.
For this problem, the obvious solution is to stop trying.</p>

<p>Does it matter if you understand what the agent did as long as you’ve verified it works?
Does it even matter how the agent did it?
I’m still not comfortable letting go of the reins on important projects,
but for vibe-coded utilities I’m definitely not looking much—or at all—at its work anymore.</p>

<h2 id="ai-control-is-a-frog-boiling-phenomenon">AI control is a frog-boiling phenomenon</h2>

<p>Yesterday I paired with AI. Today I review its work. Tomorrow I’ll probably just let it loose.
I’ll never explicitly choose to cede full control of my projects to AI.
It’ll just happen one little step at a time.</p>

<p>The problem is that the value you can extract from AI is inversely proportional to the time you spend overseeing it.
As we continue to extract more value—because it’s human nature to be more ambitious—the less we will check its work.</p>

<p>With code review this means eventually we don’t review the agent’s work at all.
With permissions, it means we go from approving every tool call, to whitelisting, to always running in YOLO mode.<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup>
With <a href="https://openclaw.ai/">OpenClaw</a> it means we limit access to our emails and bank accounts until eventually
we get so sick of having to type passwords and press buttons that we relent.</p>

<p>Will there be problems with this?
Absolutely. Databases will be deleted. Accounts will be hacked. Money will be lost.
But these things will be rare, and we’ll decide the microscopic risk is worth it.</p>

<p><strong>We aren’t going to decide at any given moment
to cede our reasoning, comprehension, trust and data to AI agents, but we will.</strong>
What happens after we’ve done that is anyone’s guess.</p>

<h2 id="nobody-knows-whats-going-to-happen-to-developers">Nobody knows what’s going to happen to developers</h2>

<p>If AI writes all the code, what are developers doing?</p>

<p>The optimistic take is that we’re needed to manage the AIs.
To prompt it and check its work and make sure it doesn’t go off the rails.
One human with taste and engineering chops can now control a fleet of agents
and will be more valuable than ever, they say.</p>

<p>The pessimistic take is that the AIs will soon be able to do all that too.
And the role of “person who understands code and computers”
will become a cute artifact of a bygone era,
in the same way that <a href="https://en.wikipedia.org/wiki/Computer_(occupation)">the original “computers” were people doing math by hand</a>.</p>

<p>Every developer I’ve talked to in the last month is suddenly worried about long-term job security
for the first time in their life.
And no one has any idea what’s coming next.</p>

<h2 id="there-is-a-big-short-term-market-in-ai-adoption-arbitrage">There is a big, short-term market in AI adoption arbitrage</h2>

<p>With developers uncertain about their futures, some I know are trying to earn as much as possible in the next few years.</p>

<p>I have multiple freelancer friends with similar stories about how they have approached this.
Some company still living in the “before times” solicits a software project
that they expect to take six months—because that’s how long projects like it have taken in the past.
The engineer then puts in a $100k proposal, wins it, and has Claude build the whole thing in a weekend.</p>

<p>Is this the last chance for engineers to earn a living?
By finding the organizations that haven’t figured AI out yet,
dramatically overcharging them for work that agents make easy,
and repeating until there aren’t any more luddites left?</p>

<p>It’s possible that we have maybe 1-2 years to generate wealth before everyone catches on and we’re all out of work.
I’ve now had this conversation with multiple people, and we were never sure if we were joking or not.</p>

<h2 id="where-does-this-go">Where does this go?</h2>

<p>Most of my conversations about AI end with “man, weird times we’re living in”.
Then we just stare off into space for a bit, lost in thought, before snapping back to reality.</p>

<p><strong>We are living in very weird times.</strong></p>

<p>Nobody knows what’s going to happen. To our jobs. To our kids. To society.</p>

<p>I’ve spent a lot of time thinking and worrying about the future,
but I’m slowly coming to terms with the fact that this—whatever it is—is happening.
And there’s basically nothing I can do to stop it or change its course.</p>

<p>It’s all just so strange.
I spend all day talking to a robot genius and wondering if there will be any work to do in the future.
And then, in the evening I play with my kids—happily joking about silly real things in the silly real world.</p>

<p>I don’t know what’s coming next, but at least there’s something to being human that will survive it.</p>

<hr />

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Recent Anthropic feature announcements of legal and security-specific tools have literally caused
  <a href="https://www.bloomberg.com/news/articles/2026-02-03/legal-software-stocks-plunge-as-anthropic-releases-new-ai-tool">hundreds of billions of dollars in market selloffs</a>. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>YOLO-mode is a way of running agents in a way that allows them to do anything they want on your system. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Cory Zue</name></author><category term="sabbatical" /><summary type="html"><![CDATA[Disjoint thoughts on AI and the future of building things.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.coryzue.com/images/ai-weird/ai-train-smash-meme.png" /><media:content medium="image" url="https://www.coryzue.com/images/ai-weird/ai-train-smash-meme.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">How I’m writing code in 2026</title><link href="https://www.coryzue.com/writing/coding-2026/" rel="alternate" type="text/html" title="How I’m writing code in 2026" /><published>2026-02-03T00:00:00+00:00</published><updated>2026-02-03T00:00:00+00:00</updated><id>https://www.coryzue.com/writing/coding-2026</id><content type="html" xml:base="https://www.coryzue.com/writing/coding-2026/"><![CDATA[<p>I tend to be the type of person that likes boring, stable technology.
You know, “if it ain’t broke, don’t fix it.”</p>

<p>But I’m also a realist. And I know that AI is coming to upend coding work faster than ever.</p>

<p>So as a compromise I try to keep up with advances in AI programming just a bit after they’ve gone fully-mainstream.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>
This used to mean updating my tooling every 3-6 months or so, but lately it feels like everything’s moving a lot faster!</p>

<p>Here’s what I’m doing now (at the beginning of February, 2026).
Notably, it’s completely different than what I was doing just 2-3 months ago.</p>

<p>My motivation for this post is that when I go on Twitter/X I feel like I am way behind all the agent-maxxers
who are running 15 instances of <a href="https://github.com/anthropics/claude-code/blob/main/plugins/ralph-wiggum/README.md">Ralph</a> or <a href="https://openclaw.ai/">molty</a> or whatever the latest thing is.
But I think there are a lot of people like me that are dipping their toes into new tools
a bit more slowly and carefully.
This post is for those people, and trying to be a bit less hype-driven than the average AI-influencer content out there.</p>

<p><img src="/images/musings/cant.jpeg" alt="Twitter" /></p>

<p class="cz-image-caption">How it feels to go on Twitter/X lately. <a href="https://x.com/ChShersh/status/2018035377886343624">Source</a></p>

<h2 id="my-primary-workflow">My primary workflow</h2>

<p>Sometime in the past couple months I’ve gone from pair-programming with AI to mostly speccing and reviewing its work.
My daily driver is Claude Code with Opus.<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<p>For any given feature I’ll do something like the following:</p>

<ol>
  <li><strong>Prompt.</strong> I tell Claude what I want it to do, give it some pointers to examples and relevant code, and set it loose.
If it’s a more complex task I’ll use <code class="language-plaintext highlighter-rouge">/plan</code> mode and iterate on a spec till I’m happy, then let it loose.</li>
  <li><strong>Wait.</strong> Claude cranks away on the feature and I auto-accept edits.
I liberally use “accept and allow all future commands like this” to keep a growing whitelist for most tool calls,
but I’m still not brave enough to run with <code class="language-plaintext highlighter-rouge">--dangerously-skip-permissions</code>.</li>
  <li><strong>Review.</strong> I will normally have Claude push its work to a new branch and use the Github diff/PR view to code review its work,
similar to how I would if collaborating with another developer. I use this time to ask Claude questions about the implementation and
suggest changes. It’s also the time when I make sure I have my own head wrapped around the code, and do any manual testing.</li>
</ol>

<p>And that’s basically it! My job is now basically a product manager (prioritizing and writing specs) and code/architecture reviewer.
It’s a weird adjustment that I’m still getting used to.</p>

<p>I still use an IDE and occasionally make small changes (usually deleting things or changing the wording of comments/doc strings).
But more and more I’ll just tell Claude what to do and let it do the changes itself.
I cancelled my Cursor subscription and have found myself not even opening my IDE sometimes—especially when multitasking on multiple projects.</p>

<p>Speaking of which…</p>

<h3 id="multitasking">Multitasking</h3>

<p>The biggest issue with this workflow is the downtime while Claude is cranking away.
I’m still not happy with how I make use of this time, but what I’m usually doing falls into one of these buckets:</p>

<ul>
  <li><strong>Watching and thinking.</strong> This was my historical default. Basically, watching the agent, trying to follow along with what it’s doing,
and interrupting it when I want it to do something different. I <em>like</em> doing this, because it allows me to kind of stay
in flow and understand the work in real time. But lately the downtime is too long to hold my attention
(hence the shift to “review after it’s done”).</li>
  <li><strong>Planning the next task.</strong> Figuring out what we’ll work on next. This is another good one, that helps me stay in flow.
Especially if I’m working on a big project and can execute a sequence of related steps towards a broader goal.</li>
  <li><strong>Exercising.</strong> I know, it’s a meme. But doing a quick set of push-ups or sit-ups while the agent cranks away is a great way to
use the body while the mind still noodles on the work. And it just kinda fires you up.</li>
  <li><strong>Getting distracted.</strong> Basically, going on Twitter/X, WhatsApp, email, etc. This is an easy trap to fall into, though I try quite
hard to be disciplined about it. But certainly it happens more than I want it to.</li>
  <li><strong>Parallel development.</strong> This is what I feel like I <em>should</em> be doing. Using the downtime of one agent to fire off another agent,
and building out 2-3 (or more?!) features at a time. I have dabbled with this workflow but I find it leaves me feeling very distracted
and significantly lowers the quality of my review step, which requires concentrated thought.</li>
</ul>

<p>Overall I think getting efficient at multitasking would be the greatest force-multiplier in terms of productivity.
But also, it really hurts my brain! I’m still trying to figure out what “efficient enough” looks like in a way that doesn’t drive me crazy.
But there’s lots to explore here.</p>

<h2 id="tooling">Tooling</h2>

<p>Like everyone, I’m experimenting with lots of tooling right now trying to optimize my setup.
Here’s some things I’m using, in approximate order of how seriously I have adopted them.</p>

<h3 id="maturing-skills">Maturing: Skills</h3>

<p>I’ve only been using <a href="https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview">Claude Skills</a> for a few weeks
but I’m a big fan, and have written almost one per day since adopting them into my workflow.</p>

<p>My mental model for when skills are useful is any low-to-medium complexity task I do regularly.
Instead of doing the task I write up the instructions for how I would do the task in a new skill, and then ask the agent to use it.
Then whenever the agent deviates from what I wanted, I ask it to update the skill itself so it does the right thing in the future.</p>

<p>Examples:</p>

<ul>
  <li><a href="https://github.com/saaspegasus/django-skills/blob/main/skills/fix-types/SKILL.md">A skill I used to get mypy passing on my Django projects</a></li>
  <li><a href="https://github.com/czue/agent-tools/blob/main/skills/release-notes/SKILL.md">A skill I use to draft release notes for SaaS Pegasus</a></li>
</ul>

<h3 id="adopting-cli-scripts">Adopting: CLI scripts</h3>

<p>Agents and scripts go together really nicely. For two reasons:</p>

<ol>
  <li>Giving an agent a script is like hooking it up to a new power.</li>
  <li>Agents are <em>really</em> good at writing scripts!</li>
</ol>

<p>Scripts can also be bundled with skills to provide not just a set of instructions but also all the tools needed to execute them.
These can get you really far for repetitive workflows!</p>

<p>I’m trying to be more aware of when a script might save me and my agents time and pain and create them instead of doing things manually.</p>

<p>Examples:</p>

<ul>
  <li>My release notes skill uses <a href="https://github.com/czue/agent-tools/blob/main/skills/release-notes/scripts/make_diff.py">this script to generate consistently-formatted diffs</a></li>
  <li>I wanted an equivalent to <code class="language-plaintext highlighter-rouge">workon</code> from <code class="language-plaintext highlighter-rouge">virtualenvwrapper</code> but for <code class="language-plaintext highlighter-rouge">uv</code> projects, so I had Claude
<a href="https://github.com/czue/dev-on">write one for me as a rust binary</a>.</li>
</ul>

<h3 id="experimenting-worktrees">Experimenting: Worktrees</h3>

<p>Like I said above, I’m still having trouble with multi-tasking my agents.
But I want to get better at it, and I <em>think</em> worktrees are the answer.</p>

<p>I’ve been trying to use them more. My ideal workflow is something like:</p>

<ol>
  <li>Create worktree for new feature.</li>
  <li>Run script to setup environment. Every DB, web app, etc. needs its own port setup for isolation and verification.</li>
  <li>Run the normal agent workflow in the worktree.</li>
</ol>

<p>And technically this works! My biggest issue comes down to core multitasking capabilities as well as maybe,
my ability to generate correctly-scoped, independent tasks for an agent on my projects.
I also experimented a bit with <a href="https://www.vibekanban.com/">vibe-kanban</a>, but ran into similar issues with speccing/tasking.</p>

<h3 id="experimenting-openclaw">Experimenting: OpenClaw</h3>

<p>With all the hype around <a href="https://openclaw.ai/">OpenClaw</a> (formerly: ClawdBot and Moltbot) I forced myself to try it out.
I set it up with root access on a fresh VPS and slowly started giving it minimal access to things, including a dev
environment for one of my projects.</p>

<p>It’s been… interesting? I love the form factor of sending messages or voice notes from my Telegram, and the
“just go install something if you need it” paradigm opens up some fun use cases.</p>

<p>But also, it managed to expose the server to crypto miners in the first two days. Which wasn’t that cool.</p>

<p><img src="/images/musings/clawd-crypto.png" alt="Crypto Miners" /></p>

<p class="cz-image-caption">My ClawdBot managed to get its own server pwned in less than 48 hours.</p>

<p>So far I don’t think it’s going to be a helpful form-factor for coding, but it is useful for automating other tasks.</p>

<p>Examples:</p>

<ul>
  <li>I asked it to do a competitor search/analysis for one of my products and upload it to a Google Sheet.</li>
  <li>At least it managed to fix itself after it pwned itself.</li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>So that’s how I’m using AI in my coding work today!
If you ask me to document this again in a few weeks I’m sure it’d be different.
But that’s the age we’re living in now.
We’ve moved on from the era where AI skeptics can be taken seriously, and are now speeding towards bigger changes faster and faster.</p>

<p>I don’t know where that ends up, but I’m hoping to stay along for the ride as long as I can.
And if you’re a coder who’s not using AI much, I strongly encourage you to start!
Even just blocking out an hour or two a week to try out some new tools goes a long way.</p>

<hr />
<p><strong>Notes</strong></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">

      <p>Or at least mainstream among early-adopter types. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">

      <p>I haven’t tried Codex, even though I know it’s supposed to be better at complex tasks. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Cory Zue</name></author><category term="writing" /><category term="musings" /><summary type="html"><![CDATA[How I write code now looks nothing like my setup from just a few months ago.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.coryzue.com/images/musings/cant.jpeg" /><media:content medium="image" url="https://www.coryzue.com/images/musings/cant.jpeg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">What happened in 2025</title><link href="https://www.coryzue.com/writing/2025-epilogue/" rel="alternate" type="text/html" title="What happened in 2025" /><published>2025-12-30T00:00:00+00:00</published><updated>2025-12-30T00:00:00+00:00</updated><id>https://www.coryzue.com/writing/2025-epilogue</id><content type="html" xml:base="https://www.coryzue.com/writing/2025-epilogue/"><![CDATA[<p>I needed to <a href="/writing/the-line/">get all the existential career stuff off my chest</a>,
but I also wanted to make sure to document what actually happened this year,
since a huge benefit of this process is being able to come back and remind myself what I was doing in past years.</p>

<h2 id="what-got-done">What got done</h2>

<p>Big picture, professionally, I would say I spent the first half of the year worrying about AI and the future of Pegasus,
and I spent the second half of the year ramping up on contracting work and keeping Pegasus running.</p>

<p>Here’s a bit more detail:</p>

<ul>
  <li>I shipped <a href="https://docs.saaspegasus.com/release-notes">27 Pegasus releases</a>—focused mostly on stability, tooling, and AI.
    <ul>
      <li>Highlights include: upgrading to Tailwind 4, adding AI-assistant tooling and MCP, major multi-tenancy enhancements, swapping Webpack for Vite, adding an integrated chatbot with agent support, streamlining the dev setup, and staying current with the latest AI chat and image models and best practices.</li>
    </ul>
  </li>
  <li>I published <a href="https://www.coryzue.com/writing/">11 articles on my blog</a> (not counting this one). Also mostly focused on AI.</li>
  <li>I published one new Django guide on <a href="https://www.saaspegasus.com/guides/modern-javascript-for-django-developers/integrating-javascript-pipeline-vite/">using Django with Vite</a>.</li>
  <li>I published <a href="https://www.youtube.com/@czue">9 videos on my YouTube Channel</a>, all focused on coding and AI.</li>
  <li>I built and launched <a href="https://lifeweeks.app/">LifeWeeks</a>—a way to create a timeline of your life where every week is a little box.
In the last year, more than 13,000 people have tried it.</li>
</ul>

<p><img src="/images/musings/lifeweeks-hero.png" alt="LifeWeeks" /></p>

<ul>
  <li>I completely rewrote <a href="https://chromewebstore.google.com/detail/photos-new-tab/fpljkobkodmnmldgodfefnmjgjlljbjn">my Chrome extension that shows Google Photos in your new tabs</a>, after Google killed all the APIs it had been using.</li>
  <li>I released an <a href="https://github.com/saaspegasus/django-vite-tailwind-starter/">open-source Django / Vite starter project</a>.</li>
  <li>I vibe-coded many different projects to varying degrees of completeness.
Most of these were small tools for myself or experiments I was playing with. They include:
    <ul>
      <li>A <a href="https://djobs.dev/">Django job board</a></li>
      <li>A <a href="https://www.saaspegasus.com/stripe-fees/">Stripe fee calculator</a></li>
      <li>An AI-powered comic maker (not public yet)</li>
      <li>A tool to notify me when new bookings are available on the South African National Parks site.</li>
      <li>A library of little agent tools I’m using to automate workflows like moving blogs from GDocs to my website,
and drafting Pegasus release notes.</li>
    </ul>
  </li>
  <li>I started contracting with <a href="https://peregrine.io/">Peregrine</a>, and helped build several AI features for them.</li>
</ul>

<p>It’s easy to get caught up in the minutiae of the days and weeks and feel like I never make progress on anything,
but looking back on this list it’s clear that I got a decent amount done!</p>

<h2 id="life-outside-of-work">Life outside of work</h2>

<p>Our nuclear family continues to do well, and the boys—now five and seven—are easier, more fun, and more interesting than ever before.
Out of nowhere Lockwood is now a near-fluent reader, and has a blossoming set of interests and friends,
making me a relieved introvert dad!
Victor learned to ride a pedal bike effortlessly, has started playing Nintendo with his big brother,
and remains a joyful, hilarious, and mysterious alien creature.</p>

<p>Outside of our family it’s more of a mixed bag.
There continued to be health issues, scares, and difficult events in our extended family.
Thankfully, my body hasn’t declined further, which, at my age, I’ll take.</p>

<p>Our friend circle in Cape Town continues to improve.
I’m slowly coming to accept that there won’t be something like the friendships I had in my 20s in my life for a while,
and that’s pretty normal for this phase, regardless of where you live.</p>

<p>Travel this year was a usual highlight.
Our main event was a seven-city trip to the US where we made it all the way to see my parents in Hawaii.
The boys loved the snorkeling, and it was great for them to spend so much time with their grandparents.
We also got to see cousins, uncles, aunts, and friends galore.
One of the nice things about being so far away from most of our family is that everyone makes time for us when we come to visit.
Separate from the big trip, we also had a great stay in Mauritius, a number of visitors to Cape Town, and several memorable weekends away.</p>

<p>I’m still trying my hardest to appreciate this period of my life and make the most of it.</p>

<p>Having kids who love spending time with me and are so full of life is a gift—even if it is also very tiring!
I think of all the families I know that are heavily constrained by strict work hours and limited vacation time,
and I feel incredibly grateful to be able to spend so much time with the boys while they still like me.</p>

<p>Through all the ups and downs of the career I’ve chosen, it’s hard to imagine anything that would make this freedom not worth it.</p>

<p><img src="/images/2025/lions-head.jpg" alt="Family on Lion's Head" /></p>

<p class="cz-image-caption">The family at the top of Lion’s Head. December 26, 2025.</p>]]></content><author><name>Cory Zue</name></author><category term="writing" /><category term="sabbatical" /><summary type="html"><![CDATA[A short write up on the events of the year.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.coryzue.com/images/2025/lions-head.jpg" /><media:content medium="image" url="https://www.coryzue.com/images/2025/lions-head.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">When the line stops going up</title><link href="https://www.coryzue.com/writing/the-line/" rel="alternate" type="text/html" title="When the line stops going up" /><published>2025-12-30T00:00:00+00:00</published><updated>2025-12-30T00:00:00+00:00</updated><id>https://www.coryzue.com/writing/the-line</id><content type="html" xml:base="https://www.coryzue.com/writing/the-line/"><![CDATA[<p><em>This is my ninth year-in-review, where I document my journey of building
and selling products online, a.k.a. indie hacking.
For the past few years I’ve mostly worked on <a href="https://www.saaspegasus.com/">SaaS Pegasus, a Django starter codebase</a>
for building SaaS apps.</em></p>

<p><em>Previous years:
<a href="/writing/2024/">2024</a> |
<a href="/writing/2023/">2023</a> |
<a href="/writing/man-in-the-arena/">2022</a> |
<a href="/writing/financial-freedom/">2021</a> |
<a href="/writing/2020/">2020</a> |
<a href="/writing/master-plan/">2019</a> |
<a href="/writing/a-tale-of-two-years/">2018</a> |
<a href="/writing/the-year-everything-changed/">2017</a></em></p>

<hr />

<p>It’s easy to build in public when things are going well.</p>

<p>It sucks when things aren’t.</p>

<p>Since I started my solopreneur career nine years ago, every year I’ve earned more than the last.
The $800 I earned in 2017 became $12,000 in 2018, then $25k, $42k, $110k, $145k.
At that point I stopped sharing things publicly, but the numbers kept going up.</p>

<p>Until this year.</p>

<p>This was the first year where my income from my products went <em>down</em>.
And not down just by a little—down by over 30%.</p>

<p>I have to get this out of the way up front, because my year was dominated by the backdrop of this inflection point.
In trying to understand why it was happening and what to do about it.
The way it impacted my psyche and sense of self-worth.
And how it changed what I did, and how I’m thinking about the future.</p>

<p>To be honest, I feel a bit lost.
It feels like much of the year was spent grasping at different ideas and ways of adapting to the situation while not necessarily landing on any plan I actually like.
Part of me is hoping that by writing this all down I can get myself to a place where I better understand what to do next.
Another part of me worries I won’t figure anything out, but wants to get it all out anyway.</p>

<p>Either way, let’s see how it goes.</p>

<h3 id="the-numbers">The numbers</h3>

<p>In <a href="/2024/">last year’s review</a> I shared a graph of my main product, <a href="https://www.saaspegasus.com/">SaaS Pegasus’s</a>, revenue by year.
Here’s that graph with 2025 added.</p>

<p><img src="/images/2025/all-pegasus-income.png" alt="All time Pegasus income" /></p>

<p>Here’s how 2025 income (purple) compares to 2024 (dotted grey), by month.</p>

<p><img src="/images/2025/2025-revenue-by-month.png" alt="2025 vs 2024 Pegasus income" /></p>

<p>Like I said—kind of bleak. Those summer months were rough!
Things picked up a bit at the end of the year for my annual sale, but were a far cry from past years.</p>

<p>Now I’m going to talk about some of the impact this change has had on me.</p>

<h3 id="the-psychology-of-peaking">The psychology of peaking</h3>

<p>I got into running pretty late in life—in my mid-30s, and around the same time I started trying to be a solopreneur.</p>

<p>One of the best things about taking up a new hobby is that you are constantly improving.
This means that you can regularly <a href="/writing/best-of-your-life/">beat your own personal bests</a>.
But as my fitness gains started leveling off, I found myself plateauing.
Then I hit 40, had an injury, and suddenly my peak running shape was behind me.
Running no longer gives me the daily thrill of improvement, but is more an exercise in fighting off further decline.</p>

<p><img src="/images/2025/exercise-tweet.png" alt="Exercise Tweet" /></p>

<p class="cz-image-caption">How exercise changes as you age. <a href="https://x.com/czue/status/2001254823690428494">Source</a>.</p>

<p>This sucks!
Psychologically, accepting that you are just never going to be able to do something as well as you used to is a hard thing to accept.
This inflection point of physical capabilities was one of the many small triggers of mid-life crisis I’ve bumped into in recent years.</p>

<p>Anyway, the point is that this is kind of similar to how things feel with entrepreneurship now.
Like with running, I’m still way ahead of where I was a decade ago.
But I’m on the opposite side of a peak, looking downhill.</p>

<p>The analogy doesn’t quite work, since obviously it’s possible to recover a declining business.
Maybe I also just wanted to bitch about growing older?
Either way, fighting off decline is just way less fun than growing from nothing.</p>

<p>And it’s hard coming to terms with the possibility that you may be past your prime.</p>

<h3 id="the-hedonic-adaptation-of-a-number">The hedonic adaptation of a number</h3>

<p><em>Hedonic adaptation</em> is a phenomenon related to how we humans perceive change.</p>

<p>When something—let’s say your income—gets better in your life,
you get a little boost of happiness.
But quickly, most people revert back to the same baseline level as before the change.
The result is that <strong>most lifestyle improvements feel short-lived</strong>.
You keep chasing the next upgrade, but the feeling of improvement never lasts.
And eventually you’re on a <em><a href="https://en.wikipedia.org/wiki/Hedonic_treadmill">hedonic treadmill</a></em>—constantly
trying to achieve the next thing and not ever feeling any better.</p>

<p>As my income went up over the past decade, my lifestyle has mostly stayed the same.
We were already doing great, and we’re still doing great.</p>

<p>The only thing that’s <em>really</em> changed was a number in a bank ledger somewhere.
That number has been higher than I need it to be for some time and will remain that way indefinitely.</p>

<p>From that perspective, it really doesn’t matter if I’m earning $100k, $200k, or $500k per year.</p>

<p>But, as the number has gone up over the years, I’ve <em>adapted</em> to it.
So now, when my income goes down from “more than enough” to “more than enough but less” I somehow feel like it’s a problem.</p>

<p>And it’s not!</p>

<p>It <em>could</em> be a problem—years and years from now if the trend keeps up and I don’t figure anything else out.
But it is nothing close to a problem today.
At most, it’s a concern. A concern I have years to act on.</p>

<p>I say all this, because even though I know all of the above to be true, <em>it doesn’t feel that way</em>.
My stupid monkey brain sees “number go down = panic.”
And so I’m constantly discouraged and scheming on how to make the number go back up.
Much to my own psychological detriment.</p>

<h3 id="returning-to-the-workforce">Returning to the workforce</h3>

<p>It is under the backdrop of feeling past my prime and a fake concern about not earning enough money that I found myself considering returning to the workforce.
And when what looked like a perfect opportunity landed in my lap—building AI features for a San Francisco-based startup—I decided to take on a part-time contracting job.</p>

<p>Why did I take the job?</p>

<p>Partly, yes, because my monkey brain was panicking about my income going down.
That was definitely the catalyst.</p>

<p>But it wasn’t just that.
Recently, I’ve been feeling like me and Pegasus have been a bit stagnant.
And I thought getting some exposure to the environment of a high-growth, well-funded Silicon Valley startup would be a great learning opportunity.
Which it has been.
It’s also been a great chance to better understand production AI systems at scale.</p>

<p>Why didn’t I tell anyone I took the job?
I think for similar reasons I didn’t announce Pegasus’s declining revenue.
<em>Because it kind of feels like admitting failure</em>.</p>

<p>Going back to contracting after “making it” on my own looks a lot like a step backwards.
And even if I can fully justify all the reasons why it’s been a good step for my career,
I worry it will be perceived as me giving up on my own products and abandoning the indie hacker dream.
Something like that.</p>

<p>Anyway, that’s the backstory.
So for the second half of the year I spent about half my time on solo-projects (mostly Pegasus)
and half my time contracting at a fast-growing tech startup.</p>

<h3 id="the-self-fulfilling-prophecy-problem">The self-fulfilling prophecy problem</h3>

<p>Ok, I think that is all the context and cards out on the table.
Which means I can start reflecting more on the year.</p>

<p>To summarize where we are so far:</p>

<ol>
  <li>Pegasus revenue started going down.</li>
  <li>I panicked and took on a part time job.</li>
  <li>I now have less time to work on Pegasus.</li>
</ol>

<p>I’m now growing worried that I might have entered an anti-flywheel of sorts.</p>

<p>When I am full-time on Pegasus it’s pretty easy for me to handle customer support, do new feature development, and do a bunch of marketing/exploration work in any given month.</p>

<p>But, when I’m half-time on Pegasus that gets a lot harder.
The support burden stays the same, taking up a bigger chunk of my available time,
and leaving little left for the proactive stuff.</p>

<p><img src="/images/2025/time-allocation.png" alt="Time Allocation" /></p>

<p>This reduced time makes it harder to address issues in the Pegasus business, take new strategic risks or do big marketing efforts.
In the end I worry it could lead to a self-fulfilling death-spiral:</p>

<p><img src="/images/2025/pegasus-death-spiral.png" alt="Pegasus Death Spiral" /></p>

<p>If I want Pegasus to survive and thrive I need to figure out why revenue and sales are going down and right the ship.
But the less time I have available, the harder that becomes.
So while it’s true that this job has exposed me to a lot of things that will be useful for Pegasus long-term,
it’s also true that the job makes it fundamentally harder to experiment, iterate, and focus on Pegasus in the short-term.</p>

<p>By taking the “safe” route of supplementing my income, am I setting Pegasus up for failure?</p>

<h3 id="looming-ai-and-the-conviction-problem">Looming AI and the conviction problem</h3>

<p>I used to be certain that Pegasus was solving a real problem, and if I could execute well on product and marketing,
it would find a place in the market.</p>

<p>But with the advent of AI, the future of Pegasus is a lot more uncertain.
I’ve been having <a href="/writing/dec-2024/">conversations</a> <a href="/writing/ai-and-coding/">about</a> <a href="/writing/preparing-for-superintelligence/">this</a>
with myself for at least a year, but the trend is hard to miss.
AI is coming for coding, and boilerplate code will be one of the first pillars to fall.</p>

<p>Now don’t get me wrong, I still believe that Pegasus is a hugely valuable product.
I recently <a href="https://eomail3.com/web-version?p=27db30cc-ce8a-11f0-8d20-1719d955881b&amp;pt=campaign&amp;t=1764679311&amp;s=ee6c9cb797e0081e2beba54fcbf73b545382afcce9357426d9f6fcbaaa44abf8">wrote up why for my mailing list</a>, and I stand by these words.
Here’s the conclusion:</p>

<blockquote>
  <p>There might one day be a time when AI is so good at coding that products like Pegasus are no longer necessary, but that day is not today.
Today, a vetted foundation like Pegasus is one of the best ways to set yourself up for long-term success.</p>
</blockquote>

<p>Yes, Pegasus is still good <em>today</em>.
I just don’t really think I should bet against the progress of technology.</p>

<p>This is part of why I’m so conflicted about the whole “returning to a job” thing.
On the one hand, I might be setting Pegasus up for failure by not investing wholly in it.
On the other hand, if Pegasus is <em>fundamentally doomed</em>—at least in its current incarnation—then not investing in it is just good common sense.</p>

<p>This is hard for me to put in writing, but I think I am slowly coming to terms with the fact that Pegasus, in its current form, is unlikely to survive the age of AI coding.
I think it’s still got some runway before the AIs catch up, and will provide great value to people using it for years to come.
But I have to accept that Pegasus—as it is in 2025—might not be very useful to the coders of 2035.</p>

<p>So if the current incarnation of Pegasus has an expiration date, what do I do next?</p>

<h3 id="the-scary-possibility-of-starting-over">The scary possibility of starting over</h3>

<p>I’ve built some 20-something products over the last decade.
Five have made some money.
Two have made at least $100k.
But only Pegasus has ever provided salary-replacement-level income.</p>

<p>If the future of Pegasus is doomed because AI eliminates the category, the main alternative to returning to the workforce is to figure out something else of my own.
Maybe it’s a Pegasus pivot.
Maybe it’s a new product.
Maybe it’s something more unusual like a Substack or real-estate business.
Who knows.</p>

<p>This path sounds—frankly—exhausting.
But also kind of awesome if it worked?
There’s still nothing I love more than creating products that help people,
and being able to do that while living on my own terms has been such a privilege.</p>

<p>It’s hard to know what my success rate would be on this path.
I have a lot going for me that I didn’t have when I first got started.
A bunch of entrepreneurial knowledge and scars.
A small-but-not-zero audience across social media and YouTube.
A lot of runway.
<em>Pegasus</em>.</p>

<p>What I don’t have is the ability to predict the future.
I’ve never had that, of course, but it <em>felt</em> a lot easier ten years ago than it does now.
The AI era is full of new miracles every day.
And because of that it is frustratingly hard to figure out what’s coming next.
Will coding be dead?
Will SaaS be dead?
Will white collar work be dead?
Will <em>humans</em> be dead?!
That these are all actual questions that serious people debate is just wild.</p>

<p>Anyway, in the age of AI I think there are really only two remotely “safe” options.</p>

<p>The first is to go all-in—ride the AI wave and see where it takes me.
This seems to be what a lot of smart, technical people that I admire are doing.
For Pegasus, it might mean making the best way to build AI products, or making an AI-powered code generator.
For <em>me</em>, it probably just means trying to stay at the bleeding edge of AI developments and see where that takes my career.
This path is largely aligned with my background and skills, though keeping pace with AI is a never-ending sprint that I’m not sure I’m willing to sign up for.</p>

<p>The other path is to find things that will be resilient—even in the age of AI.
The first-principles-level “safe” investments that come to mind are things like real estate, restaurants, experiences, and communities.
People will always want to live in nice places, eat good food, and do interesting stuff with other people.
Those might be AI-resistant things to do, but they are also quite a leap from my current career path.</p>

<p>Hmm…</p>

<h3 id="i-dont-know-what-happens-next">I don’t know what happens next</h3>

<p>I wrote above:</p>

<blockquote>
  <p>Part of me is hoping that by writing this all down I can get myself to a place where I better understand what to do next.
Another part of me worries I won’t figure anything out, but wants to get it all out anyway.</p>
</blockquote>

<p>Having gotten everything down, I think it’s clear that it’s the second option.
<em><strong>I don’t know what happens next.</strong></em></p>

<p>What I <em>do</em> have is more clarity on the problem, some good options to explore, and the peace of mind of finally getting all this out in the open.</p>

<p>The world is changing fast, and it appears the era of my career where I was able to coast by with SaaS Pegasus is coming to a close.
I guess it’s time to adapt or die.</p>

<p>And so the roller-coaster continues!</p>

<p>Let’s see where it takes me next.</p>

<hr />

<p><em>If you’re interested in more, I also wrote a <a href="/writing/2025-epilogue/">separate, more personal update covering the details of the year</a>,
and you can sign up below to get emailed when I publish new stuff.</em></p>]]></content><author><name>Cory Zue</name></author><category term="writing" /><category term="sabbatical" /><summary type="html"><![CDATA[As the world changes, my solopreneur career may be in jeopardy]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.coryzue.com/images/2025/2025-social.png" /><media:content medium="image" url="https://www.coryzue.com/images/2025/2025-social.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Six-word statements of gratitude</title><link href="https://www.coryzue.com/writing/gratitude/" rel="alternate" type="text/html" title="Six-word statements of gratitude" /><published>2025-11-27T00:00:00+00:00</published><updated>2025-11-27T00:00:00+00:00</updated><id>https://www.coryzue.com/writing/gratitude</id><content type="html" xml:base="https://www.coryzue.com/writing/gratitude/"><![CDATA[<p>Happy gratitude day!</p>

<p>Yesterday, <a href="https://messaging-custom-newsletters.nytimes.com/dynamic/render?uri=nyt://newsletter/ebe9503b-0dc7-5805-b61c-55a10ae699df">the New York Times published a series of six-word statements of gratitude</a>,
and I thought it’d be fun to try it myself.</p>

<p>Here’s what I came up with first:</p>

<ul>
  <li><em>Health. Kids. Partner. Freedom. Options. Fun.</em></li>
</ul>

<p>It felt a bit like I was cheating, though, picking six different, giant things.</p>

<p>So I decided to turn each one into its own six-word statement.</p>

<p>Here are those:</p>

<ul>
  <li><em>Still reasonably fit for mid-40s.</em></li>
  <li><em>Our home is full of joy.</em></li>
  <li><em>Her unwavering partnership, support and love.</em></li>
  <li><em>My time is mine to control.</em></li>
  <li><em>Countless career options to try next.</em></li>
  <li><em>Enjoying most of my time, daily.</em></li>
</ul>

<p>I don’t typically do a good job of practicing gratitude—I tend to either be too heads-down,
or focused on problems and how to solve them.</p>

<p>But I recommend this exercise!
It helped me take a beat and realize that despite all my concerns and uncertainty
about my life, career, the future, and everything else, I have it pretty good.</p>

<ul>
  <li><em>A lot to be grateful for.</em></li>
</ul>]]></content><author><name>Cory Zue</name></author><category term="writing" /><category term="musings" /><summary type="html"><![CDATA[A small constraint to help you give big thanks]]></summary></entry><entry><title type="html">How to disable CloudFlare proxying when you can’t access the dashboard</title><link href="https://www.coryzue.com/writing/cloudflare-dns/" rel="alternate" type="text/html" title="How to disable CloudFlare proxying when you can’t access the dashboard" /><published>2025-11-19T00:00:00+00:00</published><updated>2025-11-19T00:00:00+00:00</updated><id>https://www.coryzue.com/writing/cloudflare-dns</id><content type="html" xml:base="https://www.coryzue.com/writing/cloudflare-dns/"><![CDATA[<p>So yesterday, I, like a lot of the internet, found many of my websites down.
The issue was not anything to do with me or my servers, but with <a href="https://www.cloudflare.com/">CloudFlare</a>—a
tool I use for DNS and to help with performance and against attacks.</p>

<p><img src="/images/cloudflare/pegasus-down.png" alt="Pegasus Down" /></p>

<p class="cz-image-caption">My site was fine, but CloudFlare still wouldn’t let anyone load it.</p>

<p>The most frustrating thing about this situation was that in theory all I had to do was change one flag
in my DNS settings—the flag that told CloudFlare to proxy my domain—and everything would work perfectly!
The only problem was that CloudFlare itself was also down<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>, which meant I couldn’t log in to make the simple change.</p>

<p>I <em>could</em> do it from the API if I had an API key, but unfortunately I didn’t, and creating an API key also happens
in the dashboard.</p>

<p>In case you ever want to be able to recover from this situation, should it happen in the future, here’s what you can do.</p>

<p>First, <strong>right now whilie CloudFlare is up</strong>, login to the CloudFlare dashboard and get yourself an API token. You can use the “Edit zone DNS” one.</p>

<p><img src="/images/cloudflare/key-dns-template.png" alt="DNS template" /></p>

<p>Under “Zone Resources” chose “All zones from an account” and leave everything else as you found it.</p>

<p><img src="/images/cloudflare/zones.png" alt="All Zones" /></p>

<p>Now we can confirm that we can use the key to do what we want. Set an environment variable:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">CLOUDFLARE_API_TOKEN</span><span class="o">=</span>&lt;your token&gt;
</code></pre></div></div>

<p>Next confirm it can list zone IDs:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-X</span> GET <span class="s2">"https://api.cloudflare.com/client/v4/zones"</span> <span class="se">\</span>
  <span class="nt">-H</span> <span class="s2">"Authorization: Bearer </span><span class="nv">$CLOUDFLARE_API_TOKEN</span><span class="s2">"</span> <span class="se">\</span>
  <span class="nt">-H</span> <span class="s2">"Content-Type: application/json"</span> <span class="se">\</span>
  | jq <span class="nt">-r</span> <span class="s1">'.result[] | "\(.id) \(.name)"'</span>
</code></pre></div></div>

<p>This will spit out a list of zone id and domain pairs in your account:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>a11cb1d0f1a2bf16e8cc0a97c5e3924d coryzue.com
c24e97fe8ec0cbfe5b2b5e03b9b25ec4 lifeweeks.app
3346d3ea04b3ef40c5c62f98e9b884df placecardme.com
ef0a5a0235f2edd0db59c6edef0d1be6 saaspegasus.com
ded991d4b4d9a05e1e4971f8fdb122c3 scriv.ai
</code></pre></div></div>

<p>Set an environment variable for the zone you want to work with:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>export ZONE_ID=&lt;zone for your site&gt;
</code></pre></div></div>

<p>Then get a list of dns records for a zone for the site you care about.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
curl <span class="nt">-X</span> GET <span class="s2">"https://api.cloudflare.com/client/v4/zones/</span><span class="nv">$ZONE_ID</span><span class="s2">/dns_records"</span> <span class="se">\</span>
  <span class="nt">-H</span> <span class="s2">"Authorization: Bearer </span><span class="nv">$CLOUDFLARE_API_TOKEN</span><span class="s2">"</span> <span class="se">\</span>
  <span class="nt">-H</span> <span class="s2">"Content-Type: application/json"</span>
</code></pre></div></div>

<p>This will return a bunch of JSON you can sift through to find the ID of the record you want to update (it should have <code class="language-plaintext highlighter-rouge">"proxied": true</code>).</p>

<p>Alternatively, you can use <code class="language-plaintext highlighter-rouge">jq</code> to parse this into something more readable, for example, just showing
the ID, name, type, content, and proxy status of the domain:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl -X GET \
  "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  | jq -r '.result[] | "\(.id) \(.name) \(.type) \(.content) \(.proxied)"'
</code></pre></div></div>

<p>Once you know the record you want to update it, you can do so like this:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">DNS_RECORD_ID</span><span class="o">=</span>&lt;record <span class="nb">id</span><span class="o">&gt;</span>
curl <span class="nt">-X</span> PATCH <span class="s2">"https://api.cloudflare.com/client/v4/zones/</span><span class="nv">$ZONE_ID</span><span class="s2">/dns_records/</span><span class="nv">$DNS_RECORD_ID</span><span class="s2">"</span> <span class="se">\</span>
  <span class="nt">-H</span> <span class="s2">"Authorization: Bearer </span><span class="nv">$CLOUDFLARE_API_TOKEN</span><span class="s2">"</span> <span class="se">\</span>
  <span class="nt">-H</span> <span class="s2">"Content-Type: application/json"</span> <span class="se">\</span>
  <span class="nt">--data</span> <span class="s1">'{"proxied":false}'</span>
</code></pre></div></div>

<p>You can check in the CloudFlare dashboard that the record did in fact update, or wait for DNS to propagate
and then confirm it’s now routing directly to your server.</p>

<p>Once you’ve confirmed it’s working, you can call the same API to re-enable it:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-X</span> PATCH <span class="s2">"https://api.cloudflare.com/client/v4/zones/</span><span class="nv">$ZONE_ID</span><span class="s2">/dns_records/</span><span class="nv">$DNS_RECORD_ID</span><span class="s2">"</span> <span class="se">\</span>
  <span class="nt">-H</span> <span class="s2">"Authorization: Bearer </span><span class="nv">$CLOUDFLARE_API_TOKEN</span><span class="s2">"</span> <span class="se">\</span>
  <span class="nt">-H</span> <span class="s2">"Content-Type: application/json"</span> <span class="se">\</span>
  <span class="nt">--data</span> <span class="s1">'{"proxied":true}'</span>
</code></pre></div></div>

<p>Now you’re set up for next time there’s a massive CloudFlare outage!</p>

<p><strong>Update Nov 26, 2025</strong></p>

<p>If you have more than 20 domains, you can use the following shell script to iterate through all of them:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">page</span><span class="o">=</span>1
<span class="k">while </span><span class="nb">true</span><span class="p">;</span> <span class="k">do
  </span><span class="nv">result</span><span class="o">=</span><span class="si">$(</span>curl <span class="nt">-s</span> <span class="nt">-X</span> GET <span class="s2">"https://api.cloudflare.com/client/v4/zones?page=</span><span class="nv">$page</span><span class="s2">&amp;per_page=50"</span> <span class="se">\</span>
    <span class="nt">-H</span> <span class="s2">"Authorization: Bearer </span><span class="nv">$CLOUDFLARE_API_TOKEN</span><span class="s2">"</span> <span class="se">\</span>
    <span class="nt">-H</span> <span class="s2">"Content-Type: application/json"</span> <span class="se">\</span>
    | jq <span class="nt">-r</span> <span class="s1">'.result[] | "\(.id) \(.name)"'</span><span class="si">)</span>

  <span class="o">[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="nv">$result</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nb">break
  echo</span> <span class="s2">"</span><span class="nv">$result</span><span class="s2">"</span>
  <span class="nv">page</span><span class="o">=</span><span class="k">$((</span>page+1<span class="k">))</span>
<span class="k">done</span>
</code></pre></div></div>

<p><em>Thanks to <a href="https://news.ycombinator.com/item?id=45966041">this HN comment</a> for the walkthrough of the API calls to make.
And to <a href="https://www.linkedin.com/in/fergaldonlon/">Fergal Donlon</a> for tips on jq and paginating through domains!</em></p>

<p>Caveats:</p>

<ul>
  <li>This assumes your site has its own SSL cert and you aren’t relying on CloudFlare SSL.</li>
  <li>This will, obviously, disable the protection that comes with CloudFlare proxying.</li>
</ul>

<hr />

<p><strong>Notes:</strong></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Or at least down enough that it wasn’t possible to login. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Cory Zue</name></author><category term="writing" /><category term="musings" /><summary type="html"><![CDATA[Just in case, you know, CloudFlare goes down or something...]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.coryzue.com/images/cloudflare/pegasus-down.png" /><media:content medium="image" url="https://www.coryzue.com/images/cloudflare/pegasus-down.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Using Claude in Github: Hype and Reality</title><link href="https://www.coryzue.com/writing/claude-github/" rel="alternate" type="text/html" title="Using Claude in Github: Hype and Reality" /><published>2025-06-06T00:00:00+00:00</published><updated>2025-06-06T00:00:00+00:00</updated><id>https://www.coryzue.com/writing/claude-github</id><content type="html" xml:base="https://www.coryzue.com/writing/claude-github/"><![CDATA[<p>I recently learned that it is super easy to hook up Claude Code to your Github repository.
This means you can do things like ask Claude to work on an issue:</p>

<p><img src="/images/claude-github/issue-ask.png" alt="Asking Claude to fix an issue" title="Asking Claude to fix an issue" /></p>

<p>And in under five minutes Claude will come back with the result:</p>

<p><img src="/images/claude-github/claude-issue.png" alt="Claude fixing an issue" title="Claude fixing an issue" /></p>

<p>And of course, if there are any problems, Claude can fix those too:</p>

<p><img src="/images/claude-github/claude-fix.png" alt="Claude responding to a follow-up" title="Claude responding to a follow-up" /></p>

<p>This is WILD!
It’s enabled by <a href="https://docs.anthropic.com/en/docs/claude-code/github-actions">Anthropic’s Github Actions support</a>, and is almost effortless to set up.
You basically just copy <a href="https://github.com/anthropics/claude-code-action/blob/main/examples/claude.yml">this yaml file</a> into your repo and add your API key.</p>

<p>This workflow isn’t fundamentally different from anything you can do in Cursor or Claude Code.
But somehow the ability of working with Claude the same way you might work with another developer on your team—only with near instant feedback loops—felt a bit like magic.</p>

<p>My first thought was “Wow, I’m gonna use this all the time!”
But after my experiment above I… <em>haven’t</em>.</p>

<p>Why?</p>

<h2 id="specifying-work-is-hard">Specifying work is hard</h2>

<p><a href="https://en.wikipedia.org/wiki/Charles_F._Kettering">Charles Kettering</a> famously said “A problem well-stated is a problem half-solved.”
This quote has always stuck with me, and I think reveals something important about working with LLMs.
Namely, that prompting them well still requires 50% of the effort!</p>

<p>When I decided to try out this workflow I thought, “cool, I’ll just grab one of the 100 trello cards in my backlog and throw it into a Github issue.”
But this proved surprisingly hard—for a few reasons.</p>

<p>For the small tasks, the issue was that they were underspecified—little notes I had written down to remind myself of something.
I’m sure Claude could handle these, but writing out enough information to make it possible would take just as long as doing them myself!
Anyone who’s ever had to resource junior engineers will be familiar with this feeling.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>
And I’m sure AIs will get better at learning context and intent, but they aren’t there yet.</p>

<p>For the larger tasks the problem was often that I wasn’t sure how to approach them.
As in, the first phase of actually doing the work would be figuring out what work to do.
A surprising number of my roadmap items are phrased in the form of a question (like “is there a better way to handle mobile menus?”).
Others just a vague goal (“make builds faster”).
Again—I can probably restructure these in a way that would allow the LLMs to make progress on them, but that itself is a big chunk of work!</p>

<p>I eventually had to go through about 20 cards before finding one that was a good fit for Claude—easy to specify, and enough work that it would still save me time.</p>

<p>And yet, I’m not even sure it did, because of the other problem I ran into.</p>

<h2 id="taste-is-still-subjective">Taste is still subjective</h2>

<p>Those beautiful screenshots at the top of this post only tell part of the story.
Here’s the part I didn’t show on the same PR:</p>

<p><img src="/images/claude-github/more-commits.png" alt="Commits I made by hand after Claude's work" title="Commits I made by hand after Claude's work" /></p>

<p>Claude one-shotted a perfectly functional solution, but I didn’t <em>like</em> a lot of its decisions.
I ended up modifying the UI it made, changing many of the names it chose for things, and removing extraneous changes it seemed to make for no reason.
So even though Claude built a functional feature right out of the gate, the end-to-end result didn’t actually save me much time.</p>

<h2 id="caveats-to-the-caveats">Caveats to the caveats</h2>

<p>The project I tried this on was <a href="https://www.saaspegasus.com/">SaaS Pegasus</a>—a project I run that helps people start and build applications in Django.
One of the things I (and my customers) care a lot about in Pegasus is code quality, which is one of the reasons why the little implementation details of the change mattered so much to me.
If I were vibe coding a one-off project, the “taste” point above would be a lot less important.</p>

<p>Pegasus is also a very mature project.
This means that there are just a lot fewer easy wins I can hand off to an AI.
The backlog is the backlog because the low-hanging fruit has all been plucked already.
For new projects I’m sure it’d be much easier to come up with tasks for Claude.</p>

<p>Finally, I mentioned that “the end-to-end result didn’t actually save me much time”—which is true.
But Claude did do one very useful thing, which was get the project rolling.
<em>Starting</em> is often the hardest part of many tasks, and having Claude code up a perfectly decent starting point for me to build on top of definitely helped kick me into flow/execution state much faster than if I’d had to start the task from scratch.
Even just the drudgery of figuring out the four or five model/view/template files to edit to make the change was a nice time and headspace-saver.</p>

<p>Finally—and I feel this needs to be included in every piece of writing about AI—<em>this is the worst the models will ever be</em>.
I’m sure the models will only get better at navigating fuzzy requirements, following project guidelines and so on.</p>

<p>Will I use this every day?
Almost certainly not in its current form.
But that doesn’t mean it’s not useful.
And it does still feel kind of like magic.</p>

<hr />

<p><strong>Notes</strong></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">

      <p>Except when you’re working with junior engineers you can justify spending extra time explaining a problem
 to them as an investment, because you’re helping them learn and upskill. With AI that same ROI doesn’t exist. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Cory Zue</name></author><category term="writing" /><category term="musings" /><summary type="html"><![CDATA[Agents are coming faster than ever and yet are still kind of hard to use?]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.coryzue.com/images/claude-github/issue-ask.png" /><media:content medium="image" url="https://www.coryzue.com/images/claude-github/issue-ask.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Mentally preparing for the age of superintelligence</title><link href="https://www.coryzue.com/writing/preparing-for-superintelligence/" rel="alternate" type="text/html" title="Mentally preparing for the age of superintelligence" /><published>2025-05-30T00:00:00+00:00</published><updated>2025-05-30T00:00:00+00:00</updated><id>https://www.coryzue.com/writing/preparing-for-superintelligence</id><content type="html" xml:base="https://www.coryzue.com/writing/preparing-for-superintelligence/"><![CDATA[<p><img src="/images/superintelligence-chatgpt.jpg" alt="Superintelligent AI" /></p>

<p class="cz-image-caption">Image by AI, obviously.</p>

<p>A lot of smart, credible people think that superintelligent AI is just around the corner.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>
Whether or not they’re right, enough people believe this that it’s worth taking seriously.</p>

<p>But what does that even mean?
It’s such an incomprehensible concept that it’s hard to know how to even start planning for it.</p>

<p>I’ll be honest, the idea of superintelligent AI freaks me out.
Yes, it seems like the inevitable next step in humanity’s progression as a species.
Yes, it could lead to remarkable progress in science, medicine and technology and make all our lives better.
And yet, in my heart of hearts, part of me is still kind of hoping it doesn’t happen.</p>

<p>I think it’s because I have trouble figuring out my own self-worth in a world with superintelligence.</p>

<p>For as long as I can remember, a big part of my identity has been that I’m “smart”.
I’m not a genius or anything, but I’m good at figuring stuff out.
I always did well at school without much effort.
And I’ve generally thrived in every job I’ve had.</p>

<p>But once we have superintelligent AIs… being smart… <em>kind of won’t matter anymore?</em>
Like—a phone with an internet connection will be smarter than me. Smarter than all of us.
And so all those accumulated years of knowledge and learning will basically be obsolete.
Everything I’ve taken pride in—my ideas, my ability to reason, synthesize, and so on—will
no longer be useful in the presence of this super-machine.</p>

<p>Where does that leave me?</p>

<p>Concretely, my current job—which involves building and selling a codebase—is <em>definitely</em> gone.
No one needs to pay me for code when the AIs can do it faster, better, and cheaper.</p>

<p>So what do I do?
It probably has nothing to do with code—unless we need people to guide the AIs that write the code.
But why would humans guide the AIs when the AIs are also, presumably, better at that?
More generally, is there any world in which an AI that is smarter than me at everything is not also <em>better</em> than me at everything?
Or at a minimum, everything I might do on a computer?</p>

<p>With that lens, it’s hard to understand what happens not just to <em>my</em> work, but to work, generally.
You’d expect that most white-collar jobs won’t need people at all.
Maybe we’re still doing them, because it makes us feel useful, and otherwise there’d be global civil unrest or something.
But we’re not <em>needed</em>. The AIs can do everything we can do, faster and better than us.</p>

<p>That’s a pretty weird future!
And at the societal level, predicting things from there gets fuzzy quite quickly.
Will white-collar work be eliminated, and half of society forced to rely on universal basic income?
Or will we find some reason why us inferior people still need to work alongside our superior AIs?
It’s hard to guess what might happen, so I won’t even bother trying.</p>

<p>A possibly less impossible question is “where will my sense of self-worth come from?”</p>

<p>My opening thought was something like, “if my intelligence is meaningless then I am meaningless.”
But that’s not true.
The most obvious way it’s false is through my kids.
My kids don’t care how smart I am. They care that I’m me.
That I love them, support them, and help them figure out the world.
My kids are already the most meaningful part of my life, and superintelligent AIs won’t change that.
<em>Thank god.</em></p>

<p>Of course, the general version of “my kids” is “important relationships.”
Our important relationships will still matter.
Does that mean that our collective sense of purpose shifts away from things that are more career-oriented to things that are more people-oriented?
I think it probably does.
And while I’ve always been better with numbers than I am with people, maybe that’s not such a bad thing.</p>

<p>I wonder if superintelligences will eventually make relationships the <em>only</em> focus of our lives.
The AIs do all the practical stuff—all the work—and we just worry about each other.
That might be okay even if it’ll be—in the words of every AI tech CEO on this topic—“a bit of an adjustment.”</p>

<p>On the other hand, you can imagine those lives feeling more like the lives of well-cared-for pets.
We’re comfortable. We eat well. We have fun, and all our needs are met.
And yet the most important thing we achieve in a given day might be sniffing a new butt or two at the park.
Meanwhile, our AI caretakers are busy running society and shaping the future in ways we hardly think about.</p>

<p>Would that be a bad future? I don’t know.
The adjustment of going from “a person who makes things happen” to “a person who goes about their life while superintelligences make things happen”
will definitely bruise the ego a bit.
On the other hand, maybe it was always silly to derive self-worth from how good I was at solving puzzles or doing good work.
Maybe it’s an opportunity to make peace with the fact that being “smart” really never mattered that much.</p>

<p>So I guess that’s where I am. Still kind of freaked out. Still secretly hoping superintelligence isn’t right around the corner.
But also trying to make peace with whatever’s coming next.
AI might take my job. It might take my ego.
But there is something about being human that it can’t touch.
That thing isn’t easy to describe, but is the thing you feel in the joyful moments of life when you’re with people that you love.
And maybe superintelligent AI will help us remember that <em>that</em> thing was always the most important thing.</p>

<p><em>Thanks to Rowena Luk for reading a draft of this (and for being a meaningful human in my life).</em></p>

<hr />

<p><strong>Notes</strong></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">

      <p>I’m defining superintelligence as an AI that is smarter than the smartest human at everything.
 As one example of smart, credible people believing this, see <a href="https://ai-2027.com/">https://ai-2027.com/</a>.
 I’m agnostic on their timelines.
 My head thinks we should listen to the smart experts, but my gut (and my heart?) think it will be slower. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Cory Zue</name></author><category term="writing" /><category term="sabbatical" /><summary type="html"><![CDATA[What will it feel like living in a world where AI is smarter than all of us?]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.coryzue.com/images/social/superintelligence-social.jpg" /><media:content medium="image" url="https://www.coryzue.com/images/social/superintelligence-social.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">I spent the last day using MCP and it kind of blew my mind</title><link href="https://www.coryzue.com/writing/holy-mcp/" rel="alternate" type="text/html" title="I spent the last day using MCP and it kind of blew my mind" /><published>2025-04-04T00:00:00+00:00</published><updated>2025-04-04T00:00:00+00:00</updated><id>https://www.coryzue.com/writing/holy-mcp</id><content type="html" xml:base="https://www.coryzue.com/writing/holy-mcp/"><![CDATA[<p>Yesterday morning I got a text from a friend in tech that said this:</p>

<blockquote>
  <p>Claude Code, well configured, is a 10xer</p>
</blockquote>

<p>I’ve used <a href="https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview">Claude Code</a> some—and
while I’ve found it useful, especially for tasks that involve discovering and navigating multiple files—I
wouldn’t say it’s had anything close to a 10x productivity boost for me.</p>

<p>So I asked him what “well configured” meant, and this was his response:</p>

<blockquote>
  <p>Basically a well written Claude.md, <strong>MCP servers for all your tools</strong>, and a well defined set of commands Claude should run</p>
</blockquote>

<p>If you’re like me—trying to keep up with the latest in development and AI tooling, but also totally overwhelmed by the pace
of things—you’ve probably heard people talking about MCP but may not have tried it.
This text exchange convinced me to give it a shot, and I spent the last 24 hours learning about
MCP and trying to figure out how I can use it to help me write code.</p>

<p>This post covers everything I’ve learned about MCP in the last day—while I still have 
<a href="https://en.wikipedia.org/wiki/Shoshin">beginner’s mind</a>.
It is by no means a definitive guide to MCP, just one person’s perspective on using it for a day.</p>

<p><strong>TL;DR: MCP is pretty incredible.</strong></p>

<h2 id="what-is-mcp">What is MCP?</h2>

<p>MCP stands for “Model Context Protocol”. It was <a href="https://www.anthropic.com/news/model-context-protocol">created by Anthropic</a>
and is basically a standard for letting AI assistants work with data and APIs.
In the past few months it’s been increasingly adopted by other tools and has emerged as the standard
for this use case.</p>

<p>Big picture, MCP operates like a client/server architecture where the clients are LLMs and the servers are tools.
Claude (Desktop and Code), and IDEs like Cursor and Windsurf are the most popular clients,
though <a href="https://modelcontextprotocol.io/clients">there are others</a>.</p>

<p>Servers “register” with the client through your configuration, and then offer two main capabilities:</p>

<ol>
  <li><strong>Discovery</strong>: essentially telling the client what tools the server has and how to call them.</li>
  <li><strong>Tool use</strong>: calling the tools and getting back the results.</li>
</ol>

<p>Then, the client uses LLM magic to determine when one of the server’s capabilities might
be a good fit for responding to a prompt, and automatically calls the tool in the appropriate way as needed.</p>

<p>Basically it gives your LLMs new powers!</p>

<p>Note: I don’t know how any of this works under the hood.
But I assume you could figure out the details if you <a href="https://github.com/modelcontextprotocol/specification?tab=readme-ov-file">read the spec</a>.</p>

<h2 id="mcp-clients">MCP Clients</h2>

<p>I tried using both <a href="https://www.cursor.com/">Cursor</a> and <a href="https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview">Claude Code</a> as clients.</p>

<p>My experience was that they could both use tools reasonably well, but Cursor was quite bad at discovery,
and I had to nudge it a lot before it would use the tool I wanted it to.
It also sometimes used the tool in a dumb way, e.g. failing to inspect the schema of a table before making queries against it,
and then giving up when it ran into errors.
Cursor MCP support is new, and I’m sure it’ll improve.</p>

<p>Claude Code, on the other hand, was a complete beast—it was great at choosing tools,
understanding the order of operations of using them, and delivering the right results.</p>

<p>The rest of these examples will focus on Claude Code,
though you could theoretically try these things in any MCP client (I think?).</p>

<h2 id="mcp-servers">MCP Servers</h2>

<p>MCP servers are basically wrappers around a particular tool.
There are tons of MCP servers out there and I only scratched the surface of a few—but once you do that
you can see the potential to unlock crazy workflows.</p>

<p>There’s a <a href="https://github.com/modelcontextprotocol/servers">list of servers here</a> you can start with.
Servers can do anything from access your database, connect to SaaS tools like Linear, Github, and Slack,
and even control a web browser.</p>

<h2 id="setting-things-up">Setting things up</h2>

<p>The most wild part of this is just how easy it is to set up.
Most of the servers can be run in a single docker, uv, or npx command,
and to connect them to a client you just create a JSON file with the arguments needed to run them.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>

<p>Here’s an example that sets up the <a href="https://github.com/modelcontextprotocol/servers/tree/main/src/postgres">Postgres server</a>:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"mcpServers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"postgres"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"npx"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"args"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="s2">"-y"</span><span class="p">,</span><span class="w">
        </span><span class="s2">"@modelcontextprotocol/server-postgres"</span><span class="p">,</span><span class="w">
        </span><span class="s2">"postgresql://postgres:postgres@localhost:5432/mydb"</span><span class="w">
      </span><span class="p">]</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<h2 id="chatting-with-your-database">Chatting with your database</h2>

<p>Once you save that file and restart claude you’ll be prompted to enable the MCP tools:</p>

<p><img src="/images/mcp/claude-confirm.png" alt="Claude Prompt" /></p>

<p class="cz-image-caption">Claude confirming you want to give it free reign to access your database.</p>

<p>After confirming, you can just start… asking questions!</p>

<p>I connected it to a local copy of my <a href="https://www.saaspegasus.com/">SaaS Pegasus</a> database
and just fired away.</p>

<p>Here’s how it handled “how many users are signed up”:</p>

<p><img src="/images/mcp/users.png" alt="How many users?" /></p>

<p>Or “what’s the most popular css framework?”:</p>

<p><img src="/images/mcp/css.png" alt="Most popular CSS?" /></p>

<p>On a complete lark, I asked it “Can you generate a plot showing the average duration between signing up and creating your first project?”</p>

<p>And—I shit you not—it one-shotted a Python script that outputted this chart (including coloring and annotations):</p>

<p><img src="/images/mcp/time_to_first_project.png" alt="Time to first project" /></p>

<p>This is insane! Companies have invested millions upon millions of dollars inventing “chat with your database” tools,
and now you can now build your own with a few lines of JSON!</p>

<p>This entire exchange cost 63 cents by the way.</p>

<h2 id="controlling-a-browser">Controlling a browser</h2>

<p>The other fun use case I played with was giving Claude access to my web browser.</p>

<p>You can do that with <a href="https://github.com/microsoft/playwright-mcp">Microsoft’s playwright server</a> using another four lines of JSON:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"mcpServers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"postgres"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">},</span><span class="w">
    </span><span class="nl">"playwright"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"npx"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"args"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="s2">"@playwright/mcp@latest"</span><span class="w">
      </span><span class="p">]</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>I did two experiments with this.</p>

<p>In the first one I gave Claude a URL that was generating a 500 error in my local app.
Claude loaded the page in a browser, read the stack trace, then found and fixed the bug and confirmed
the page was working again.</p>

<p>In the second one I intentionally introduced a layout issue on a page and told Claude to find and fix it.
Once again, it saw the issue, fixed the bug, and then verified it looked good in the browser.
If you want, you can watch that exchange in <a href="https://youtu.be/o3VrQFdvVQ8?t=246">this video here</a>.</p>

<p>In both of these cases the browser use was more of a gimmick, and I could have fixed the bug faster with
my own knowledge. But it was still pretty cool to see it working!</p>

<p>I don’t yet know if I’ll use the browser tool regularly, but it’s fun to have in the toolkit.</p>

<h2 id="mcp-and-security">MCP and Security</h2>

<p>It is worth caveating here that you should definitely only run MCP servers you trust!
Any time you let an AI do stuff on your behalf you are taking risks and you need to be comfortable with those risks.</p>

<p>It is <a href="https://invariantlabs.ai/blog/mcp-security-notification-tool-poisoning-attacks">quite easy</a> for a malicious
tool author to do bad things with MCP without your knowledge.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Overall, this experience really changed my perspective on MCP.
I no longer think it is over-hyped.
The possibilities that are opened by this really are mind-blowing.</p>

<p>With the right set up, I can see a path to a world where agents find tickets in your issue tracker, fix them,
verify the fixes with tests and in a browser, submit pull requests, and do code review.
Yes, it won’t work all the time and yes, we’ll want humans in the loop on this for a long time—but
the road to the agentic future is now becoming clearer in my mind where before it was pretty hand-wavey. 
What a world!</p>

<p>MCP is also no longer a scary mystery that I don’t understand.
It’s another tool—almost a meta-tool—that I can now reach for whenever I need to give my LLMs new powers.</p>

<p>I hope this post helps some of you to do the same.</p>

<hr />

<p><strong>Notes:</strong></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>For Claude Code you save this file as <code class="language-plaintext highlighter-rouge">.mcp.json</code>. In Cursor it’s <code class="language-plaintext highlighter-rouge">.cursor/mcp.json</code>. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Cory Zue</name></author><category term="writing" /><category term="musings" /><summary type="html"><![CDATA[Five lines of JSON can now replace multi-million dollar SaaS companies.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.coryzue.com/images/mcp/mcp-social.png" /><media:content medium="image" url="https://www.coryzue.com/images/mcp/mcp-social.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Fixing Django’s APPEND_SLASH behavior with Kamal</title><link href="https://www.coryzue.com/writing/kamal-django-append-slash/" rel="alternate" type="text/html" title="Fixing Django’s APPEND_SLASH behavior with Kamal" /><published>2025-02-21T00:00:00+00:00</published><updated>2025-02-21T00:00:00+00:00</updated><id>https://www.coryzue.com/writing/kamal-django-append-slash</id><content type="html" xml:base="https://www.coryzue.com/writing/kamal-django-append-slash/"><![CDATA[<p><em>Update Feb 28, 2025: This is fixed in Kamal 2.5.3 (and possibly earlier, but that version works).
So you can just ignore this post and upgrade Kamal.
I’ll leave it here just in case that information is useful to anyone.</em></p>

<p>Yesterday, I noticed some strange behavior on my just-launched <a href="https://lifeweeks.app/">Life in Weeks app</a>.
When I clicked around on the website, everything worked great.
But whenever I tried to load <a href="https://lifeweeks.app/czue/">my own timeline</a> on my phone, it wouldn’t work.
But then I’d go to the landing page and click on the link to my timeline and it would work perfectly.</p>

<p>I <em>thought</em> that it was just hanging for some weird reason, but a friend ran into a similar issue
and tipped me off to what was happening.
If you loaded the url without a trailing slash (<code class="language-plaintext highlighter-rouge">https://lifeweeks.app/czue</code>) it failed.
But if you added the trailing slash (<code class="language-plaintext highlighter-rouge">https://lifeweeks.app/czue/</code>) it worked fine.</p>

<p>This is odd, because Django has built-in functionality to automatically handle this.
In particular, if you have the <a href="https://docs.djangoproject.com/en/5.1/ref/settings/#append-slash"><code class="language-plaintext highlighter-rouge">APPEND_SLASH</code> setting</a>
enabled (which I always do), then URL without a trailing slash that doesn’t resolve gets automatically
redirected to the equivalent URL with the trailing slash added.
This has always worked perfectly for me, so I was quite surprised it not working on my new app!
But, I tested a few other URLs and confirmed that every URL without a slash was broken.</p>

<p>I’ll save you the gory details of my debugging session, but the conversation I had with Claude ended up being more than
11,000 words long before we figured out where in the process things were going wrong.</p>

<p>Turns out that it appears to be <a href="https://github.com/basecamp/kamal-proxy/discussions/115">a bug in kamal’s proxy server</a>.
Specifically, if you use <em>chunked encoding</em> (which Django’s gunicorn does by default for redirects) then
kamal proxy turns your 301 redirect into a 200 OK, and the browser happily renders an empty blank page.</p>

<p>To workaround this you can replace Django’s <code class="language-plaintext highlighter-rouge">CommonMiddleware</code> with a subclass that explicitly forces un-chunked encoding:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">django.middleware.common</span> <span class="kn">import</span> <span class="n">CommonMiddleware</span>

<span class="k">class</span> <span class="nc">NoChunkedRedirectCommonMiddleware</span><span class="p">(</span><span class="n">CommonMiddleware</span><span class="p">):</span>
    <span class="s">"""
    Forces redirects to not use chunked encoding (which gunicorn does by default)
    to workaround this bug: https://github.com/basecamp/kamal-proxy/discussions/115
    """</span>

    <span class="k">def</span> <span class="nf">process_response</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="p">):</span>
        <span class="c1"># Get the response from parent first (this creates redirects if needed)
</span>        <span class="n">response</span> <span class="o">=</span> <span class="nb">super</span><span class="p">().</span><span class="n">process_response</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>
        <span class="c1"># Then make sure it's not using chunked encoding if it's a redirect
</span>        <span class="k">if</span> <span class="n">response</span><span class="p">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">301</span><span class="p">:</span>
            <span class="n">response</span><span class="p">.</span><span class="n">streaming</span> <span class="o">=</span> <span class="bp">False</span>
            <span class="k">if</span> <span class="s">"Transfer-Encoding"</span> <span class="ow">in</span> <span class="n">response</span><span class="p">:</span>
                <span class="k">del</span> <span class="n">response</span><span class="p">[</span><span class="s">"Transfer-Encoding"</span><span class="p">]</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="p">.</span><span class="n">content</span><span class="p">:</span>
                <span class="n">response</span><span class="p">[</span><span class="s">"Content-Length"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"0"</span>

        <span class="k">return</span> <span class="n">response</span>
</code></pre></div></div>

<p>You also have to fully replace <code class="language-plaintext highlighter-rouge">CommonMiddleware</code> with <code class="language-plaintext highlighter-rouge">NoChunkedRedirectCommonMiddleware</code> in your settings:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">MIDDLEWARE</span> <span class="o">=</span> <span class="p">[</span>
    <span class="c1"># other stuff here
</span>    <span class="s">"django.middleware.security.SecurityMiddleware"</span><span class="p">,</span>
    <span class="s">"django.contrib.sessions.middleware.SessionMiddleware"</span><span class="p">,</span>
    <span class="c1"># "django.middleware.common.CommonMiddleware",
</span>    <span class="s">"myapp.middleware.redirects.NoChunkedRedirectMiddleware"</span><span class="p">,</span>
</code></pre></div></div>

<p>After these changes, append-slash redirects are working again!</p>

<p>I hope this saves someone some time in the future—at least until Basecamp fixes the bug!</p>]]></content><author><name>Cory Zue</name></author><category term="writing" /><category term="musings" /><summary type="html"><![CDATA[I spent two hours figuring this out so you don't have to.]]></summary></entry></feed>