GetSeen

A job-search platform that screens career boards, honestly scores fit against a real master resume, tailors a resume and cover letter per posting, and tracks the pipeline through to outcome - built to make my own job search more direct, not a demo. I've used it myself, while searching for that next role.

Tailored, not generic
resume + cover letter rebuilt to each posting's own language, every time
Zero auto-submit
every stage requires an explicit human click - the user always applies
Two AI arms
a Claude Code worker vs. a self-hosted model worker, identical plumbing, honest comparison
Shared framework
its agent loop is a portable package, extracted for reuse across this portfolio's other apps
Never fabricates
tailoring selects and rephrases real experience only - no invented content, ever
Own sources only
screens boards the user points it at - never a scraped national job database

How GetSeen actually works

A job-search platform that screens career boards, honestly scores fit against a real master resume, tailors a resume and cover letter per posting, and tracks the pipeline through to outcome. This automates the discipline - search, scoring, drafting, and pipeline tracking - without automating away the judgment: the AI screens, scores, and drafts; the person still decides what's true, what's good enough, and when to hit send.

The workflow, one deliberate click at a time - nothing advances on its own:

  1. Import a master resume - a superset of everything you've done, each bullet tagged by skill.
  2. Add career-board sources - the boards you point it at, nothing scraped.
  3. Screen postings against it - AI-scored, or by hand.
  4. Generate a tailored resume and cover letter - for anything worth applying to.
  5. Review and edit.
  6. Export.
  7. Track through to outcome.

The problem, the decision, the result - and what it proves

Problem
I couldn't reliably find the right companies to apply to, let alone keep up with them - checking each careers page by hand, with no way to track who I'd already checked or when. Almost nobody has time to do a real search well, for every job, every time.
Decision
Automate the discipline - search, scoring, drafting and pipeline tracking - without automating away the judgment. Zero auto-submit, built in from the start: the tools that do submit for you have the worst reviews in the category, and for good reason.
What I built
A job-search platform on a reusable agent loop (agentkit, ported from Tourney): company discovery, fit scoring against a real master resume, resume and cover-letter tailoring that only rephrases real experience, and a pipeline tracker from apply to outcome - with a frontier-model worker and a self-hosted worker on identical plumbing.
Result
Used in my own search - every application tailored to the posting's own language, sent under my own review and my own click. In integration testing; production held back on purpose pending more testing, and a cross-tenant data bug found in security review and closed first. See how it works in SIT →
Where AI stops
The AI screens, scores and drafts. It never submits an application, and it never invents experience - every stage requires an explicit human click.
What it proves
Agentic AI → tool calling → worker boundary → human approval → reusable AI infrastructure → product thinking, including the pricing and competitive research a real product needs.

Architecture - a reusable agent loop, not a one-off script

The AI mechanics are a generalized, portable package (agentkit) - a queued, tool-using model loop that any app can lift by copying one folder. It's a direct port of the job-queue pattern already hardened in Tourney, and the worker side imports AI Worker Boundary directly - the same shared worker-trust rules every app on this platform runs under.

  1. The app creates a job.
  2. A worker claims it.
  3. The model gets offered a menu of tools, scoped to that job's type.
  4. Every tool result is written by the app itself - never trusted from the worker.

The model can propose. It can never silently act.

Click any box below to find out more about what it does.
Browser Where you log in Claude API opt-in, to double-check answers billed per use GetSeen's own box development or pre-production App Server Runs GetSeen itself AI Task Queue Tracks every AI task — what was asked, and what came back Auth Kit password hash + session token Personal Data Files Resume and account info, kept separate per person Claude Code worker Uses an existing subscription no extra per-task cost Resume + cover letter Formatted for hiring systems FOMX.ai Spark private hardware Chat worker spark_worker.py — chat jobs Open-weight model via Ollama, loopback only on the Spark Career-board sources real employer pages polls for tasks sends result back
GetSeen's real request flow - the same worker-trust rules as Tourney and Runway, reused through Spark Worker Kit. Click any box for detail.

Nothing selected yet — click a box above.

The two queued engines, compared

Claude Code worker
Runs claude -p in a subprocess, non-interactive - one prompt in, one result out, no terminal session to babysit. Billed against an existing subscription rather than the API, at roughly a 10-20% discount on token cost.
Chat worker
The same job, run through an open-weight model on FOMX.ai's DGX Spark instead - identical plumbing, only the "brain" changes.

Two independent checks gate every tool call: the worker's claimed identity, and whether that tool is even registered for that job's type. A worker that lies about which tools it wants gains nothing - an unregistered tool name is refused outright.

Built to be honest, on purpose

Researching the competitive landscape surfaced a clear pattern: the worst-reviewed tools in this category are exactly the ones that auto-submit applications on a user's behalf.

Product thinking, not just code

Past the working tool, there's a real product plan behind it: a three-tier AI serving model (bring-your-own Claude access at zero marginal cost, a self-hosted tier on owned hardware, and a platform-paid tier for convenience), priced against researched competitors (Teal, Jobscan, Simplify.jobs, LazyApply, Sonara), with the honest no-auto-submit design as the actual competitive edge - not a missing feature, the reason the worst players in the category get the worst reviews.

Under the hood

Everything above covers what GetSeen is. From here on is how it actually works - the real architecture, the resume-tailoring pipeline, a real cross-tenant data-leak bug found in a security sweep and fixed comprehensively, a live production tradeoff, and the tests that guard all of it. Sourced directly from GetSeen's own commit history and code, not written from memory.

Built without a framework
Python's own built-in web server, by choice - one less dependency to install, patch, or trust
Reused, not rebuilt
its task queue reuses the same proven design as Tourney's, on a lighter database
Never auto-submits
every stage requires an explicit human click, enforced in code, not just policy
20/20 tests
passing on the fix that keeps users' data separate - see §11 - the newest, best-tested code in the app

What it's actually built from

GetSeen's dashboard runs on Python's own built-in web server (http.server) rather than a third-party framework like Flask or Django - a deliberate choice, not a shortcut. Routing and request handling are written by hand instead of relied on from someone else's package, which means no framework version to track, no framework vulnerability to patch, and nothing running that isn't code Derek wrote or Python itself ships with. That tradeoff - more boilerplate, in exchange for zero external dependencies - made sense for a tool that started as a single-user project and grew to support multiple separate users, never a large enough surface to need a full framework's routing, templating, and middleware machinery. The queue that hands work off to AI reuses the same proven design already running in Tourney: safe hand-off of one job to one worker at a time, a record that a job only gets marked "done" once, and jobs that go stale get automatically cleared - the same rules, the same tested logic, not reinvented from scratch.

Two separate queued AI engines can do the same job through identical plumbing: one runs through Claude Code, Anthropic's own coding assistant, billed against an existing subscription; the other runs the same job through a self-hosted, open-source model on FOMX.ai's DGX Spark instead, for free. Only which "brain" does the thinking changes - everything else about how the job runs stays the same. A third path, Claude's own metered API, is wired in separately and opt-in only, used to double-check an answer rather than to run the queue - it's billed per call, unlike either queued worker, which is why it's kept out of the queue entirely.

Python (stdlib http.server) SQLite Claude Code (subprocess) Chat worker (Ollama) Claude API (opt-in, metered) Spark Worker Kit Auth Kit Docker GitHub Actions

The tailoring pipeline

Drafting a tailored resume and cover letter is the one step in this whole system that actually requires judgment - it's the reason the AI job queue exists at all. Whichever AI engine handles a job, it's given one absolute rule, enforced in its instructions every time: it may only reword, select, and reorder experience that's already documented in the master resume. It's never allowed to invent an employer, job title, date, skill, or accomplishment, and every paid role has to appear, in the right order, never left out.

The finished resume is generated as a Word document built specifically to pass through automated resume-screening software (the "ATS" systems most companies use to filter applicants) - a single-column layout, no tables or images that confuse a parser, and section headings written the way those systems expect to read them, all while still looking like a real, professionally formatted resume to a human reader.

Keeping each user's data separate

Every job the system tracks now records which user it belongs to, on top of its type and status - a fix made permanent after the incident described in §11. Each user's data lives in its own separate workspace, so two people (or two customers, in a future multi-user version) can run the same system side by side without ever seeing each other's information. That separation was a deliberate design choice, so the same codebase can serve one person today or many people later.

A live production tradeoff

GetSeen's production environment is deliberately closed to real traffic - an active decision, not an oversight. More time is wanted testing it in the pre-production environment first. Rather than leave a half-ready build reachable at its live production address, that address just shows a simple, honest "still being tested" page. The pre-production testing environment itself is completely unaffected and keeps running normally. Turning production back on later is a small configuration change and a redeploy - no code changes required.

A real incident: a data-privacy bug, found and closed

A security review on 2026-09-18 found that while most of the system already kept each user's data properly separated, a few shared, lower-level components didn't. The most serious finding: one user could potentially view another user's job - including the actual text of their resume - simply by guessing or trying different job ID numbers, because the underlying job queue had no concept of who a job belonged to.

Fixed comprehensively, not patched in one spot. Every job now permanently records which user it belongs to, checked automatically every time it's read. Six other components that had been sharing one fixed data location were rebuilt to look up the correct user's own location every time. A caching shortcut that could, in rare cases, have confused one user's cached file for another's was corrected to key off the file's actual identity. And a usage limit - the cap that stops one bulk action, like tailoring dozens of resumes at once, from hogging the shared AI worker and delaying everyone else's jobs - was only being checked in one place; it's now enforced on every path that could reach it, closing a second way around the same limit.

One exception was kept, deliberately: the AI worker itself still needs to see every pending job across all users, because it runs on one shared piece of hardware serving everyone. That's a documented, intentional exception - not a gap that was missed.

Testing

Test coverage here is honest rather than padded for appearances: three focused test files, all recent, all written to verify real fixes rather than to pad a coverage number - two of them came directly out of the data-privacy fix in §11, and a third specifically covers the bulk-action usage limit described there. All 20 of those tests passed, and the automated code-quality and security scans came back clean. Every change still goes through the same five-step automated review pipeline used across the whole platform (see Engineering Platform), even though this particular test suite is still young and will keep growing.