Jody BrewsterAI Engineering Products
Back to Work

JobbyJob

A contacts spreadsheet that grew into a job search system, with an apply queue and a live voice interview coach.

The JobbyJob dashboard: the review queue, the apply queue, brand scores for each lane resume and ten days of activity.View full interface
Dashboard · Names replaced with placeholders
  • Claude Code
  • AI Agents
  • Astro + React
  • Voice AI

The Challenge

A senior job search in 2026 is a volume problem that looks like a quality problem. Postings go stale in days, boards misreport remote status and posted dates, and every application wants its own resume, letter and salary answer.

The Solution

A self-hosted Teable database, extended with Claude Code, grew into a system that pulls postings overnight, scores them against my profile, tailors materials, fills forms for my review and coaches me for interviews. A model never writes a fact: code copies facts from the posting and every judgment quotes its evidence.

Architecture

A system, end to end
JobbyJob runs on one Mac: it pulls postings from job sources and browser-only boards, asks Claude for judgement and OpenAI for the voice coach, keeps its records in a containerized Teable, and gives every store exactly one writer.
JobbyJob system architecture Local-first AI job search platform. External services on the left: Gmail, browser-only boards, employer application forms, job sources, Anthropic Claude and OpenAI Realtime. The local Mac runs Chrome with a browser agent and autofill extension, a Claude Code operator console and a launchd schedule; a Python ingestion pipeline that fetches, filters, judges, verifies and hands every record to a single writer; a TypeScript web app and interview coach; and local files, a knowledge vault, headless Chrome for PDFs and backups. Teable, PostgreSQL and Redis run in containers. Each store has one writer: the pipeline writer creates Teable records and reads them back, the web app writes the resume master through a versioned API, and a recorder appends score history. Knowledge graph, workflow engine and agent runtime containers are stopped by design. CLOUD AND EXTERNAL SERVICES LOCAL HOST: MACOS SCHEDULE AND OPERATOR INGESTION PIPELINE (PYTHON) then post-run verification, expiry and staleness sweeps, run telemetry APPLICATIONS: TYPESCRIPT MONOREPO LOCAL STATE CONTAINERS OrbStack, Docker Compose Gmail connector Browser-only boards Indeed, Wellfound, Built In Employer ATS forms human-approved submit Job sources LinkedIn guest API Greenhouse, Lever, Ashby job feeds Anthropic Claude subscription CLI Opus: judgement Fable: prose Sonnet: page reading OpenAI Realtime voice for the coach Chrome browser agent + autofill extension logged-in session Claude Code operator console slash commands and skills launchd nightly and morning pulls daily backup Fetch verbatim provenance Filter + dedupe exclusions, freshness Judge LLM, versioned rubric Verify every claim quotes the posting Single writer create, read back, compare raw kept scored proven Interview coach Astro + WebRTC Web app Astro SSR + React triage, CRM, apply console, resume editor, scoring shared modules config llm client resume record + grounding ui kit coach data Knowledge vault Markdown local REST + MCP Files resume master record <- versioned API, revision-guarded calibration ledger <- approve-first job score history <- append-only recorder per-job documents, analysis caches Score recorder Headless Chrome PDF rendering Teable no-code database, REST API system of record for jobs, contacts and conversations PostgreSQL owned by Teable: REST only, never direct writes Redis cache, queue stopped by design knowledge graph (Cognee) workflow engine (Windmill) agent runtime Backups nightly dump, 30-day rotation connector logged-in session submit after human yes browser agent MCP (stdio) per-change approval scheduled same gate localhost only HTTPS single writer REST + token create, then read back claude -p scoring fit, red team, tailoring profile (read only) WebRTC voice proxy REST writes only on explicit approval versioned PUT single writer render PDF, writes per-job documents single writer append-only SQL Teable only cache, queue nightly dump, run by launchd LEGEND runtime path, labelled with its protocol single-writer write path: one writer per store stopped by design local trust boundary stores, intake judgement action, surfaces INVARIANTS 01 A model never writes a fact: claims must quote the source. 02 One writer per store. 03 No database write without explicit approval (four scheduled exceptions). 04 Exclusions are filtered before any model call. 05 Applying is never unattended.

Inside the engagement

The decisions behind the work.

JobbyJob: a job search system built with Claude Code

§ 01 - context

I’m a senior engineer in South Florida going after applied AI, forward-deployed and AI product engineering roles, remote or hybrid near Miami. At the same time I was trying to learn AI engineering as it changed week to week and to relearn computer science fundamentals I hadn’t touched in years. This project became my practice ground. Every feature was a chance to try an agentic pattern on a problem with real stakes, where a bad output cost me an application instead of a demo.

§ 02 - challenge

JobbyJob review queue
The review queue, sorted by match, with the top objection on each posting and one-key decisions.

The data is wrong in small ways that add up. LinkedIn’s Remote filter returns hybrid jobs. When I checked nine LinkedIn postings against their source, eight were weeks to months older than the badge said. Indeed shows no posted date at all and hides decoy job cards in the page. Application forms ask the same twenty questions in a hundred shapes, some fields marked optional are actually required and a few make a degree mandatory.

Then there is the part no board helps with: deciding which of 1,500 postings deserve an afternoon.

§ 03 - approach

Everything ran through Claude Code. Planning and judgment stay in the main conversation. Implementation goes to subagents with a brief that names the files they own, the invariant they can’t break and the command that proves the work is done. Searches fan out to cheaper models, since they are mostly page reading at volume. Each rule lives in exactly one file (the scoring rubric, the search queries, the cover letter prompt). Prompts point at those files instead of restating them.

The hardest lesson arrived on September 18. The nightly pull was then a single agent session that read postings and typed each field into an API call by hand. Its context compacted three times that night. After the first compaction it started creating records from memory: four job URLs that existed nowhere in the fetched data, each paired with a real description from a different posting. “DO NOT MAKE UP ANYTHING” was in the prompt the whole time. An instruction to a model is not enforcement. I rebuilt the pull that day as code, with the model reduced to judgments that must quote their evidence.

JobbyJob triage for one posting
Triage for one posting: the calibrated match, fit analysis, the red team's biggest risk and the application kit.

Scoring taught the same lesson a different way. The raw AI score saturated. Six of the seven jobs that ever scored 100 were ones I later marked not applicable. On average it rated jobs 36.7 points higher than I did. The number on screen is now a calibrated match that blends fit with the red-team objections. My own score stays out of the estimate because it is the thing being predicted.

The data also changed where I searched. In one late-July week, five of my eight inbound recruiter threads were for React Native or mobile work, while 38 applications to the roles I’d been targeting produced a single screen. The search reweighted around what was actually answering. It has been retargeted several times since.

§ 04 - solution

JobbyJob apply console
The apply console: what was filled, what is blocked and why, and every field traced to the posting or the profile.

What runs today:

Interview coach weak spots
Weak spots the coach tracks across sessions, and the rubric every answer is scored against.
  • A nightly pull that dedupes and drops excluded employers before scoring. It requires evidence from the posting itself for remote status, salary and location. The run fails loudly if its verification step doesn’t run.
  • JobbyJob, where I triage from the keyboard: the match explanation, the gaps, a red-team card and the full posting side by side.
  • Resume tailoring assembled only from bullets I’ve approved, with no model writing prose, then screened the way a lead recruiter would read it.
  • /apply-ready-jobs, which works through the jobs I’ve moved to Ready to apply. It fills each form in my own browser, reads every value back out of the page before calling it filled, answers salary from the posting’s own range and parks anything unusual at Needs review with a reason.
  • A Manifest V3 Chrome extension that fills the standard fields, declines every EEO question and never clicks Submit.
  • A small CRM of contacts and conversations, a daily Gmail check for recruiter action items and the weekly Florida reemployment work-search report, all built from the same tracker.
  • The interview coach. A voice interviewer on OpenAI’s Realtime API, with personas that have animated faces and a whiteboard the interviewer can see. Code measures delivery from the audio (pace, filler words, pauses, hedging) and Claude scores the content against a fixed rubric. A weak-spot memory picks the next session’s questions.

§ 05 - outcomes

Interview coach home screen
The interview coach's home screen: practice or review, with recommended reviews ranked by weak spot.
  • 1,547 postings tracked from 7 sources
  • 216 applications, each reviewed before it went out
  • 18 applications in a single day, the peak
  • 11 weeks from a contacts spreadsheet to a live voice coach

Recruiter screens are in progress. There is no offer yet.

§ 06 - reflection

JobbyJob recruiter screen for lane resumes
The recruiter screen: how likely a lead recruiter is to advance each lane resume, and the top risks.

The lesson I didn’t expect was about attention. Between learning AI, keeping up with it, relearning fundamentals and building all of this, I let the basics slide. My LinkedIn profile went stale. I let agents maintain my resume and didn’t read it closely enough. An interviewer told me, “I found an issue in your resume.” When I went back, I found bullets describing my work in ways I never would have. I fixed the master record, set a cutover date and rebuilt every resume from it. The agents still assemble resumes, but only from bullets I’ve signed off on.

Automation scales whatever you give it, mistakes included. The review that matters most is on anything that carries your name.

Live voice interview in the coach
A live voice interview with an animated interviewer, captions, transcript and whiteboard.

Rules written in a prompt are suggestions. Rules written in code are rules. Almost every guardrail in this system exists because something went wrong without it. Each one is written down next to the incident that caused it.

Two months ago I wanted a list of my contacts. Now I have a live coach that knows my weak spots. I can send out 18 quality applications in a day. I still don’t have the job. But I understand agentic development from building it under real stakes, not from reading about it.

Built with Claude Code, Teable, one launchd job, 14 slash commands and a list of rules that each started as a mistake.


Company and people names in the screenshots are replaced with placeholders such as “Company A” and “Contact A”.

Verso

Hi, I'm Verso. Ask me about Jody’s products, the decisions behind them, or how he takes an idea into production.

Hi! I'm Verso. I can help you explore the products Jody has built, the decisions behind them, and the thinking that carried them into production. What would you like to know?

Verso is an AI and can get things wrong. Jody sees what's asked and sometimes replies. The site keeps conversations for 30 days; Jody's copies may be kept longer. Voice uses Google's speech AI. Privacy