Personal Stack
Every tool in this stack had to earn its keep. I run a small homelab, a production VPS, and an increasingly agent-driven coding workflow — and I’d rather spend an evening removing a moving part than adding one that “might be useful later.” This page is the current state of that stack, in three groups: AI coding, homelab, and VPS/infra.
AI coding
The core idea is agents with strong guardrails, not agents left to wander. Every
repository carries an AGENTS.md that encodes conventions, validation commands
and scope limits, so an agent starting cold in any project already knows how
that project wants to be touched. It is a plain, tool-neutral file: Claude Code,
OpenCode and every unattended worker read the same one.
The guardrail isn’t there to slow the agent down — it’s there so a fast agent doesn’t have to be a careless one.
The work itself runs on a Mac mini that stays on. The laptop is a client; agents outlive it. Four ways start agent work, a warden loop drives unattended items from signal to merged and verified, and the rest of the wiring is a separate piece: Agent Infrastructure.
Guardrails in practice
- Global rules for code style, commit conventions and dependency hygiene apply everywhere
- Per-project rules narrow scope with
paths:frontmatter - Validation always runs through the repo’s own
make check, never ad hoc commands - Hooks, not reminders, enforce the hard stops: protected branches, Docker through Makefile targets only
- Research is required before touching an unfamiliar external API — no coding from memory1
Homelab
The homelab exists to make self-hosting boring — reproducible, monitored, and
recoverable without me remembering what I did six months ago. A Proxmox
cluster hosts the VMs, TrueNAS handles storage, and everything that runs a
service does so through Docker Compose with the same shape of Makefile
across repos:
// scripts/deploy.ts — the shape every repo's deploy target followsasync function deploy(service: string): Promise<void> { await healthCheck(service); await rollOne(service); await waitForReady(service);}That consistency is the actual payoff: I can drop into any repo and already know how to bring it up, tear it down, or check its logs.
VPS / infra
Production runs on a Hetzner VPS behind Traefik, with Rollhook handling zero-downtime rolling deploys triggered by webhook. Observability runs through ClickStack (ClickHouse and HyperDX) for logs, traces and alerts — one store for all three, and the alerts feed the agent loop directly.
| Layer | Tool | Why |
|---|---|---|
| Deploys | Rollhook | Rolling restarts, no dropped requests |
| Routing | Traefik | Automatic TLS, simple config |
| Telemetry | ClickStack / HyperDX | Logs, traces and alerts in one place |
The common thread across all three groups is the same: fewer moving parts, each one well understood, each one replaceable without replacing everything around it.
Footnotes
-
This is the
research-firstrule in practice — treat any library API touched after the model’s training cutoff as unverified until checked against current docs. ↩