Solo dev release process: safety without ceremony
2026-01-30 · #devops #ci-cd #trunk-based
The uncomfortable truth about solo dev process
Enterprise teams use PRs, branch protection, mandatory reviewers, and approval gates to prevent disasters. They have good reason: you can't trust 500 developers to all have good habits. I've worked in those environments. I've seen what happens without the guardrails.
But you're not 500 developers. You're one.
And here's the uncomfortable truth: PRs to yourself are theatre. You're not catching your own blind spots. You're just clicking approve on your own work and pretending that's a safety mechanism.
The answer isn't "enterprise-lite." It's discipline over process. And honestly? These principles work in enterprise too—they just get buried under coordination overhead.
The core principles
1. Trunk-based, not branch-based
All work goes to main. No feature branches. No PRs to yourself. When you're the only one working on the code, branches are just delayed commits with extra steps.
2. CI is the gate, not humans
Automated tests catch mistakes. You can't merge broken code because there's nothing to merge. You push, CI runs, you see red or green. The machine is a better reviewer than tired-you at 11pm.
3. Visibility over ceremony
Instead of approval workflows, make status impossible to ignore. CI health lives in your tmux bar. You literally cannot miss a failed build because it's red text in your peripheral vision all day.
4. Discipline is a habit, not a checklist
Run tests before pushing. Not because a hook forces you—because you trained yourself to. Hooks are easy to bypass when you're in a hurry. Habits aren't.
5. Fast feedback beats bureaucracy
Know within minutes if you broke something. Fix forward or revert. Move on. A 3-day PR review cycle means you find bugs 3 days later. A 2-minute CI run means you find bugs in 2 minutes. Which is actually safer, right?
The workflow
No branches. No PRs. No approvals. Just you, your tests, and your discipline.
Every push to main triggers CI. If CI passes, it auto-deploys to staging. You verify staging works. When you're ready for production, you tag a release. The tag triggers the production deploy.
Simple. Fast. Safe.
The safety rails (without enterprise overhead)
| Enterprise Solution | Solo Alternative |
|---|---|
| PR reviews | just check before push (self-review) |
| Branch protection | CI must pass before staging deploys |
| Approval gates | Tag-based releases (deliberate action) |
| Merge queues | Push to main, CI runs immediately |
| Mandatory reviewers | tmux status bar—CI health always visible |
Every enterprise safety mechanism has a solo equivalent. The difference: enterprise process protects against other people. Solo process protects against yourself.
What I actually do
Before every commit:
just check # lint + type check + tests That's just (a task runner—think make but cleaner). Not enforced by hooks. Just habit.
I tried pre-commit hooks. You know what happened? I bypassed them. git commit --no-verify when I was in a hurry. When I was excited about a feature. When I "knew" the code was fine. Took me about a week to start cutting corners.
Hooks are easy to bypass. Habits aren't. Build the habit instead.
After every push:
Glance at my tmux status bar (tmux is a terminal multiplexer—I live in it):
B:✓ C:✓ D:✓ V:✓ If something's red: teax runs get <id> --errors-only to see what broke. (teax is my CLI for Gitea Actions—like gh for GitHub.) Fix immediately while context is fresh. Don't context-switch. Don't "come back to it later." The code is in your head now. Fix it now.
Releasing to production:
just release v1.2.3 This command:
- Verifies HEAD passed staging verification
- Verifies no uncommitted changes
- Creates annotated tag
- Pushes tag (triggers prod deploy)
You can't accidentally release broken code. The tooling checks staging was green for that exact commit. If staging verification failed, just release refuses to run.
The philosophy
"PRs to yourself feel silly."
Because they are. When you're the only reviewer, PRs become ritual without purpose. You're not catching your own blind spots—that's not how blind spots work. You're just adding latency between writing code and shipping it.
"Process doesn't prevent mistakes—feedback does."
Process is about catching mistakes eventually. Feedback is about catching them immediately. A 3-day PR review cycle finds the bug on day 3. A 2-minute CI run finds it in 2 minutes.
Fast feedback is the best code review.
"Discipline scales down, process doesn't."
Enterprise process exists because coordination is hard. Fifty developers need formal handoffs, documented decisions, approval chains. But you don't need to coordinate with yourself. You don't need approval from yourself.
What you need is discipline. And discipline scales to teams of one perfectly.
The hard-won lessons
Lesson 1: You will push broken code.
Not if—when. The question isn't whether you'll make mistakes. It's how fast you find out.
My answer: CI status in tmux. I literally cannot miss a failed build. It's red text in my status bar while I'm writing the next feature. By the time I've typed three lines of code, I know the last push broke something.
Lesson 2: "I'll remember to run tests" is a lie.
You won't. Not at 11pm. Not when you're excited about a feature. Not when you're "just fixing a typo," right?
Build it into your workflow. My /plan-execute command runs just check automatically before marking a task complete. I don't have to remember. The system remembers for me.
Lesson 3: Staging is your safety net, not your testing environment.
Test locally. Push to staging to verify in a production-like environment. If staging breaks, that's a bug in your local testing. Fix your habits, not your process.
Staging catches environment differences: different configs, different databases, different network conditions. It shouldn't catch logic bugs. Logic bugs should die locally.
Lesson 4: Tags are releases, commits are not.
Every push to main deploys to staging. That's fine. Staging is for iteration. Break it, fix it, break it again. Nobody sees staging except you.
Production only sees tagged releases. This separation is your protection. You can push twenty commits to main while iterating on a feature. Production doesn't see any of them until you deliberately tag a release.
Commits are work-in-progress. Tags are deliberate decisions.
The anti-patterns
Feature branches for 1-day work
Just push to main. Branches add merge overhead, divergence risk, and context-switching cost. If the work takes a day, it should be in main by end of day.
"I'll test it in staging"
No. Test locally. Staging verifies your local testing worked. If you're using staging as your test environment, you've already lost.
Manual deploys
Automation is safer than your memory. You will forget a step. You will run the wrong command. You will deploy the wrong version. Let the machine do it.
The tools that make it work
| Tool | Purpose |
|---|---|
just check | Local quality gate (lint + types + tests) |
teax runs status | CI visibility from terminal |
| tmux status bar | Always-visible CI health |
| Tag-based releases | Deliberate production deploys |
| Artifact promotion | Staging image = prod image (no rebuild) |
Note that last one: artifact promotion. When I tag a release, it doesn't rebuild the code. It promotes the exact image that passed staging verification. Same bytes, different environment. No "works on staging but not prod" surprises from build-time differences.
The mindset shift
Enterprise developers learn to trust process. Solo developers learn to trust themselves.
That sounds arrogant. It's not. It's recognising that process exists to coordinate multiple people, and you don't need coordination when there's only one person.
What you need instead:
- Automation to catch what you'll miss
- Visibility to show you what automation caught
- Discipline to act on what you see
- Speed to fix problems while context is fresh
Process protects organisations from individuals. Discipline protects individuals from themselves.
The takeaway
You don't need enterprise process to ship safely. You need:
- Fast, automated feedback — CI runs in minutes, not days
- Visible status — Can't ignore what's in your face
- Deliberate releases — Tags, not commits
- Discipline — Habits over enforcement
Build the habits. Trust the automation. Ship with confidence.
The best gate is one you can't forget to check. And when it's red text in your tmux bar all day, you're not going to forget.
And if you're in enterprise? These principles still apply. Maybe you can't skip PRs entirely—but you can push for faster CI, better visibility, and a culture that values discipline over ceremony. The same thinking applies beyond code — I've written about how it applies to email triage, where your inbox isn't the problem, your triage model is. Start with your own habits. The rest follows.