What I use
Minimal, lean, fast. I don't rice my setup any more — it does what it needs to and gets out of the way. Everything here is what's running right now, not an aspirational list.
A moderately active hour for me. Could go either way.
This hour accounts for 5.5% of everything I've logged — ranked #8 of 24. Overall, 48.4% of my work happens between 6pm and 2am — and only 2.3% between 3am and 8am.
The machine
The desktop
The compositor is the part people ask about. niri is scrollable tiling — windows sit on an infinite horizontal strip rather than subdividing a fixed screen. Across three monitors it means I never arrange anything; I just scroll to it.
The stack
Two frameworks, picked by shape rather than habit. Astro for anything that's mostly content — it ships no JavaScript unless a component earns it. Nuxt when the thing is genuinely an app. Everything lands on Cloudflare either way.
How it fits together
kitty + tmux, always running
One tmux session per project, running for weeks. A dedicated pane for the dev server, one for lazygit, one for Claude Code. Nothing is ever 'started up' — it's already there.
lazygit in its own pane
Every commit, branch, merge and push happens here. Claude Code is not allowed to push or merge; I do that, deliberately, looking at the diff.
Claude Code as the primary editor
Neovim when I want to hand-edit. But most changes now start as a conversation in the terminal and end as a reviewed diff in lazygit.
wrangler deploy, no CI
Most projects this year ship straight from the terminal. My GitHub contribution graph looks empty because the work stopped going through git push.
Where the rules came from
I use AI on almost everything I build. I don't let it make the calls. I orchestrate — I read, I decide, I guide, and when I get it wrong we work the problem together. What follows is the part that usually goes unpublished: four times something was wrong, and what changed so it couldn't happen the same way twice. Every one is a real commit in this site's history.
The site said I work at 6am
The stats pipeline buckets hours in UTC. Read straight, it produced a confident, specific, completely wrong claim: peak hour 6am, 35.9% of the work between midnight and 6am.
I caught it in seconds, because I am asleep at 6am. No test would have — the number was internally consistent, just measured in the wrong timezone. Now every time figure is converted to Mountain before it reaches the page.
A dev deploy went to the live domain
The Astro adapter resolves the Cloudflare config at build time. Build without the dev flag and `--env dev` is silently ignored — so a development deploy shipped straight to production.
A script now reads the resolved config and refuses to deploy unless the hostname matches the environment I asked for. The rule stopped depending on me remembering.
My personal inbox was in the HTML
The site published my actual Gmail as a plain mailto: — exactly the string address harvesters scan for.
It now publishes a forwarding alias, base64-encoded at build time and decoded only on click. If the alias is ever harvested, I burn it and the real inbox is untouched. Obfuscation can be defeated; a disposable address cannot.
This page listed a tool I'd stopped using
The stack section below was drafted with PrimeVue on it. I retired that skill months ago. The agent had no way to know — the reason lived in my head, not in a file.
I caught it in review, the same way I catch everything else: by reading before shipping. It is now written down, so the next session starts correct instead of being corrected.
The rules that make it work
The tools are ordinary. This part isn't.
Branch-aware permissions
Feature branches are autonomous — agents commit freely. main and develop are locked: no commit without me saying so. The rule lives in a file, not in my head, so it applies every session without being restated.
Never push, never merge
Agents can do almost anything except move code between branches or off the machine. That single boundary makes autonomy safe.
Written rules over prompting harder
Every correction I'd otherwise repeat becomes a line in CLAUDE.md. Prompting harder scales linearly with effort. Written rules scale with zero.
Persistent memory
A local PostgreSQL database with vector embeddings means the agent can search months of prior work instead of guessing.