The ten stages
Six are positions on the path. Four are endings, and the difference between them is the whole point.
The first six are the board columns. The four endings get their own view.
Solid arrows are progress; dotted ones are the endings, and an application can reach any
of them from anywhere. Nothing enforces the order — you can move a card straight from the
wishlist to an offer if that is what happened.
Colour carries the same information: hue rotates in one direction as an application
advances — steel, blue, violet, pink, then gold at the offer — so two chips read as
“further along” without you knowing which label is which. The endings sit outside that
rotation, because they mean something other than progress.
Capturing something
From a URL
capture_job_posting fetches the page server-side, reads the structured posting data
most job boards publish, and creates the application in one move — company matched or
created with its own website, role title, full description, location, compensation
and source, starting on the wishlist.By hand
create_application needs only company and roleTitle. The company is created
automatically if it does not exist yet.capture_job_posting
returns captured: false with whatever it did parse and creates nothing — deliberately,
because an employer guessed from a URL is worse than an employer you were asked about.
A listing is optional
A role you are chasing through a LinkedIn DM with no posting at all is still an application. Track it with just company and role title, putCold outreach in sources,
and attach the person you messaged as a contact.
Where it came from
sources is a list, because a job board posting, a referral and a LinkedIn message are
often the same job. They are free strings underneath, so nothing stops
met the CTO at a wedding.
The starters are LinkedIn, Job board, Company site, Referral, Recruiter reached out and
Cold outreach. Your own list is those plus everything you have already used — call
list_application_sources before writing one so you reuse your existing spellings
instead of minting near-duplicates.
The timeline
Every application has one, and everything that happened goes on it. Twelve activity types:NOTE · STAGE_CHANGE · EMAIL_SENT · EMAIL_RECEIVED · CALL · INTERVIEW ·
FOLLOW_UP · APPLIED · OFFER · REJECTION · REFERRAL · OUTREACH
OUTREACH is for a message you sent first — a DM to a hiring manager, a cold email.
Half of some searches happen there, before or instead of a formal application.
Moving a stage writes its own timeline entry and resets the follow-up date, so
move_application_stage is one call rather than two. Do not also log the change by hand.
Write the entry the way you said it. “Recruiter said the team is six people and they
want someone to own billing end to end” is worth far more in three months than “had a
call” — and it is what makes a follow-up message refer to something real.
Follow-ups that set themselves
Changing stage schedules the next nudge automatically, for 9am on the day it falls:
Moving to
WISHLIST schedules nothing. Moving to one of the four endings clears any
follow-up date the application had and stamps it closed — a finished application should not
keep nagging you. Override any of it by hand: nextFollowUpAt on the application, or the
cell in the table.
Moving out of WISHLIST for the first time also stamps the applied date, if it was not
already set.
Contacts have their own version: nextFollowUpAt on a person is where “ping Sarah in two
weeks” lives.
Three ways to ask what is due
list_follow_ups
What is already due, or due within N days. Returns two lists: applications whose date
has arrived, and contacts whose ping has. Both are work.
list_schedule
Everything dated between two dates, merged and sorted: follow-ups, task deadlines and
activity already logged. The right call for “what does my week look like”.
list_tasks
To-dos, with or without a due date, optionally attached to an application.
Reading the search
pipeline_stats gives you the counts: by stage, active, sent this week, interviews,
offers, open tasks, follow-ups due, response rate.
diagnose_search gives you the answer. It returns a one-sentence verdict naming which
step of the funnel is losing people — no responses at all is a resume or targeting
problem, responses that die at the phone screen is a story problem, interviews that do
not convert is something else again — plus per-step conversion, median days in each
stage, weekly volume for the last six weeks, applications that have gone quiet, and the
response rate of each resume so you can see which one is working.
Progress is measured by the furthest stage an application ever reached, so a rejection
after a final round counts as having got that far. When there is not enough data yet, it
says so plainly rather than inventing a trend.
Views and cuts
The pipeline toolbar picks the view — a drag-and-drop board, a sortable table, or a month calendar of everything with a date on it — plus the stage filter and a search. Stage filters combine, so “screening and interviewing” is one view rather than two trips. The table edits in place: stage, follow-up, salary and location are the cells themselves, a Waiting column counts days since anything last moved, and selecting rows closes a batch out in one action. A cut worth keeping gets saved under a name. A saved view stores the pipeline URL’s own parameters:
Saving under a name that already exists replaces that view, which is how you edit one.
Anything outside those six parameters is dropped, and they are always written in that
order — so the same view saved twice is the same string.
Sharing the board
share_pipeline mints a read-only link at /p/<slug> for a friend, a coach or a former
manager who is helping you review the search. What a viewer sees is deliberately narrow:
They see
Company, role, stage, location, how long each has been sitting, and when a follow-up
is due. Optionally the closed applications too.
They never see
Notes, job descriptions, salary, contacts, or the activity timeline.
unshare_pipeline
destroys the address rather than pausing it — sharing again later mints a completely
different URL — because the reason to revoke is usually that a link reached someone it
should not have, and a pause you can undo does not fix that.