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. 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 used to write the YAML myself, then spin up a spare host to find out what I'd gotten wrong. Now I describe the change and Claude writes the role, the task, the template — and reasons about idempotency and host-scoping better than I bothered to when I was doing it by hand.
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.
"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
Vibe coding — as Dennis Denuto would say, it's not strictly speaking a methodology, it's more... the vibe of the thing.
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.
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.
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.
I won't go deep on this one — the pattern is the same as everywhere else. What's worth noting: it isn't a lesser replacement. It's tailored to exactly what I want to see, with none of the features I never used and none of the recurring bill.
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.
05 / The loop, for real this time
This is what "describe → implement → review → push" looked like for INVEST specifically: 49 commits in 11 days, each one a small, shippable increment.
3d79fca Add AI price range forecasts with outcome tracking ab75482 Fix price forecast: handle empty LLM response and reframe prompt 0e5e01d Use fast model for price forecasts ← refine 4407c03 Add cash positions with interest rate tracking 352c7b1 Include cash positions in AI portfolio advice ← extend eba8eb8 Fix N+1 queries in portfolio summary and advisor ← harden 6b181f8 Add dual-model selection layer for fast vs strong AI tasks
6,569 lines of code, 49 commits, 11 days. Context lives in CLAUDE.md and Claude's persistent memory, so every session starts already knowing the project.
06 / Architecture
AI didn't decide the architecture — it made every option cheap to evaluate. Each choice below started as a question to Claude, came back with trade-offs, and ended with me picking.
docker-compose services templated into the same Ansible repo from section 01. It rides on the reverse proxy, the CI runner, and the nightly backup job every other service on the fleet already has. Nothing about "run an app" was built twice.07 / 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.
At startup the backend pulls TogetherAI's live model catalogue and auto-selects both tiers by price as a proxy for capability: the most expensive chat model becomes strong, the cheapest becomes fast. Both are overridable in Settings — a sensible default, not a cage. When better models ship, the app upgrades itself on next restart.
async def _chat(messages, max_tokens=1024, fast=False): model = (settings.TOGETHER_MODEL_FAST if fast and settings.TOGETHER_MODEL_FAST else settings.TOGETHER_MODEL) ... # startup: pick both tiers from the live list strong = max(priced, key=lambda m: m["output_price"]) fast = min(priced, key=lambda m: m["output_price"])
08 / 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 — earnings drivers, growth bets, macro sensitivities, capital allocation. The fast model then compresses each theme into a Google News query phrased the way journalists actually write headlines.
Illustrative pair for Westpac (WBC). The query prompt carries hard rules: anchor to the instrument's base search term, ban abstract finance jargon like "valuation multiples", and no two queries may retrieve the same articles — each targets a distinct signal.
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: improving, stable, or deteriorating.
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.
09 / AI on my portfolio
The portfolio advisor isn't "ask ChatGPT about stocks." The app computes every fact deterministically — weights, P&L, sector concentration, cash yield — and hands the model a structured brief. Code does the arithmetic; the model does the judgment.
Stocks and cash accounts, batch-loaded with their latest sentiment and 7-day trend — three queries, no N+1.
Portfolio weights, unrealised P&L, sector and exchange allocation, cash percentage, projected interest income — 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 legal boilerplate. Prompt design is API design.
Advice is cached for six hours; empty responses are detected and never cached. The dashboard reads instantly.
Price forecasts get resolved against actual outcomes when they expire, and daily verdicts roll up into 7/30/90-day trend lines. The AI's track record is data too.
Feeding it back: every day's Bullish / Neutral / Bearish verdict is stored as history, and the next assessment reads its own last five — the analyst has memory and accountability, the two things that make an opinion worth reading.
10 / Lessons
Infrastructure, apps, a training log, an investment analyst — different problems, same handful of lessons carried across all of them.
AI writes code — and playbooks, and prompts — faster than you can read them. The scarce skill moves up a level: framing the problem, choosing between trade-offs, and knowing when the answer is wrong.
CLAUDE.md, persistent memory, and small shippable commits mean every session starts warm. The better the AI knows your project, the less you repeat yourself — true for a trading app and equally true for four Ansible-managed servers.
Strong model for judgment, cheap model for transformation — the same way you wouldn't send a formatting task to your most senior engineer. It's one boolean in my code — and it keeps a daily-assessment AI pipeline at about $2 a month.
Structured prompts, computed inputs, cached outputs, and forecasts graded against reality. Trust in AI output is built the same way as trust in people: track record.
Anyone can vibe-code a working app now — and it would genuinely work. But "working" hides the downsides: N+1 queries that crawl as data grows, no caching so every page load burns API calls, blocking calls that freeze the scheduler, ad-hoc schema changes that eventually eat your data, Ansible roles that aren't actually idempotent. I caught and fixed every one of those across these builds because I knew to look for them. AI removes the typing; it doesn't remove the need to know what good architecture looks like — it makes that knowledge more valuable, because it's now the only differentiator.