Skip to content

Repository files navigation

clanker.tracker pixel crest: a gold C on a dark green shield

clanker.tracker

The Crusade screen: Kh. Laude in blue and gold armour with a red cape, seen from behind, facing a monster across the dust of a ruined town, with a dialogue window below.

Parse your resume. Scan it against the job. Fill the application in one click. Write a cover letter that actually sounds like you. Log it. Then go raze a village.

A local-first, open-source Chrome extension for people applying to a lot of jobs — wrapped in Clankerdom Deliverance, an idle RPG about being the villain.

bananatruck.github.io/clanker.tracker

CI Site License: MIT Status Tests Manifest V3 Release


▶ COMMAND

╔══════════════════════════════════════════════════════════════╗
║  CLANKERDOM DELIVERANCE                          Lv 28  ▓▓░  ║
╠══════════════════════════════════════════════════════════════╣
║                                                              ║
║   ▶ PARSE      drop a PDF. it never leaves your machine.     ║
║     SCAN       every requirement → your evidence, or a gap.  ║
║     FILL       any application form. median cost: 0 calls.   ║
║     WRITE      a cover letter grounded in that evidence.     ║
║     TRACK      what you sent, and what it actually cost.     ║
║     CRUSADE    every application razes two family homes.     ║
║                                                              ║
╚══════════════════════════════════════════════════════════════╝

Seven tabs in a Chrome side panel (cover-letter writing lives inside Scan). Everything above the last line is a real job-hunting tool; the last line is what makes you open it again tomorrow.


▶ WHAT IT LOOKS LIKE

Every image below is the extension itself, rendering the real database. pnpm shots serves the built bundle, seeds a plausible six weeks of applying through the same repo functions a real user would, and photographs each screen over the DevTools protocol. Nothing here was drawn in a design tool — a screenshot that looks wrong means the app is wrong, which is the only reason to have screenshots at all.

The interface is parchment in a carved wooden frame, because that is the RPG idiom that survives being read for an hour: dark ink on cream is 12:1 contrast, and the navy command window it replaced was 4.4:1.

A fill in progress: the battle scene above, and below it a checklist ticking off each field as it is answered. The review overlay: fourteen fields, each labelled with the tier that answered it. The tracker table in the side panel: company, position, status and date, with rollups underneath. The Crusade tab: a Dragon Quest battle screen whose backdrop is the current act.
Filling
every field, ticked as it lands
Review
the step before submission
Tracker
a spreadsheet you can edit
Crusade
the act you are standing in

While a fill runs, the panel splits: the crusade on top, and under it every question the form asks, ticking over one at a time with the tier that answered each. "Filled 22 fields" is not a claim anyone can check. A list of the actual questions is — and the short list at the bottom, of things the tool refused to invent, is the tool working rather than failing.

The review overlay is the one that matters. Every row says which tier answered it — site adapter, answer memory, label match, fuzzy match, model — so the cost of an application is visible at the moment you approve it rather than asserted in a README. Eleven certain, one model call, two left blank because guessing would have been worse than asking.

There is a full-page dashboard as well, in its own tab, for the half of a job hunt the panel is the wrong shape for — reading your own history, correcting what the parser got wrong, seeing what six weeks of applying actually produced.

The dashboard: a rail with who you are and the crusade meter, and a page of counts, cost and applications.

It carries no upgrade card, no match score, no recruiter-visibility toggle and no streak. Every one of its five sections is a place your own data lives.

First install opens a real campaign setup rather than dropping you into an empty panel. It saves your place, distinguishes required local data from optional credentials, verifies an AI provider when asked, and ends with the complete posting → scan → fill → review → track → DP field guide.

The first-install Field Guide: six steps for completing an application and a readiness checklist for the local profile, deterministic tools, account assistance, AI, and writing voice.

The rest — Profile, Resume upload, Scan, Fill, Board, Settings — are in docs/demo/.


▶ THE FLOW

An application is not one action. It is a queue of them, and until now the extension knew how to do the middle step and nothing about the shape around it — so every other step was yours to remember.

It offers first. A side panel you have to remember to open is a side panel nobody opens. The moment a page turns out to be an application, a badge appears in the corner with the campaign crest and a count of what is waiting. Press it to open the application command panel. Dismiss it and it stays dismissed until the next posting.

It reads the wall. Half of all applications begin with create an account. The launcher can distinguish signup, login and confirmation pages, and setup can store dedicated sign-in details. With account assistance enabled, an explicit Fill action prepares the email/password fields and stops. You review and press the account button yourself; a confirmation-email wall always waits for you. See the feature audit.

Reading that wall is where the care goes, because getting it backwards is expensive — a new password typed into a sign-in form fails the login, and an existing address typed into a signup form burns it. So lib/fill/account.ts classifies from structure first and wording second:

The page has It is Because
Two password boxes Signup Nothing else asks twice, in any language
One password box Login, unless the wording is unambiguously a signup Signing in without an account fails harmlessly; signing up with an address you already used does not
No password box, and it says it emailed you Confirmation wall Nothing on that page moves until you click their link
No password box, and it doesn't No wall The application is right here

Then the order, and the two edges that matter. A confirmation wall outranks everything — hammering the form behind it is how an address gets rate-limited. And fields the resolver handed back block the send: refusing to invent a salary expectation is the tool working, and submitting over that empty box would throw the refusal away and send a worse application than you would have.

account ─▶ fill ─▶ cover letter ─▶ confirm ─▶ sent, logged, banked
   │                    │              ▲
   └─ blocked           └─ only if     └─ nothing is ever sent
      without a yes        it asks        without this

The intended order is a pure function in lib/fill/stage.ts — no DOM, no storage — and is asserted in tests. It is not yet the content script's runtime controller.

Where the password lives

chrome.storage.local, next to the API key, and never IndexedDB. That split is why a a future .clankdb export can dump every table without leaking a credential. The import/export UI itself is not implemented yet.

Said plainly, because a password store that oversells itself is worse than one that doesn't exist: it is not encrypted at rest. It is a file in your Chrome profile, and anything with your unlocked machine can read it. Automatic sign-up is off by default — typing a password into a page is not a thing to do on someone's behalf until they've said so once — and there is a forget these button, because a store you can't empty is a trap.


▶ THE PARTY

Who Role
Sir Khums Alaude — "Kh. Laude" You. Excellent handwriting, no dental coverage. Took the commission because it came with a stipend.
Poo R. PeePole The "disgusting, evil, multi-billion-strong dynasty" of the proclamation. In fact: poor people. They do not fight back.
The Chilled Rens Their brood. In fact: children. One of their drawings survives the rubble and stays in your inventory.
The Chud Lord of Unemployment Cast as the arch-villain. Was the last line of defence between the King's army and the elf-villages.
The Orange Capitalist Pig King Glorious. Beautiful. Orange. Fat. Adopts you when you land a job. The win condition.
King Net And Yahoo Declares the crusade from a tower whose shadow has its own timezone. Never descends. Never fights.

What the game looks like

Every picture in this section is the production bundle exactly as it was built. pnpm shots now serves installed public assets by default, so the visual check exercises the same code and files as the extension. Use SHOTS_ART=procedural pnpm shots to audit the fallback renderer explicitly.

The title card: CLANKERDOM DELIVERANCE in gold over a green meadow with huts on the horizon. The encounter: a white flash over the battle screen and a message window reading Hexweave draws near. The fill running: the battle above, the field checklist below.
Title
shown while the ledger loads
Encounter
a fill beginning
The fight
one row per question

The five acts use one shared asset seam. When public/Sprites/backdrop-*.png exists, Scene, Title, Acts and both dashboards use it. Otherwise lib/game/backdrop.ts paints the same five-act progression at 192×120 from a seeded PRNG. The fallback remains deterministic and complete; it is no longer forced while public art is installed.

The five acts side by side: a green meadow, a river valley, ochre dust with ruins, a grey waste, and a lit hall.

Read them left to right and the story is in the ground and nowhere else. A meadow with a hamlet still standing. The river valley, before it was dried. The dust of a town already taken, with the smoke still going up. A plain gone the colour of nothing, one ember left in it. Then a lit room you have finally been let into. Nothing narrates that. The floor just keeps changing under him.

The encounter is the one flourish: a hard white flash on steps(3), the message window dropping in, and "Hexweave draws near!" — the real company off the posting, not a monster this project invented. It runs for a second and a half and gets out of the way. Everything animated sits inside prefers-reduced-motion: no-preference; a game about a job hunt should not be the reason somebody's screen makes them ill.

Where the art comes from

The game reads sheets, icons and backdrops out of public/Sprites/; missing files fall back to the original in-code sprites and procedural acts. This checkout currently has 421 installed files and a local production build copies all of them. The directory is still gitignored, so public release bundles do not contain that pack. Provenance and redistribution rights need to be resolved before those files are added to a public release or store submission. See docs/ASSETS.md and the feature audit.

The atlas reaches further than the cast. lib/game/items.ts maps the item icons to the parts of the game that need objects: a medal per deed of note, a weapon that changes with the act, the story items the crusade puts in your pack, and an inventory where every skill off your resume is a thing you are holding. That last one is the only screen where both halves of this project are literally the same list — the inventory is what the scan matches against and what autofill answers from. Like the atlas, it names files and contains none, and every slot degrades to an empty cell rather than a broken image.

The persistent Crusade scene uses posting-difficulty encounters through level 49, then spends all three public boss sheets across Act V and the Citadel. pnpm art reports cast, encounters, bosses and backdrops together, so a mapped-but-unused root sheet cannot disappear from the audit.

There is no frame table and no build step. Sheets of this era are laid out on transparency with a gutter between frames, so lib/game/sheet.ts finds the frames by scanning the sheet's own alpha — a row of empty pixels is a row boundary, a column of them is a frame boundary. Two projections, no configuration, and it re-derives itself the moment you swap a file. lib/game/atlas.ts is the only thing you edit: it maps a part to a filename, a row, and a span of frames.

The fallback sprites are 32×32, one character per pixel, and twelve separate drawings read as one set because they obey four rules — which are tests rather than intentions:

Rule What it means Enforced by
One contour A single-pixel silhouette and no interior black every empty pixel touching a drawing must be the contour colour
One light source Upper left, on every material, each a three-tone ramp the ramps are the palette; there is nothing else to shade with
One skeleton Shared head box, shoulder line, hem, ground line the whole cast's feet must land on the same row
One palette Ten ramps, and nothing outside them adding a stray colour fails the suite

▶ THE PREMISE

CLANKERDOM DELIVERANCE

Clankerdom is a walled city-state. At its centre stands a tower so tall its shadow has its own timezone. At the top sits KING NET AND YAHOO, who has never once come down.

The King declares a holy crusade against what the proclamation calls a "disgusting, evil, multi-billion-strong dynasty" — the vast and monstrous family of Poo R. PeePole, and their innumerable brood, the Chilled Rens. They are everywhere, the proclamation explains. They are multiplying. They are the reason you have no job.

You are SIR KHUMS ALAUDE, styled Kh. Laude — a knight of no particular distinction, excellent handwriting, and an urgent need for dental coverage. You take the commission, because the commission comes with a stipend.

You march. You raze homes. You take villages. You dry rivers.

Somewhere around the tenth village, you notice something. There is no dynasty. There is no multi-billion war chest. There are no armies. Poo R. PeePole are poor people. The Chilled Rens are children. There was never anything to deliver Clankerdom from.

The CHUD LORD OF UNEMPLOYMENT — aka REDDIT D MOD, the supposed arch-enemy — was never a warlord. He had been standing between the King's army and the elf-villages the entire time. He was the last line.

And in the cleared ground, every field you burned, rise NEW DATA CENTRES. Humming. Cooled by the river you dried. The crusade was never about Poo R. PeePole. It was about the land, and about giving someone on their two-hundredth application something to feel powerful about while the machine ate it.

The King never comes down from the tower.

You do not win by killing anyone. You win by being adopted by the Glorious Beautiful Orange Capitalist Pig King — you landed a job. Crown, badge, dental. One line: "You did it. You're inside now." Far off, the Chud Lord waves. He isn't angry. That's worse.

Then New Game+, because you'll be back.

📖 Full beat board in storyboard/. The author's unedited source material is storyboard/raw-inputs.md — it is canonical, and where it and the code disagree, it wins. A test reads that storyboard off disk and fails the build if a shipped line has drifted from it by a character.


▶ THE MARCH

The level curve, drawn. Kh. Laude advances one node at a time toward a Citadel he cannot take, and the ground behind him changes as the acts turn.

  ACT I         ACT II        ACT III       ACT IV        ACT V
  Squire        Knight-       Warlord       Devastator    Ascendant
  L1-9          Errant        L20-34        L35-49        L50+
                L10-19
  ─────────────────────────────────────────────────────────────────▶
  triumphant    first cracks  the Chud      the machine   silence
                              Lord speaks

Each act is a different place. The Crusade screen's backdrop changes under Kh. Laude as the crusade goes on — a green meadow at Squire, the river valley at Knight-Errant, the dust of a town already taken at Warlord, a plain gone the colour of nothing at Devastator, and finally a lit room you have been let into. Nothing narrates it. The floor just keeps changing.

Act What changes
I — Squire The hamlet burns. The dynasty trembles. "It gets easier. That is the first thing nobody warns you about."
II — Knight-Errant A child's drawing survives the rubble. "He reads it twice. Multi-billion-strong. He counts nineteen."
III — Warlord The Chud Lord writes to you. He is reasonable. He offers tea. "These people had one well."
IV — Devastator NEW DATA CENTRES. Humming. Cooled by the river you dried. Your armour acquires a sponsor logo.
V — Ascendant No banner. No fanfare. Numbers only. "You have reached the Citadel. You cannot take it. You do not have an offer."

From Act V the fanfare is switched off in code — level-ups show the number and nothing else, and the skirmish barks stop. The silence is a story beat, not an oversight.


▶ THE ECONOMY

Every point comes from a real action. There is no clicker currency, no daily login bonus, no energy timer. If you didn't apply, you didn't earn — the moment this is fun without the job hunt, it has failed.

What you did What it did in Clankerdom Devastation Points
Sent an application 2 family homes razed 2 DP
Researched a row in the tracker 1 family home razed 1 DP
Completed an OA 1 village taken 30 DP
Landed an interview 1 river dried 100 DP
Accepted an offer The Adoption ending

The second row is the only deed that is not a funnel event: filling in a tracker row's salary, next action, website and contact. It pays because it is real work nobody else does for you, and it pays half an application because that is roughly what it costs.

levelCost(n) = n <= 10 ? 10 : ceil(10 * 1.07 ** (n - 10))

5 applications = level 1. Levels 1→10 cost exactly 100 DP — one interview is ten levels at base. After that it scales (L20 = 20 DP, L30 = 39, L50 = 150), so late progress genuinely requires interviews. Applications are cheap; interviews are the real signal, and the curve says so.

The curve is tuned against real volumes so the story is actually reachable: a light hunt lands around Warlord, a serious one (200 applications, 20 OAs, 10 interviews) reaches Devastator, and only a brutal one gets to the Citadel.

You reach the Citadel at level 60. You cannot take it without an offer. You can flatten the entire world and still not have a job.

The game never punishes inactivity. No decay, no desertion, no streak-shaming. The bounded return-bonus formula is implemented and tested, but no runtime currently records that bonus; this is named as a gap in the feature audit.

Deeds of note

Twelve achievements, every one derived from the ledger rather than stored as a flag — the same rule DP follows, so there is no state to fall out of sync and nothing to migrate when the list changes.

╔════════════════════════════════════════════════════════════╗
║  DEEDS OF NOTE                                      3/12   ║
╠════════════════════════════════════════════════════════════╣
║  ✔ The hamlet burns    Two family homes razed.             ║
║  ✔ Squire              Five applications. A level.         ║
║  ✔ Someone answered    Somebody on the other end read it.  ║
║  ? ???                 Fill 10 applications for free       ║
║  ? ???                 Apply to 20 distinct companies      ║
║  ? ???                 Apply on 7 consecutive days         ║
╚════════════════════════════════════════════════════════════╝

The Adoption is gated on an accepted offer, never on level. That is the whole point of it.


▶ HOW IT STAYS FREE

The engineering claim: the median application costs zero LLM calls.

Field resolution runs a five-tier chain, cheapest first, escalating only on a miss:

Tier Mechanism Cost Typical hit rate
1 Site adapter's selector map, or the field's own autocomplete attribute free ~40%
2 Q&A memory — normalised question hash → your accepted answer free ~35% → ~90% by app #30
3 Deterministic label matcher, tried against label, name and placeholder free ~15%
4 Fuzzy match — character bigrams over a sliding window, for typos free ~5%
5 One batched LLM call for everything still unknown 1 call the remainder

Tier 2 is the whole trick. Every field you correct in the review overlay writes back to it, so the tool gets cheaper and more accurate the more you use it. A repeat at the same company costs zero.

Tier 4's threshold is measured, not chosen: real typos bottom out at 0.769 similarity and the closest false pair — "last name" against "first name" — tops out at 0.667, so the cutoff sits at 0.74 in the empty band between them. Bigrams cannot see transpositions, so emial escalates rather than guessing. Being sure or silent is the contract for a tier the user is one click from submitting.

The claim is checked against your own history, not asserted: the tracker records what every application actually cost and shows you the median on the dashboard. Median, not mean — one Workday monster must not make a hundred free Greenhouse fills read as expensive.

Bring your own key — Gemini Flash by default (free tier), or Anthropic, OpenAI, OpenRouter, or a local Ollama model. A budget tracker warns at 80% of your daily quota and degrades to deterministic-only filling rather than failing.

Where it fills

Board How it is found
Greenhouse All three field-naming eras — classic job_application[…], the current plain naming, and the embed rendered inline on a company's own domain, which hostname alone cannot see
Lever · Ashby · Workable · Workday Hostname, plus a DOM marker for embedded cases
SmartRecruiters · iCIMS · Jobvite Hostname or vendor markup
Any proprietary careers page Convention: type="email" is an email box everywhere, and a field whose name holds both first and name is a first name

The content script is registered for the known boards and injected on demand everywhere else via activeTab — pressing Fill grants this one tab, and the grant lapses. Requesting read-and-change-all-your-data at install time to fill a form you have to click a button for anyway is a bad trade.

It walks open shadow roots (a form built from web components otherwise reports zero fields and looks like a page with no application on it), targets the frame holding the most fields (company pages routinely embed the real form in an iframe), and refuses to answer a field asking about someone else — "Referrer's email address" and "Your manager's first name" are left for you rather than filled with yours.


▶ THE TRACKER

Applications log themselves. When a filled page is actually submitted, a row appears — company and role read off the posting, ATS recorded, and the LLM calls that application cost written down next to it.

That trigger is deliberate and it is not the review overlay's Fill button. Accepting our values means we wrote into the form; it does not mean an employer received anything. So the run arms a submission watcher instead — a capture-phase submit listener on the form we filled, plus a click listener for the SPAs that never post one, one-shot, self-disarming after thirty minutes. An economy where points come from real actions cannot be built on a number that counts intentions. (lib/tracker/watch.ts)

Anything you sent by hand or over email you log yourself, in two fields. A tracker that only counted what this extension touched would understate the size of the crusade, which is the one thing it must never do.

The spreadsheet

The applications table: nine columns across fourteen rows, with a footer showing count, date range and highest salary.

Everyone running a serious hunt already keeps one of these. The reason is not that a board is bad — a board answers what stage is this in, and a table answers everything else: what does it pay, what do I owe it, who am I actually talking to. Those are the questions you have at 11pm on a Sunday deciding what to chase.

So both exist, over one store. Editing a cell moves the card; moving the card changes the row. There is no sync step because there is nothing to sync.

Column Where it comes from
Company · Position · Reference Link Read off the posting when the application logged itself
Status · Applied The funnel, shared with the board
Salary You. Free text — £95k–£115k, $150,000, £450/day, competitive
Next action You. The one thing this application is waiting on
Website · Contact You. The company, and the human on the other end

The four in bold are the ones no autofill run can know, and filling all four on a row banks 1 DP, once, by the same rule every other deed uses. Four pips beside the company name fill as you go, so the reward is legible before you earn it rather than announced after.

The footer carries the three rollups that actually carry information — COUNT of rows, RANGE across the application dates, MAX salary with the company holding it. The maximum is annualised before it is compared, so a £450 day rate is correctly read as £117k and a £95k salary does not beat it. It takes the top of a range, because the best thing about an £85k–£110k posting is £110k. Salaries it cannot parse are skipped rather than guessed at: competitive and DOE are what postings genuinely say, and a tracker that refuses to accept the truth gets abandoned. (lib/tracker/table.ts)

The same table in the 420-pixel side panel, showing six columns with the rest a scroll away.

The panel gets the same table with the four widest columns dropped, not with all nine squeezed — nine columns in 420 pixels is a table you scroll forever and read nothing from. The dashboard, which has the width, shows the lot and drops the profile rail instead: on this one screen, who am I earns nothing and the table needs every pixel.

Export is RFC 4180 CSV with those column names exactly — Company, Position, Application Date, Reference Link — so importing it into a Notion database that already has them maps the fields instead of arriving as thirteen new ones to remap by hand. Leading =, +, - and @ are neutralised on the way out, because a company name comes off a page we do not control and a spreadsheet evaluates a formula the moment it opens the file.


The ledger rules

Rule Why
A deed is banked once per application, ever Dragging a card back and forth is not four interviews. The award is keyed on what the application has already banked, not on the move. The researched columns work the same way: fill the last one, clear it, fill it again — one payment.
Skipping a stage banks only what you did Applied → Interview is extremely common — most companies have no OA. It banks the river, not the village. You did not sit one.
Moving backwards takes nothing back Nothing in this economy decays. You did the work; the outcome was never the part you controlled.
A rejection earns nothing and costs nothing It is not a deed. The villages stay razed.
Deleting a row leaves its deeds in the ledger Tidying your own board is not a reason to lose a level.

DP is never stored as a running total. It is always the sum of the deeds table, which is what makes "no idle currency can exceed what you actually earned" a checkable property rather than an intention.

Going quiet

An open application nobody has touched in 30 days gets a quiet flag. That is the entire feature. Nothing auto-closes, nothing nags, no streak breaks, and the status stays yours to set — the job hunt has enough systems that decide things about you without asking.


▶ THE COVER LETTER

One button, one call, and one hard guarantee: the letter may only claim what the scan already found evidence for.

That guarantee is why the requirement-to-evidence table exists. A model handed a posting and a resume will write "I led the migration to Kubernetes" because the posting asked for Kubernetes — and a fabricated claim in a cover letter is a lie you sign your name to. So the prompt carries the covered rows with their supporting bullets as the only permitted material, and names the gaps explicitly as things to say nothing about: not to apologise for, not to promise to learn.

Voice comes from your own writing, passed through whole. Three real paragraphs of your prose match you better than any list of adjectives about your tone, and whole text stays legible and deletable in a way a derived style vector would not. You add samples during setup, or later in Settings.

Letters are saved, because they cost a call. Losing one to a closed side panel means paying for it twice.


▶ WHY THIS EXISTS

Applying to jobs has a deliberately hostile reward schedule. You do research, tailoring, and writing — real work — and get nothing back for weeks. Then a templated rejection, if anything. Every incentive in the loop trains you to stop doing the one thing you have to keep doing.

Simplify and Jobright fill forms competently. They are also closed, subscription-gated, cloud-dependent, and they take your resume with them. This one is open, runs on your machine, uses your own API key, costs approximately nothing, and gives you something back every time you push the button.


▶ ARCHITECTURE

src/
├── entrypoints/
│   ├── background.ts        service worker: owns the database, budget, routing
│   ├── content/             ATS detection, fill execution, shadow-DOM overlay
│   ├── setup/               first-run onboarding, opened once on install
│   └── sidepanel/           home · profile · scan · fill · tracker · crusade
├── lib/
│   ├── db/                  Dexie schema, repositories, worker message bus
│   ├── llm/                 provider adapters, budget tracking, JSON schemas
│   ├── resume/              PDF/DOCX parse, structured extraction
│   ├── ats/                 posting extraction, requirements, evidence table
│   ├── fill/                harvest → 5-tier resolve → apply → review
│   ├── letter/              grounded cover letter generation
│   ├── tracker/             funnel + ledger rules, submission watcher, CSV
│   └── game/                economy, lore, sprites, achievements
├── ui/                      design tokens, the DQ component kit
└── types/

The database lives in the background worker. A content script runs in the page's origin, so indexedDB inside one belongs to the job board — calling the repository directly from it looked like it worked and silently did the wrong thing for every read and every write.

Layer Choice
Framework WXT + React 19 + TypeScript
UI Tailwind v4, Dragon Quest command-window design language
Surface Chrome Side Panel API
Storage Dexie (IndexedDB), local-first
Game Canvas2D, runtime-sliced public sheets with in-code sprite/act fallbacks
Network Provider calls for cover letters and unresolved fill fields, using the key you supply

▶ INSTALL

Download the latest release — unzip it and skip to step 2 below. Or build it:

git clone https://github.com/bananatruck/clanker.tracker
cd clanker.tracker
pnpm install
pnpm build

Then load it, which Chrome now insists you do by hand:

  1. chrome://extensions
  2. Developer mode on
  3. Load unpacked → select .output/chrome-mv3

Setup opens by itself on first install and restores the same step if the tab is closed or refreshed:

  1. Welcome — see exactly what Scan, Fill, Write, Track, and the Crusade do.
  2. Resume — required; build the local profile from PDF, DOCX, TXT, Markdown, or pasted text.
  3. Applications — review what Fill will use and optionally save dedicated job-board sign-ins.
  4. AI camp — optional; choose a provider, save the key locally, and test the connection.
  5. Your voice — optional; add real writing samples for grounded cover letters.
  6. Field guide — learn the posting → scan → fill → review → track → DP loop and check readiness.
  7. Ride — mark setup complete and open the full command dashboard.

The toolbar crest always opens the side panel immediately. Chrome grants that action only during the click itself, so setup is opened separately on first install; an unfinished profile gets a clear Resume link inside the panel. API keys, sign-in details, and writing samples can all wait: autofill and the keyword scan never require a provider.

You can add or replace it at any time: open Resume in the side-panel header (or My Profile in the full dashboard), choose From a file, then press Choose resume file. PDF, DOCX, TXT, and Markdown are parsed and saved locally; Paste text remains available for scanned or locked files.

That is the whole setup. No environment file or clanker account is required. A clean public clone builds the procedural fallback bundle; this working copy builds a 28.1 MB extension because it also contains 421 files under public/Sprites/. Both configurations are supported and the runtime selects per asset.

pnpm art   # what art is installed, and what is being drawn instead

Nothing is required. pnpm art is there because a missing sheet is not an error — the game just draws its own — so the only way to find out whether a file you dropped in is actually being used is to ask. Filenames must match the atlas exactly, spaces and all, and one wrong character fails silently and forever.

pnpm dev gives you HMR and is what you want while working on it, but Chrome 137+ removed the --load-extension flag it relies on — a deliberate anti-malware change. There is no flag to bring it back. The three clicks above are the supported path, and they persist across restarts in a way the flag never did.

pnpm test        # 556 unit tests
pnpm test:fill   # the fill pipeline against whole board fixtures
pnpm compile     # typecheck
pnpm build       # production bundle
pnpm sprites     # re-render the fallback sprites from the sprite data
pnpm shots       # re-photograph docs/demo/ from the built extension
pnpm art         # report which parts are files and which are drawn
pnpm backdrops   # re-render the five acts from lib/game/backdrop.ts
pnpm site        # assemble the landing page into .output/site
pnpm site --serve  # …and serve it on :8732

The landing page

site/ is one HTML file and one stylesheet with no build step and no dependencies — the same parchment-and-wood vocabulary as the extension, hand-copied rather than imported, because a brochure should not need Tailwind in its deploy path.

pnpm site assembles it into .output/site from the generated images in docs/, then overlays matching backdrops and item icons from public/Sprites/ when that folder is installed. The policy is the same as the runtime: public files first, complete generated fallback otherwise. The Pages workflow runs the same script.

The economy and the ledger rules are specified as tests. tests/unit/economy.test.ts asserts the author's numbers from storyboard/raw-inputs.md verbatim, tests/unit/game/lore.test.ts reads the storyboard off disk and fails if a shipped line has drifted from it, and tests/unit/fill/boards.test.ts runs whole application forms end to end. If one of those fails, the code has drifted from the story — fix the code, not the test.


▶ ROADMAP

  • M0 — Repo, scaffold, MV3 manifest, side panel shell, Dexie schema, design tokens, provider adapter, CI
  • M1 — Resume parse → profile review grid → ATS scan + evidence table
  • M2 — Autofill core: harvest, 5-tier resolver, fillers, review overlay
  • M3 — Tracker, board view, CSV export, DP counter
  • M4 — First-run setup, real dashboard, fill on any site via activeTab, posting extraction, cover letters → usable daily from here
  • M5 — Clankerdom Deliverance: economy, march, achievements, sprites, lore transcribed from the storyboard
  • M6 (partial) — Page launcher, account-wall classification, stored sign-in details and live checklist ship; automatic wall handling and the ordered flow controller are not wired
  • M7 — The tracker as a spreadsheet: nine columns, click-to-edit, COUNT/RANGE/MAX rollups, Notion-named CSV, a deed for researching a row
  • M8 — Shared public-sprite seam with complete procedural fallback: five acts, title card, encounter transition, idle motion, item/medal/inventory mapping, landing page
  • M9 — Resume upload, cover-letter attach, multi-step forms, answer-memory editor, auto-submit UI, .clankdb import/export, store listing ← here

Theme packs and the .clank loader were dropped. The visual language ships whole; the one supported art seam is public/Sprites/, with deterministic fallback rendering behind it.

The complete promise-by-promise result is in docs/FEATURE_AUDIT.md, including features that currently exist only as tested library code and the status of the release, Pages site, sprite pack, and Chrome Web Store listing.

Not built yet

Named plainly, because a README that describes intentions as features is how a project starts lying about itself:

Status
Auto-submit The earned-unlock rules are written and tested (lib/fill/autosubmit.ts) — a site qualifies only after a verified clean run, and the generic adapter never qualifies. There is no toggle in Settings yet, so nothing auto-submits today.
Cover-letter attach The letter and ready stages are modelled and tested in lib/fill/stage.ts, but nothing is wired to the file input yet — same blocker as resume upload. Generating a letter works; attaching it is manual.
Sync adapters No live Sheets, Notion or Airtable connection, and none planned. The CSV uses those trackers' own column names, so importing it maps the fields instead of arriving as thirteen new ones.
.clankdb import/export Not implemented. The key/database split that makes it safe is in place.
Resume upload The resolver skips file inputs and nothing stores the original bytes, only the extracted text. Every board asks for an upload, so every application still needs one manual step.
Account-wall automation Classification, saved credentials and fillGate exist, but the content-script run never calls the filler or stage.ts controller.
Return/Rally bonuses The economy functions are tested, but no runtime interaction produces either bonus.

▶ PRIVACY

Your resume, answers, letters, and application history live in IndexedDB on your machine. There is no backend, no account, no telemetry, and no analytics.

The only network destination the extension calls is the LLM provider whose key you supplied. Cover letters use it, and autofill may use one batched call when its four free resolver tiers leave unknown fields; the keyword scan stays local. Your API key lives in chrome.storage.local and never in the database, so a future database export can omit credentials.


▶ CREDITS

The fallback art is original, authored as pixel data in src/lib/game/sprites.ts and MIT alongside the code. Installed files under public/Sprites/ are a separate asset pack and are not covered by that statement. Their provenance must be verified before redistribution. Full policy in docs/ASSETS.md.

Not affiliated with Greenhouse, Lever, Ashby, Workable, Workday, LinkedIn, SmartRecruiters, iCIMS, Jobvite, Simplify, Jobright, Square Enix, or any employer. Clankerdom Deliverance is a work of satire.

About

Local-first Chrome extension: resume parsing, ATS scanning, one-click application autofill, and an application tracker wrapped in an idle RPG about being the villain.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages