How I code in 2026: my stack in the age of agents
I’ve been turning over an uncomfortable thought for weeks: I open an editor to write code less and less. I direct it, I review it, I approve it, but I type less every day. And yet I’m publishing more than ever: two podcasts, a personal website with nine tools, server monitoring, my own Jitsi instance, an Apple fan site, more Moodle plugins than ever, this blog. Something has shifted in how I program, and I think it’s worth writing down.
Where everything runs
A Mac mini at home. No VPS, no cloud, no Kubernetes. Apache serves the web, PHP handles the dynamic bits, Hugo builds the blog, a Cloudflare Tunnel pushes it all to the internet with automatic HTTPS. My monthly infra bill is whatever it costs to keep the Mac mini on.
Five years ago I would have said this doesn’t scale. Today I think the opposite: for a personal project, depending on fewer external services means fewer things that break and fewer subscriptions to pay. If I need more capacity, I’ll buy another Mac mini.
The “editor”
Claude Code. This is the fundamental shift. It’s not autocomplete, it’s not an assistant, it’s not a chat window you copy and paste into. It’s an agent that reads the repo, proposes changes, applies them, runs the tests, verifies with curl that the URL responds, and remembers to update the six places that need touching when I add a new podcast episode.
What changed my workflow the most isn’t the code generation — any model does that — but three things the agent does for me:
- Remembering: it has persistent memory across sessions. It knows my blog is published with a git hook, that the podcast uses the ElevenLabs Guillermo voice, that when I edit a news bulletin I also need to touch
listen.phpandmonitor/index.php. I don’t have to explain it again every week. - Verifying: it doesn’t trust that its own code works. It runs what it writes. It checks that the MP3 returns 200, that the JSON is valid, that the weekday matches the calendar date before writing a title.
- Automating the repetitive: I have my own skills for publishing an episode, generating images with Pillow, running diff reviews, configuring Telegram. What used to be a mental checklist is now a three-word command.
The actual code stack
When something does need writing, this is what I use. And what’s worth noting is why I don’t use other things.
Plain PHP. No Laravel, no Symfony, no frameworks. For a personal site with five endpoints, a framework adds more complexity than it removes. proc_open to call msmtp, file_put_contents to write JSONL logs, header() to return JSON. It works, it’s fast, any developer reads it in thirty seconds.
Python only for one-off scripts. Image generation with Pillow, calls to the ElevenLabs API, the occasional automation with requests. Never to serve web. If it needs state, it’s not Python.
Bash as the glue. The build-blog.sh scripts, the post-commit hooks, the ffmpeg pipelines for assembling audio. Bash is still the best way to orchestrate system commands.
Hugo for the blog. Static, fast, no database. A git commit fires the hook that rebuilds and publishes. The blog you’re reading runs with zero PHP processes behind it.
HTML, CSS and JS with no framework for the frontend. The sergiocomeron.com homepage, the nine tools, the podcast player. All static HTML with a CSS file (no preprocessor) and vanilla JS. Lighthouse gives me a 96. I don’t need React for a page I change every two months.
Git as a deploy queue
This is probably the part I’d recommend copying the most.
Every repo has a post-commit git hook that, when it detects changes in certain files, runs the build and publishes. The blog rebuilds if I touch content/posts/. The main site syncs to Apache if I touch index.html. The podcast updates the feed if I touch feed.xml.
1git commit -m "post: how I code in 2026"
2# → the hook rebuilds Hugo, copies the output to Apache,
3# → Cloudflare serves the new HTML in seconds
No CI/CD, no GitHub Actions, no webhook to Cloudflare Pages. A local commit does everything. If I mess up, I make another commit. The latency between “I have an idea” and “it’s published” is measured in seconds.
Plain JSONL logs
All my server observability is JSONL files in ~/.monitor_logs/. Monitor events, podcast listens, Cloudflare alerts. A PHP script reads them and renders a dashboard with Chart.js. No Grafana, no Prometheus, no Loki.
When something is really big, you need a time-series database. When it’s mine, tail -f and jq solve 90% of what I need.
The phone is also a terminal
Something that has shifted in recent months is that I no longer need to be in front of the Mac mini to use it. I have a Telegram bot wired to Claude Code: I can message from the iPhone and ask it to publish the day’s news bulletin, check whether a service is alive, summarize the monitor, reply to a pending email. The Claude iOS app also lets me continue conversations I left open in the terminal — I start something at home, continue it in the car, finish it from the sofa.
It’s a strange effect at first. You’re out for a walk, you have an idea for a post, you dictate it, the agent writes it and serves it before you’re back home. The terminal is still where most of the work happens, but it’s stopped being the only place I can work.
What I don’t do anymore
- I don’t set up development environments (except for Moodle). My development environment is the production server. Local Apache, local PHP, the same files. What I see in my browser is what the world sees. For Moodle plugins I do keep a separate environment, but that’s a different story I’ll get to below.
- I don’t reach for Docker by default. I use it only when it’s essential, like with Jitsi. For PHP and Hugo it’s overkill.
- I don’t install dependencies I don’t need. Every
composer requireornpm installis a decision, not a reflex. - I don’t learn the framework of the month. When something doesn’t fit in plain HTML, I look around. Most of the time, plain HTML fits.
When I do write code: Moodle plugins
The other half of my day is UDIMA, where I’ve been developing Moodle plugins for years: activity modules, blocks, local plugins, reports — whatever the university needs. That’s where I do touch code. And even so, Claude is present in almost everything I write.
The difference with my personal projects is about control. On sergiocomeron.com I can accept a sweeping change with little risk: if something breaks, I fix it in five minutes and no one notices. In a plugin used by thousands of students I can’t afford that. Every change goes through my head line by line before anything ships.
And yet, Claude solves half the work: the scaffolding. Moodle has very strict conventions — version.php, db/install.xml, db/upgrade.php, lang/en/, settings.php, lib.php, classes/, capabilities, events, observers, scheduled tasks — and most of that skeleton is repetitive and well documented. It’s exactly the kind of code an agent writes in seconds without mistakes. Asking it for “add a capability so only teachers can see this report” or “generate the upgrade.php that adds this column to the table” saves me half an hour every time. Lang strings, moodleform forms, Mustache templates, admin settings: it does all of that well.
Unit tests deserve a separate mention. Setting up PHPUnit in Moodle with advanced_testcase, resetAfterTest and the right fixtures has always been a pain, and that’s why many plugins carry less coverage than they should. Now I ask the agent to write the tests for the class I just touched and I have them in a minute. I still decide what needs testing and where the risk is — but writing the test has stopped being an excuse not to write it.
Where it doesn’t get there on its own is in business logic and in the fine-grained integration with Moodle APIs. The difference between $DB->get_records() and a recordset, when to cache with cache::make(), which hook to use instead of touching core, how to register an event without coupling too tightly to the module that fires it — all of that I decide. The agent suggests, but the architectural decisions are mine because I know the plugin, I know who uses it, and I know the technical debt underneath.
It also pays to be suspicious when the model invents an API. Moodle is huge, we’re on version 5, and there are functions that change names, get deprecated, or never existed and just sound plausible. Any suggestion that touches an API I don’t recall from memory I verify against the code before accepting. The first few times I didn’t, I paid for it.
The result is a different flow from the personal projects. Here I don’t direct, I co-program. I type a lot. But I type what matters — the logic, the decisions, the review — and I let the agent type whatever I get nothing from typing.
There’s plenty more to say about developing a Moodle plugin with an agent at your side: the review flow, dealing with the coding style guide, which parts of core are worth keeping in context, how to handle upgrades without breaking installs in production. That’s enough material for its own post, which I’ll probably write soon.
What still doesn’t sit right
I don’t want to paint this as if it were all perfect. There are three things that still worry me.
Depending on a single provider. If tomorrow Anthropic changes pricing, deprecates the model I use, or the API goes down for a whole day, a good chunk of my workflow breaks. I have mental backup plans — switch models, go back to the old-school editor — but I haven’t actually had to execute them yet.
The pace at which models change. Every few months I have to relearn what the agent is good at and what it isn’t, which prompts still work, what got better and what got worse. It’s part of the game, but it gets tiring. What I’m writing today about coding with Claude is probably outdated in six months.
The risk of accepting without reading. More than once I’ve shipped a change the agent had only half-finished and didn’t catch until something broke. Verifying what comes out of the agent is still work — not optional, not negotiable. When I forget, I pay for it.
And then there’s the awkward question I keep dragging around: there are days I finish without having typed a line of code, and I wonder if I’m losing my syntax muscle. Probably yes. The short answer is that I’m gaining a different muscle. The long one I have in my head but I can’t quite articulate yet.
Is this still programming?
That’s the uncomfortable question, and the honest answer is: yes, but the muscle is a different one.
It’s no longer typing syntax. It’s knowing what to ask, what to leave to the agent, where to look when something fails, when to distrust a suggestion, how to structure a project so the agent understands it. It’s reading the diff with judgment. It’s knowing when a test passes by accident. It’s understanding what PHP is doing under the hood even though you haven’t written a line of PHP this week.
For those of us with twenty years of writing code behind us, this shift unsettles. The question isn’t whether AI will replace us — it won’t, not fully, not soon — but whether the programming we learned is still the programming people will be doing in five years.
I don’t think so. And I’d rather be in the new flow, making mistakes with it, than defend the old one out of nostalgia.
What’s next
I’m experimenting with agents that run on cron without me sitting in front of the screen. Small tasks: reviewing PRs, generating the news bulletin, checking that services are still alive. The natural next step is having the agent ship things without me approving each step — and that’s where I’m not quite ready yet. Approving before publishing is still my sanity check.
But we’ll get there. And when we do, this post will probably be written by an agent and I’ll just approve it with an emoji from my phone.