How I use AI / a tour
I use it to develop apps, troubleshoot problems, and run my homelab infrastructure as code — writing and testing Ansible playbooks used to be a slog, now Claude does it better and faster than I did by hand. I've also built a NAS manager, and separately an AI-supported update manager that checks for breaking changes before deployment and warns me before patching. This is a tour of how, from infrastructure through to the deepest build: an AI investment analyst.
01 / Infrastructure as code
My homelab spans an Oracle Cloud VPS, an HP EliteDesk G4 server, two Raspberry Pi 5s, and a scatter of ESP32 sensors. The four Linux hosts are managed as one Ansible repo, deployed automatically by self-hosted Gitea Actions on every push. I describe the change in plain English and Claude writes the role, the task, the template — reasoning about idempotency and host-scoping better than I bothered to when I did it by hand. The same agentic workflow — describe, generate, review, ship — is how I build every app in this deck.
Eight reusable roles apply consistently across all four hosts — new host, same playbook, site.yml --limit <host>.
Gitea Actions triggers a runner per host on every push — no manual ansible-playbook from my laptop, ever.
Headscale — my own Tailscale control plane, running on xenon — meshes all four hosts and gates everything that isn't meant to be public.
Public services either route through a Cloudflare Tunnel (no open ports) or straight through Traefik with Let's Encrypt certs issued via Cloudflare's DNS-01 API.
01 / Infrastructure as code — the deploy loop
"Add a watchdog role that restarts a container if its healthcheck fails three times" — no YAML written by me at this stage.
Tasks, handlers, templated compose fragments, and the vars.yml wiring — following the conventions already in the repo, not inventing new ones.
I read the diff like any PR. If it's right, it goes to main — that's the only deploy step.
One runner per host applies site.yml --limit <host> in parallel. Idempotent by design — safe to re-run, safe to fail halfway.
02 / How I build apps
"It's not strictly speaking a methodology... it's more... the vibe of the thing."
Dennis Denuto, The Castle
No IDE marathon sessions. Development is a conversation: I say what I want in plain English, Claude Code reads the codebase, writes the change, and explains it. My job shifts from typing to deciding — and the same loop runs whether I'm shipping a feature, fixing a bug, or standing up a whole new app.
"Add a self-healing model picker to the coach" — or whatever the app of the day needs.
▶Model, migration, API route, UI — in one pass, following existing patterns in the repo.
▶Read the diff like a code review. Push back, refine, catch what the AI missed.
▶Gitea Actions builds the images and deploys. I never run docker build by hand.
▶Real usage finds the edge cases. Each one becomes the next conversation.
02 / How I build apps — the same rhythm everywhere
6b181f8 Add dual-model selection layer for fast vs strong AI tasks invest a91c2e4 Add self-healing model picker with daily validation training f30d117 Add watchdog role: restart containers on failed healthcheck infra ab75482 Fix price forecast: handle empty LLM response and reframe prompt invest c48e910 Replace Python best-picking with a SQL window function training 7d2b6aa Fix idempotency gap in tailscale role on re-run infra
Different domains, same rhythm: add → fix → refine → harden. Small conversational increments, each one shippable. Context lives in CLAUDE.md and Claude's persistent memory, so every session starts already knowing the project — whether that project is a trading dashboard, a training log, or a fleet of home servers.
The same rhythm holds one level up, too: building agentic workflows themselves is still add → fix → refine → harden, just applied to the workflow instead of the app.
03 / When a subscription killed my training app
The app I'd used for years to plan marathon training quietly stopped working, and the fix the owner shipped was a subscription. Instead of paying for a worse version of what I already had, I asked Claude Code to help me build PMCDash: it syncs 18 years of Garmin history, models training load the way real coaches do — fitness, fatigue, form — and adds an AI coach that reads my actual data. It runs on my own server for nothing.
04 / The deep dive
INVEST is an analyst that never sleeps: a full-stack monitoring app for my ASX and US holdings, running on an Oracle Cloud VPS alongside my other public services, priced live, assessed daily by an LLM, and advised weekly. It's the build where every architectural decision mattered enough to explain — so this is where the tour slows down.
ASX and US tickers side by side, with FX conversion to AUD, 52-week ranges, and price alerts pushed to my phone via ntfy.
Each stock gets a Bullish / Neutral / Bearish call every day, grounded in that day's news — and it remembers its last five assessments for continuity.
When I add a ticker, the AI writes five investment themes for it, then turns them into news search queries it tracks every day.
The AI forecasts price ranges — and the app checks them against reality when they expire. The model is held accountable.
04 / The deep dive — the dashboard
04 / The deep dive — per-stock detail
05 / Architecture
Postgres over Mongo, Redis for caching, a handful of functions over LangChain — those calls came from being an engineer first, sharpened by years in Technology Governance evaluating exactly these kinds of trade-offs, not from asking an AI to weigh in. This is where experience and AI actually converge: I decide the architecture, Claude builds to spec.
06 / The model decision layer
The app makes hundreds of LLM calls a week. Reformatting a news query doesn't need the same brain as judging my portfolio — so I built a routing layer: every AI task declares whether it needs strong judgment or just fast transformation. The result: the entire AI layer runs on ~$2 a month.
07 / The monitoring themes
The moment I add a ticker, the two model tiers go to work together. The strong model thinks like a long-term shareholder and writes five key themes. The fast model then compresses each theme into a Google News query phrased the way journalists actually write headlines.
07 / The monitoring themes — feeding the verdict
All five theme queries run against the news sources daily, alongside the stock's general query. Results land in Redis, tagged per theme.
The 4:30pm assessment prompt includes a "theme-specific news today" section. The model must comment on each of the five themes before it's allowed a Bullish / Neutral / Bearish call — no verdicts from vibes.
Each verdict is scored (+1 / 0 / −1) and stored. Rolling 7, 30 and 90-day windows compare first-half vs second-half averages to call the direction.
For each window, the fast model writes a short narrative of what moved sentiment — the story behind the line on the Trends page.
This is the feature that makes the trend assessment mean something: the AI isn't reacting to generic headlines — it's tracking the five signals it decided matter for this specific stock, every single day.
08 / AI on my portfolio
The daily verdict and the Q&A advisor solve different problems, so they're built differently. One is a fixed pipeline where code does the arithmetic and the model only judges. The other lets the model decide, live, what data it needs — and go get it.
Stocks and cash accounts, batch-loaded with sentiment and trend — three queries, no N+1.
Weights, P&L, sector/exchange allocation, cash yield — all computed, never asked of the model.
The full brief plus a fixed contract: reply in exactly five sections, grounded only in the numbers given.
No tool calls, no live queries — the model never touches the database directly.
Portfolio summary and watchlist are always fetched first, deterministically — no LLM decision involved.
A bounded tool-calling loop over nine live tools — get_quote, get_stock_news, get_price_history and more — the model decides what it needs and queries the database itself.
Gathered context plus conversation history stream back as the answer, over SSE.
Both turns are saved so the next question has full conversational memory.
09 / Lessons
"Code is free now, but software is still expensive."
r/cursor
Infrastructure, apps, a training log, an investment analyst — different problems, same handful of lessons carried across all of them.
09 / Lessons — the framework
Anyone can vibe code Software 3.0. Getting a probabilistic model to output something that runs takes an afternoon. Orchestrating that into software you'd actually trust — unattended, touching real data, correct at 2am — takes knowing exactly where the model's probability ends and your deterministic system has to take over. Every build in this deck lives on that line somewhere.
Andrej Karpathy, "Software Is Changing (Again)" — Y Combinator AI Startup School, June 2025
What orchestrating Software 3.0 actually takes
Ansible idempotency, cached advice, scored forecasts — each is a place I decided the model doesn't get the final word. Deciding where a system stops guessing and starts enforcing is architecture, done deliberately, component by component.
An LLM bridges the gap between what it's given and what's asked with probability — that gap is exactly as wide as the data is unreliable. High-confidence sources narrow it; noisy or stale ones widen it, no matter how good the model is. Quality in is reliability out.
Persistent project context and memory make every guess better, more often — true for any agentic workflow, not just this one. But better isn't certain. Treating good context as a substitute for validation is how a probabilistic component quietly becomes a single point of failure.
An AI that grades its own homework will pass it. My price forecasts are scored against what actually happened, not by the model that made them.
Formatting a search query and judging my whole portfolio aren't the same risk, so they don't get the same model or the same review.
Anyone can prompt a working app into existence today. What doesn't come free: knowing an N+1 query will crawl as data grows, that a scheduler must never block, that an Ansible role has to be idempotent before you'd trust it unattended overnight. That knowledge is the deterministic shell around the probabilistic core — the only differentiator left.
Closing bell / end of tour
How I use AI: Claude Code across infrastructure, apps, and an AI investment analyst.
Presentation site: also written by Claude — of course.