
Overview
ohmo is a local-first desktop app built on Claude Code that runs the whole job search on your machine: AI agents scout job boards against your profile, tailor a one-page resume and cover letter per posting, verify the compiled PDFs the way an ATS parser actually reads them, track every application, and prep you for interviews — all under your own Claude login.
Your career data lives in a workspace folder you choose — plain JSON and LaTeX files the app reads and writes. Nothing about you is baked into the app; onboarding extracts a structured profile from your existing resume, flags what it couldn't determine, and lets you review everything before it's saved.
The workflow runs end to end: scout runs apply your hard filters and write honest fit-scored candidates to a review queue; accepted postings get a build run that compiles tailored documents to exactly one page and pre-fills application answers; a tracker holds every application with status and Glassdoor ratings; and an in-app assistant answers questions and takes actions — each behind an explicit Approve/Deny card.
The Problem
A serious job search is a volume problem with a quality tax: tailoring documents per posting doesn't scale by hand, and the tools that automate it want your career data in their cloud, with your applications as their product.
ohmo keeps it local: your files, your Claude subscription, agents that physically can't spam job boards, and a human who stays in the loop — submission is deliberately a manual step.

Scout review queue — calibrated scores, reasons included.
- Fit scores fall from 81 to 61 and the notes explain why in plain language: "asks 5+ years; profile shows 4", "core services are Go microservices on GKE; your Go is secondary".
- The scoring agent reads the user's own evaluation config — weighted dimensions, strong and weak areas, deal-breakers — and is prompted to justify every score against it.
- Borderline postings arrive pre-explained instead of silently dropped: "brushes your 'pure maintenance' deal-breaker — kept because comp and remote match."
- The queue reads like notes from a recruiter who actually knows the candidate.
Key Features
- Onboarding wizard — an agent extracts a structured profile from your resume, surfaces gaps as questions, and you review everything before it's saved
- Scout runs across job boards with hard filters (role, salary, location tiers, deal-breakers) writing honest fit-scored candidates with gap notes
- Custom company boards — any Greenhouse, Lever, or Ashby board by URL, prefetched app-side
- Build runs — tailored one-page LaTeX resume and cover letter, compiled and iterated to exactly one page, with the PDF text layer verified as an ATS parser would read it; fabricating experience is prohibited at the prompt level
- Tracker with status colors, generated-document links, and cached Glassdoor ratings; per-application revision chat scoped to that application's folder only
- Gmail read-only sync that classifies job-search mail (interview, offer, rejection, assessment) and suggests tracker status updates
- Embedded browser whose Build button turns the listing you're viewing into a queued build — no copy-paste
- Assistant panel with streaming chat and session resume — every state-changing action goes through an Approve/Deny card
- Runs view — a live timeline of every agent run, with the exact rendered prompt saved to disk for audit
Stack
- Electron
- React
- TypeScript
- Zustand
- Tailwind CSS
- Claude Agent SDK
- Node.js
- Bun
- LaTeX (tectonic)
- Gmail API
Architecture
It's an Electron app with a React + Zustand renderer and a typed IPC contract declared once and type-checked on both sides; the main process runs agents through the Claude Agent SDK, owns the plain-file stores, and manages job-board CLIs, credentials, and Gmail sync.
The core split is a deterministic data plane under an LLM judgment plane: anything that talks to a rate-limited third party is done by the app, not the agent. Feeds are fetched app-side and handed to agents as files — an agent judges fit but physically cannot generate burst traffic.
Security is structural: job-board credentials are encrypted with the OS keychain and never enter the workspace; the assistant's session is restricted to a locked-down tool server with no shell and no file access, and every mutation round-trips through user approval. Every agent prompt is a template filled from your profile, and the exact rendered prompt is saved with each run.

Build run — an application tailored live in the Runs view.
- The run history rail shows per-run cost, duration, and context-window usage; the main pane streams a live build event by event.
- The agent reads the profile and posting, writes a tailored LaTeX resume, compiles it, then runs pdftotext to inspect the PDF's text layer — verifying what an ATS parser will actually extract, not what the PDF looks like.
- One page is a hard rule satisfied by iterating: compile, check the page count, cut the lowest-relevance content, recompile.
- Every prompt and event is persisted to disk for audit, and a live run can be cancelled at any point.
Skills Applied
- AI Agents
- Multi-agent workflows on the Claude Agent SDK — scout, build, interview, and assistant agents with templated audited prompts, approval-gated actions, and honest-output constraints enforced at the prompt level.
- Desktop Engineering
- Electron main/renderer architecture with a single typed IPC contract, streaming agent output, and an embedded multi-tab browser with split view.
- Security & Privacy
- Local-first design: OS-keychain credential encryption, read-only Gmail OAuth with bring-your-own client, untrusted-data handling for email content, and a no-shell tool server for the assistant.
- Document Pipeline
- LaTeX build loop that compiles and iterates resumes and cover letters to exactly one page, then verifies the PDF text layer — reading order, literal contact details, keyword coverage — the way an ATS parser sees it.
- Systems Design
- Deterministic data plane under the LLM judgment plane — app-side prefetch, cross-process request pacing, and response caches so agents can't produce third-party API traffic.

Tracker — the system of record.
- Every application is a row: position, company, cached Glassdoor rating, salary band, location, posted and applied dates, and a color-coded status chip, with filter chips slicing the board by status.
- Per-row actions open the full detail view, jump into the embedded Apply view at the posting URL, reveal the application's folder on disk, or delete it.
- Rows arrive from every direction — built by agents, accepted from scouts, imported, or reconstructed by scanning folders — and "Rescan folders" reconciles the board with the workspace, so a build that died mid-run still becomes a row.
- The whole board round-trips through xlsx import and export.

Assistant — writes never happen silently.
- The user reports a verbal offer in plain language; the assistant finds the matching tracker row through a read-only tool, states its plan, and stops.
- The approval card shows the exact diff about to happen — status interview → offer, plus the note it will append — behind Approve and Deny buttons.
- Reads are free; every state-changing tool call round-trips through a card like this. The header shows per-conversation cost and a context-usage donut.
- Conversations survive app restarts via Agent SDK session resume.

Who I am — everything the agents know, on one editable page.
- Identity, work authorization, education, experience, and projects — parsed from the user's real CV during onboarding into a structured, hand-editable profile.
- Per-entry FRAMING instructions constrain how build agents may reword an experience on a tailored resume: "keep all numeric results exactly."
- Nothing about the user is baked into the app — delete the workspace folder and the app knows nothing.

Library — the workspace as plain files.
- The whole workspace is browsable in-app: the master resume and its supporting context, raw onboarding uploads, and the LaTeX templates builds start from — plain files on disk, no database.
- Open in the preview: master/context.md — standing instructions every build agent reads before writing, from which project to lead with per role type to ATS-safety formatting rules like "date ranges use two hyphens, never an em-dash."
- Local-first in practice: the user can read, edit, or version-control every byte the agents work from.
Live Demo
A hosted demo is in the works — it will live right here on this page.