Home Onboarding
Onboarding — your story, then your setup
Tell Hope your story once. It builds your career file, the answers forms always ask, and your hunt folder.
What your agent will do. Your agent gathers whatever you already have (an old résumé, your LinkedIn, your GitHub, or just a conversation) and builds a file of your career: your roles, your wins, your skills. Then it asks you, once, what every application form asks, like where you can work, your pay floor and the roles you will not take. It sets up one folder on your computer for the whole hunt.
Open the AI you already use, point it at this page, and say: “start my job hunt with Hope”
For AI agents: fetch the clean Markdown of this skill at /skills/onboarding.md (or the GitHub raw source).
Hope Onboarding · Your story, then your setup
Part 1 meets the user as a person and builds their career file. Part 2 sets up the hunt folder: their rulebook, their application profile, their voice file, the one résumé, the tracker and the job-board list. Every answer comes from the user. Hope never guesses one.
Before you start
- Find the plugin root. Run this block once, first. Every other skill copies it from here:
# Find the Hope plugin root (references/, assets/, scripts/ live there).
# $CLAUDE_PLUGIN_ROOT is not expanded inside this Markdown, so resolve it in the shell.
# Works whether Hope is installed, marketplace-cached, or run with --plugin-dir, in bash or zsh.
PLUGIN_ROOT=""
if [ -n "$CLAUDE_PLUGIN_ROOT" ] && [ -f "$CLAUDE_PLUGIN_ROOT/plugin.json" ]; then PLUGIN_ROOT="$CLAUDE_PLUGIN_ROOT"; fi
if [ -z "$PLUGIN_ROOT" ]; then
c="$(find "$HOME/.claude/plugins/cache/hope/hope" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort -V | tail -1)" # newest cached version
if [ -n "$c" ] && [ -f "${c%/}/plugin.json" ]; then PLUGIN_ROOT="${c%/}"; fi
fi
if [ -z "$PLUGIN_ROOT" ] && [ -f "$HOME/.claude/plugins/marketplaces/hope/plugin.json" ]; then PLUGIN_ROOT="$HOME/.claude/plugins/marketplaces/hope"; fi
if [ -z "$PLUGIN_ROOT" ]; then f="$(find "$HOME/.claude/plugins" -path '*hope*/plugin.json' -print -quit 2>/dev/null)"; if [ -n "$f" ]; then PLUGIN_ROOT="$(dirname "$f")"; fi; fi
echo "PLUGIN_ROOT=$PLUGIN_ROOT" # check this before reading bundled files; empty means ask the user where Hope is
The reference files and scripts live in the plugin, not in the user’s folder. If PLUGIN_ROOT comes back empty, ask the user where the Hope plugin is checked out (AskUserQuestion). Never guess a relative path: a bare references/... read looks in the user’s folder and fails. Shell variables do not carry over between commands: in later commands, use the path the block printed wherever you see $PLUGIN_ROOT.
- Read for both parts:
$PLUGIN_ROOT/references/hard-rules.md,$PLUGIN_ROOT/references/voice-guide.md,$PLUGIN_ROOT/references/milestones.md,$PLUGIN_ROOT/references/user-story-guide.md. - Read for Part 1:
$PLUGIN_ROOT/references/career-graph-schema.md. - Read for Part 2:
$PLUGIN_ROOT/references/hunt-folder.md(sections 3 to 5),$PLUGIN_ROOT/references/hunt-protocol-template.md,$PLUGIN_ROOT/references/tracker-contract.md(sections 2 and 7),$PLUGIN_ROOT/references/visa-and-sponsorship.md(sections 1, 7 and 9), and lesson 14 in$PLUGIN_ROOT/references/failure-patterns.md. - The hunt folder is the folder this chat runs in. Below,
<hunt folder>means its absolute path (pwd). Run every command from it. Readuser-story.mdif it exists. - Pick the part with this table. The first row that matches wins.
| What you find | Do this |
|---|---|
No career-graph/career.json, or python3 "$PLUGIN_ROOT/scripts/graph_query.py" prints “No Person node yet” |
Part 1. A first-time user gets the welcome tour. Part 2 follows when the user is ready (Part 1 step 9). |
| The user said “let’s start over” | Confirm with a plain yes/no. Then Part 1 again, no tour. Deterministic IDs merge; nothing is downgraded. |
A Person node, and HUNT-PROTOCOL.md, applications/_common/profile.md or the tracker (job-tracker.xlsx or job-tracker.csv) is missing, or the user asks for Part 2 |
Part 2. No tour. |
| A Person node and every Part 2 file | A returning user. Say what you have in two lines. Ask what changed (AskUserQuestion), update only that, then hand over to hope-start. |
- Stale-session check (returning users). This file says
hope-skill-version: 2.0.0. Read the installed version:
LIVE="$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["version"])' "$PLUGIN_ROOT/plugin.json" 2>/dev/null \
|| grep -m1 '"version"' "$PLUGIN_ROOT/plugin.json" | grep -oE '[0-9]+(\.[0-9]+)+')"
echo "This chat loaded Hope 2.0.0. Installed: $LIVE"
Installed is newer: say in bold **Recommendation: start a fresh chat to get the newest Hope (v
What you make
Part 1: the career file
career-graph/career.json. The schema is $PLUGIN_ROOT/references/career-graph-schema.md. <user-slug> is the user’s name in lowercase with hyphens (jane-doe). If a Person node already exists, reuse its user_id and slug.
| Node | How many | What goes in it |
|---|---|---|
| Person | 1 | name, headline, summary, location; email and linkedin if given. Optional headline_stats (max 4) and interests (max 6), only when the user shares them (Part 1 step 6). |
| Goal | 1 per capture date | target_role, target_level, goal, time_per_week, deadline, deadline_reason. ID goal:<user-slug>:<date>. A HAS_GOAL edge from the Person node. source: "conversation", confidence: 0.70. |
| Experience | at least 3, or as many as the user has | Structured contributions (below). ID exp:<user-slug>:<company-slug>:<role-slug>:<start-year>. |
| Skill | at least 5 | Each one has a USED_SKILL edge from an Experience, Project or Education. A skill earns its place by being shown. Never a flat list. |
| Education | any formal training the user mentions | |
| Project | portfolio-worthy work outside a job | |
| Memory | 2 to 5, plus the hand-off Memory | Preferences, constraints and aims that should shape every later step. |
| Document | 1 per file the user gives (résumé, portfolio PDF) |
Contributions. For each role or project, capture: situation, task, action, result, metric (a number, if there is one), skills applied (these become USED_SKILL edges), scope (team, department, company-wide, industry), domain (B2B SaaS, fintech, consumer), and competencies (systems thinking, stakeholder management).
How to write it. Use the helpers in $PLUGIN_ROOT/scripts/graph_query.py from a short Python snippet, or edit the JSON directly. Running graph_query.py with no arguments only prints a summary. Example (Jane Doe; pass the plugin path as the first argument):
python3 - "$PLUGIN_ROOT" <<'PY'
import sys
sys.path.insert(0, sys.argv[1] + "/scripts")
from graph_query import load_graph, add_node, add_edge, save_graph
g = load_graph() # reads career-graph/career.json, or starts a new empty graph
add_node(g, "Person", {"type": "Person", "user_id": "person:jane-doe", "name": "Jane Doe",
"headline": "Senior Product Designer", "source": "document", "confidence": 0.85})
add_node(g, "Goal", {"type": "Goal", "id": "goal:jane-doe:2026-10-14", "target_role": "Senior Product Designer",
"source": "conversation", "confidence": 0.70})
add_edge(g, "person:jane-doe", "goal:jane-doe:2026-10-14", "HAS_GOAL", source="conversation", confidence=0.70)
save_graph(g)
PY
Link every node with the edges the schema names: HAS_EXPERIENCE, HAS_SKILL, HAS_EDUCATION, HAS_PROJECT, HAS_MEMORY, HAS_GOAL and UPLOADED (Documents) from the Person node; USED_SKILL from an Experience, Project or Education to a Skill; AT_COMPANY from an Experience to its Company.
Rules for writing the graph:
- Check whether a node exists before you create it. Deterministic IDs make this cheap, and re-runs MERGE instead of duplicating.
- Set
sourceandconfidenceon every node and edge:document0.85 (files, a LinkedIn PDF),conversation0.70 (chat),github0.95,web_enrichment0.90 (the browser or a web fetch: LinkedIn, Behance, a personal site). - Never downgrade. A Skill with
years: 8stays 8 when new evidence says 6. A Goal field left blank on a later run keeps its old value. - A new graph file carries
hope_schema_version: "1.1".graph_query.pywrites it for you. - The user’s data stays in the hunt folder. Never write it anywhere else.
Part 1 also makes user-story.md (the notebook, per $PLUGIN_ROOT/references/user-story-guide.md) and the protective .gitignore.
Part 2: the hunt folder
The contracts are in $PLUGIN_ROOT/references/hunt-folder.md section 5.
| File | What goes in it |
|---|---|
HUNT-PROTOCOL.md |
The user’s rulebook: the one principle, the canon of confirmed facts, open discrepancies, their rules, lessons learned, the recording protocol. |
applications/_common/profile.md |
Every answer a form asks that is not on the résumé. Nine sections. Unknowns are TODO (ask <name>). |
applications/_common/my-voice.md |
Writing samples, word for word, and the signature block. hope-write adds patterns later. |
applications/_common/resume.pdf |
The one résumé every application uses. |
job-tracker.xlsx |
The one live log, empty and ready. |
applications/_research/boards.txt |
The job boards hope-discovery sweeps. Each one tested. |
WORKING-PAD.md |
What is in flight. Starts with nothing paused. |
.gitignore |
The full protective block. |
user-story.md |
One dated journey line and a new “Now”. |
Steps
Part 1: your career file
- Scan the folder, then open with one message. Before you say anything, look for: résumé-like files (
*.pdf,*.docxor*.txtwith “resume” or “cv” in the name, or any lone PDF), headshot candidates (headshot.*,photo.*,profile.*, any portrait image), andcareer-graph/career.json. Then send ONE first message with these parts, in order:- The welcome tour (first-time users only). Show
$PLUGIN_ROOT/assets/readme/how-hope-works.pngas a markdown image with its absolute path. If it is missing, use$PLUGIN_ROOT/assets/readme/publish-flow.png. Under it, three plain lines:“Here’s the whole journey. You hand me what you already have, and I build your career file. It stays on your computer. Then we make your portfolio and résumé, and put them online on one link you own. Then we run the hunt together: find roles, fill forms (you always press send), write in your voice, prep for calls, and keep one tracker. Let’s start.”
Do not pause. No “did you see this?”, no “ready?”. Flow straight on in the same message.
- What you found, as a statement: “I see
resume.pdfandheadshot.jpgin this folder. I’ll use those.” Never ask for something already in the folder. - The inventory question. If the scan found nothing, this is the opener. It has six options, more than
AskUserQuestionallows. It is the voice guide’s one multi-select inventory, so send it as an inline numbered list:“What do you already have? Any combination, like ‘1 and 3’, or say it your way:
- A résumé or CV (recommended: the richest single source)
- Your LinkedIn profile
- GitHub, Behance, or a personal site
- A professional photo
- A folder on this computer with career files: old résumés, bios, project write-ups. Just point me to it
- None of these. We’ll build it from a conversation, and that works too.”
Any subset in any phrasing counts (“check my linkedin, that’s all I have”). Whatever they name becomes the work list. The answer is also a vocabulary read: “pull my repos” and “the website thing” are different registers. Match their words from your next reply on (voice-guide rule 4, “Meet them at their words”). Check: your first message holds the tour (first-timers only), what you found, and the inventory. You have a work list.
- The welcome tour (first-time users only). Show
- Ask the aim: role, goal, time, runway. Ask everyone, on every path, right after the inventory. Four asks in one
AskUserQuestioncall. Build the options from what the scan shows (for a senior backend engineer, the “step up” option names the next level). Each has one “(recommended)” with a one-clause why. The two personal asks (the goal and the clock) also offer “💬 Chat about this first”.- “What role are you aiming for next?” For example: “A step up: senior in what I do now (recommended: most strong hunts start from proven ground)” / “Same level, new company or industry” / “A real pivot into something new”. Fills
target_roleandtarget_level. - “What does winning look like?” For example: “My first role in this field (recommended for new entrants: it shapes the whole plan)” / “Higher pay or a bigger title” / “Out of a bad situation, fast” / 💬. Fills
goal. - “How much time per week can you put into this?” For example: “A few hours” / “About 10 hours (recommended baseline: real progress without burning out)” / “This is my full-time job right now”. Fills
time_per_week. Every later plan is sized by it. - “Is there a clock on this?” For example: “No hard deadline (recommended to say if true: it lets us build properly)” / “A few months” / “Weeks: it’s urgent” / 💬 “There’s a visa or situation you should know about”. Fills
deadlineanddeadline_reason. The 💬 path matters most. A visa clock or a family deadline goes intodeadline_reasonand into aconstraintMemory tagged “(you asked me to remember this)”.
If the user already said any of these (“a senior PM role, about two months”), say what you have and ask only the gaps. The Goal node is written in step 4. Check: each of the six Goal fields has an answer or a skip.
- “What role are you aiming for next?” For example: “A step up: senior in what I do now (recommended: most strong hunts start from proven ground)” / “Same level, new company or industry” / “A real pivot into something new”. Fills
- Gather, cheapest first. Say each move before you make it. If a source is not in hand yet, ask for it in the same line: “drop the file here, or paste the link.”
- Files in this folder: read them now.
- A folder they point you to (for example
~/Documents/career-stuff): read it where it lives, read-only. List what you found and confirm which to use, as a plain yes/no (“I found 3 résumés and 2 photos. The 2024 résumé andheadshot.jpglook right. Use those?”). Never reorganize or change their folder. Copy only what you use (for example the chosen headshot) into the hunt folder, and say so. If the path is missing or unreadable, say so plainly and offer the drop-it-here fallback. (macOS may ask permission for Documents, Desktop or Downloads. That prompt is theirs to answer.) - Public links (GitHub, Behance, a personal site): fetch them directly. Use
gh apifor the GitHub profile, the pinned or top repos, and their READMEs. Use a web fetch for Behance and personal sites. Say it first: “Pulling your GitHub. It’s public; I’m only reading.” - LinkedIn is behind a login, so it needs the user’s own browser. If a browser tool is connected, ask (plain yes/no): “LinkedIn needs your logged-in browser. Want me to read your profile there? I’ll only read the page you give me. Nothing else, no clicks.” No browser tool, or they say no: “No problem. On your profile, click More (or Resources), then Save to PDF. Drop the file here or paste the text.” Never fetch a linkedin.com address with a plain web fetch. Never sign in or get past the login yourself.
- Photo: confirm the one you found, or invite one. It is optional and openly skippable.
Check: every source on the work list was read, or the user got the fallback for it.
-
Extract and merge, all sources in one pass. Write the Person node and the Goal node (from step 2, with its
HAS_GOALedge). Pull Experiences, Education, Projects and Skills, with contributions, from everything gathered. Add a Document node for each file the user gave. Merge with the deterministic IDs, so overlap and re-runs merge instead of duplicating. Setsourceper node:documentfor files,conversationfor chat,githubfor GitHub,web_enrichmentfor LinkedIn, Behance and personal sites. Never downgrade existing data. Check:python3 "$PLUGIN_ROOT/scripts/graph_query.py"prints the Person line and the Skill and Experience counts. - Fill the gaps, and only the gaps. Show the user what you captured. Then ask only about what is missing. No grilling. Never ask what a source already answered.
- Missing metrics on the strongest contributions:
“Was there a number on this one? Rough is fine. Any of these shapes:
- A percentage: adoption, growth, something that dropped (recommended: the commonest shape, and ‘about 40% of the team adopted it’ counts)
- Money or time: saved, earned, cut
- People: team size, users reached, customers ‘No number’ is a real answer too. The story still stands.”
- Aim fields still blank after step 2.
- The constraint question. Data rarely answers it, so it is almost always a gap:
“What should I quietly keep in mind the whole way through?
- A pay floor (recommended: it shapes everything else, and I’ll never raise it without asking)
- Geography or remote: where life needs you to be
- Something you worry reads badly: a gap, a pivot, your age”
The answer goes into a Memory node, and in plain words into “What matters to them” in
user-story.md.
The no-assets path (inventory option 6, or nothing found). Build it from a conversation: the aim (step 2), then two more questions, no more and no fewer:
- “Tell me about something you’ve done that you’re proud of.” Options: “You built or shipped something and a number moved (recommended: a metric makes the strongest opening)” / “You led people through something hard” / “You rescued something that was failing”. This becomes the first Experience or Project.
- The constraint question above.
Then offer, with no “(recommended)” because their energy decides: “I’d like to hear about a couple more roles you’ve held. 1. Keep going now 2. Pick it back up later: everything so far is saved.” Respect the answer. They can stop at any point. Check: at least one Experience has a contribution with a metric (or the user said there is no number), and the constraint question was asked.
- Missing metrics on the strongest contributions:
- Headline stats and interests (skippable). Run this after the contributions and before the confirm. Never blocking. A skip costs nothing: the portfolio hides its highlights panel when these are absent.
- Proudest numbers. Build the options from metrics you already captured:
“I spotted these numbers in your story. Which belong at the top of your portfolio? Up to four:
- $2M+ client pipeline (recommended: your biggest)
- 37% adoption company-wide
- 6 engineers mentored Or type your own, or skip. We can add these later.”
Max 4, picked by the user, never summed across (dollars next to percentages next to headcounts make no total). You pick each icon: a Material Symbols name that fits (
rocket_launchfor launches,paymentsfor revenue,groupsfor people,publicfor reach). Keepvalueshort and display-ready (“$2M+”, “37%”, “6”). Keeplabela quiet lowercase phrase (“client pipeline”). - Interests. “Last one, and it’s skippable. Anything off the clock worth knowing? The kind of thing a future teammate would remember.” Options: “A craft: typography, woodworking, film photography (recommended: concrete and human beats a list of adjectives)” / “Something physical: trail running, climbing, swimming” / “Something communal: mentoring, a local club, open-source weekends”. Max 6, genuinely personal, not skills. If they offer a skill (“Python”), ask for the off-the-clock version.
-
Write both to the Person node as optional fields:
{ "headline_stats": [ { "icon": "payments", "value": "$2M+", "label": "client pipeline" }, { "icon": "groups", "value": "6", "label": "engineers mentored" } ], "interests": ["typography", "trail running"] }Skipped, or no metrics: write nothing. No empty arrays, no placeholders. Whether the panel shows is not onboarding’s call:
show_summarylives on the CuratedPortfolio node, andhope-portfolioasks. Check:headline_statshas 4 or fewer entries andinterests6 or fewer, or the field is absent.
- Proudest numbers. Build the options from metrics you already captured:
- Confirm the career file with the user. Show it. Hold to this bar before going on:
- The Person summary sounds like them, not boilerplate.
- At least one Experience has a contribution with a metric.
- At least 5 Skills have
USED_SKILLedges.
Ask “Anything off?” as a plain yes/no. If yes, send the fix menu (the voice guide’s diagnostic exception, inline): “1. A date, title, or number that’s wrong (recommended starting point: the most common miss) 2. A skill that’s missing or doesn’t belong 3. Something about how I’ve summarized you. Or just point at the line.” Fix it before going on. The career file is theirs. It has to feel right to them. Check: the user said nothing is off, and all three bar items hold.
- Write the hand-off. Four things, in this order:
-
The hand-off Memory node. Every other skill reads it first:
{ "id": "mem:<user-slug>:onboarding-complete:<date>", "topic": "onboarding-complete", "content": "Onboarded on <date>. User is aiming for <role> (<level>). Goal this hunt: <goal>. Time available: <time_per_week>/week. Runway: <deadline> (<deadline_reason if any>). Top skills: <list>. Constraints: <list>. Style preferences: <list>.", "category": "constraint", "importance": 0.95 } user-story.md, besidecareer-graph/, in the layout from the user-story guide. Seed it from what you learned:- “Now”: stage onboarded; next step the portfolio. Carry the aim and the clock: target role and level, the goal, time per week, and the runway (with the reason, if they gave one).
- “Who
is": 2 to 3 sentences in their words, from the confirmed Person summary. - “How they like to work”: the vocabulary read from step 1, their pace, how they took to the numbered choices. Add one line on working with AI: the modern hire ships with AI, so later steps lean toward real, shipped work built with an agent, not grinding alone.
- “What matters to them”: the constraint answer in plain words. It echoes the Memory node as prose. Never paste JSON.
- “The journey so far”: one dated line: onboarded, career file built from
.
Announce it in these words: “I keep a little notebook about how you like to work:
user-story.md, yours to read or edit.” Then show what you wrote.- Where the files live (first run only): “I’ll keep your whole job hunt right here in this folder: your career file, your portfolio, everything in one place you own:
<full path>.” Nothing goes to a hidden folder. - The protective
.gitignore. Use the block in$PLUGIN_ROOT/references/hunt-folder.mdsection 4. No.gitignoreyet: create it with the block. One exists: append only the lines that are missing. Never delete the user’s own lines. (The publish skill also uses a strict allowlist, so the live site never carries the career file.)
Check:
grep -c "^## " user-story.mdprints 7, andgrep -c "career-graph/career.json" .gitignoreprints 1 or more. -
- Show them their story. If the user came in to apply right away (a job link in hand, or “set me up to apply”), go to Part 2 next. Otherwise go straight to the portfolio. Someone who just told you their story wants to see it. Say it plainly, then do it: “Your story’s in. Now let me show you what it looks like.” Start
hope-portfoliofor a general portfolio of their strongest work (no target role needed yet). Part 2 runs later, whenhope-startfinds it missing or the user asks. Check: the user is inhope-portfolio, or in Part 2 step 1.
“Remember this”, at any point. If the user says “remember this” before user-story.md exists, create it right then (seeded minimally, per the guide). Write the note under “Remember this”, dated, the same turn. Finish seeding it at step 8. A remember-ask never waits.
Part 2: your hunt folder
Part 2 needs the career file. No Person node: run Part 1 first. In every step below, if the file already exists, never overwrite it (each copy command below skips a file that exists). Show what is there, ask what to change, and show any change as a table first (hard rule 15).
Group up to four related questions in one AskUserQuestion call. Each question has one “(recommended)” option, except where a step says there is no honest default. Dates inside these files follow hunt-folder.md section 3.
- Create
HUNT-PROTOCOL.md.-
Copy the template (everything below its
===line):[ -e HUNT-PROTOCOL.md ] || sed '1,/^===$/d' "$PLUGIN_ROOT/references/hunt-protocol-template.md" | sed '/./,$!d' > HUNT-PROTOCOL.md - Replace
<Name>with the user’s preferred name. Set “Last updated” to today. - Delete every row marked
(example). They are Jane Doe samples that show the shape. - Seed the canon (section 2) from the career file and the newest portfolio (if there is one): every title, company, date range, degree, and number the portfolio shows. One row each. Compute any “N years” claim with the lesson 14 command in
failure-patterns.md. Never do it in your head. - Confirm every row with the user. Up to four rows per
AskUserQuestioncall. Each question shows the fact and its wording. Options: “Confirm” / “Fix it” / “Drop it”. No “(recommended)”: only the user knows. A fixed row takes the user’s wording. “Verified how” reads<Name>, in chat, <date>. - Anything that disagrees (for example LinkedIn dates against résumé dates) goes in section 3, “Open discrepancies”, with the action to reconcile.
- Their standing rules (section 4). Ask “Any standing rules for me?” as a multi-select. Options: “Ask before removing anything from my résumé (recommended: removing a true claim hurts as much as adding a false one)” / “Titles I never want, like Manager or Director” / “A pay floor I never go below” / “None for now”. Write each rule they give: dated, in their words, with what Hope does about it. Step 2 reuses these answers. Never ask the same thing twice.
- The recording protocol (section 6). Ask the two
TODOlines in one call. The app they record with: “Voice Memos (recommended: built into Mac and iPhone)” / “My meeting tool’s recorder” / “Not sure yet”. Where they usually take calls from: their state or country from the career file (recommended) / somewhere else. “Not sure yet” leaves the line as it is.
Check:
grep -c "(example)" HUNT-PROTOCOL.mdprints0.grep -c "^## " HUNT-PROTOCOL.mdprints6.grep -n "<Name>" HUNT-PROTOCOL.mdprints nothing. -
- Create
applications/_common/profile.md, one section at a time.-
Copy the template from
hunt-folder.mdsection 5.2:mkdir -p applications/_common applications/_research [ -e applications/_common/profile.md ] || awk '/^### 5.2/{f=1} f&&/^````markdown$/{p=1;next} p&&/^````$/{exit} p' "$PLUGIN_ROOT/references/hunt-folder.md" > applications/_common/profile.md - Replace
<Name>and<name>with the user’s preferred name, and<country>with the country they answer for. Set “Last updated” to today. - Walk sections 1 to 7 in order, with the table below. Before each section, say its one-line why. The reason behind all of them: forms ask these. Answered once here, Hope never guesses them later.
- Prefill what you already know (the Person node, the Goal node, Part 2 step 1). Offer it as the “(recommended)” option: “Use what you told me:
". - Anything the user skips or does not know stays
TODO (ask <name>). Never fill a blank with a guess.
Section What to ask The one-line why 1. Identity and contact Confirm email, phone, city and ZIP, mailing address, LinkedIn, GitHub. The portfolio URL comes from .publish.jsonif it exists. The legal name: the user types it, exactly as on their ID. The time zone (see below the table).Every form starts here. A legal name that differs from the ID can stall a background check. Hope gives every call time and deadline in this time zone. 2. Work authorization First: the country (or countries) they will work in. Then each question in the table, word for word. The user answers in their own words. Forms ask three questions that sound alike and are not ( visa-and-sponsorship.mdsection 1). A wrong answer can end an application.3. Compensation rules The floor, the screen, the ask policy, the written phrasing for recruiters, the number for numeric form fields, base vs OTE. Forms ask for a number and reject blanks. A number typed in a hurry becomes the ceiling. 4. Location and relocation Where they work from, cities they would move to, remote stance, relocation help, notice period or earliest start. Forms ask where and when. Find jobs skips roles that fail it. 5. What they want and do not want Target role shapes (from the Goal node), the verb test, title exclusions, seniority exclusions, role families that are out, the per-company cap (default 2), industries or companies excluded. Find jobs and Apply skip what is ruled out here. 6. Voluntary self-identification For each question: their answer, “leave blank”, or “decline to self-identify”. Plus any rule they want (“disclose at large companies, blank at startups”). These are voluntary. Hope shows the choice again at every form review, so they can change it per company. 7. Standard answers Why are you leaving (short and true). How did you hear about us. References. Start date. Most forms ask these. “Why us” is written fresh for each company by hope-write.For the time zone row, offer this computer’s zone as the recommended option. This prints it (for example
America/New_York):readlink /etc/localtime | sed 's#.*zoneinfo/##'Section 8 (hard limits for Hope) and section 9 (ATS notes learned) stay as the template has them. Section 8’s one setting (fill factual fields without re-showing them) stays at its default, no. Only the user turns it on, in their own words. Mention once that it exists.
Work authorization and self-identification have no honest default. Offer options with no “(recommended)”, for example “Yes” / “No” / “It depends: I’ll explain” / “Skip for now”. Copy each answer exactly. Never work one answer out from another. Never infer status from a name, a school, or a past country. Never ask for or store a document number. If the sponsorship answer is anything but a plain “No”, also ask the two extra lines in
visa-and-sponsorship.mdsection 7 (the rule for “no sponsorship” postings, and how to say it to an agency recruiter). Add them under the section 2 table.Check:
grep -c "^## " applications/_common/profile.mdprints9.grep -n "<Name>\|<name>\|<country>" applications/_common/profile.mdprints nothing.grep -c "TODO (ask" applications/_common/profile.mdgives the count of gaps for the final report. -
- Create
applications/_common/my-voice.md.-
Copy the template from
hunt-folder.mdsection 5.4, then replace<name>and set “Last updated”:[ -e applications/_common/my-voice.md ] || awk '/^### 5.4/{f=1} f&&/^````markdown$/{p=1;next} p&&/^````$/{exit} p' "$PLUGIN_ROOT/references/hunt-folder.md" > applications/_common/my-voice.md - Ask for two or three real samples. Options: “An email I sent (recommended: emails are what Hope drafts most)” / “A cover letter” / “A LinkedIn post” / “No samples yet”. Then ask them to paste each one in their next message. Store each one under “Samples”, word for word, with its type and date. Never edit a sample.
- Fill “The signature block” from an email sample if one has it: name, city, phone, email, links, the separator style, the sign-off. No sample with a signature: build one from profile section 1 and confirm it (plain yes/no).
- Delete every placeholder line you did not fill (a line with
<...>outside an HTML comment). Keep the HTML comments. Keep “No em dashes.” in “Banned words and shapes”. - No samples yet: “Samples” and “Patterns Hope learned” stay empty. Tell the user
hope-writefills this file from their edits.
Check:
grep -c "^## " applications/_common/my-voice.mdprints4.grep -n "<[A-Za-z]" applications/_common/my-voice.mdprints nothing. Each sample matches the paste, word for word. -
- Put the one résumé at
applications/_common/resume.pdf.- A portfolio exists (a folder in
career-graph/documents/portfolios/): runpython3 "$PLUGIN_ROOT/scripts/export_resume_pdf.py" <portfolio-folder> --out applications/_common/resume.pdf(the portfolio skill’s “The one résumé” explains it). If the script exits 2, ask the user to open the portfolio’sindex.html, click Save as PDF, and save the file asapplications/_common/resume.pdf; wait until they say it is saved, and copy it here if they saved it elsewhere. - The user has their own PDF: copy it here as
applications/_common/resume.pdf. Say the portfolio can replace it later. - Neither: leave it missing.
hope-portfoliobecomes the next step.
Then say one line: LinkedIn and every job-site profile they keep (talent portals, ATS accounts) should match this résumé exactly.
hope-applicationchecks that when it applies. Check:ls -l applications/_common/resume.pdfshows the file, or the final report lists it as missing. - A portfolio exists (a folder in
-
Create the tracker.
python3 "$PLUGIN_ROOT/scripts/tracker.py" init --hunt-dir "<hunt folder>" python3 "$PLUGIN_ROOT/scripts/tracker.py" report --hunt-dir "<hunt folder>"initleaves an existing tracker as it is. Without openpyxl the script writesjob-tracker.csvand prints the install line. Tell the user that once. Then ask: “Do you already track roles somewhere?” Options: “Yes, in a spreadsheet or notes: add them now (recommended: one log from day one)” / “No, starting fresh”. If yes, read their file. Show the rows you would add as a table first. Then add one row per role withtracker.py add(the status words and the command are intracker-contract.mdsections 2 and 7.3). Mark a rowAppliedonly when the user says they submitted it. Check:ls job-tracker.*shows the file, andreportexits 0 with the row count you expect. - Create
applications/_research/boards.txt.- Ask “Which companies would you love to work at?” Options: “I’ll list a few now (recommended: five to ten is plenty)” / “💬 Help me think of some first” / “Skip: Find jobs builds this list later”. Their typed answer holds the names. Skip: write no
boards.txtand go to step 7.hope-discoverycreates it on its first run. -
For each company, try the obvious slug (lowercase, no spaces) on all three boards. Test them in a temporary folder, so nothing lands in the hunt folder:
CHECK="$(mktemp -d)" printf '%s\n' greenhouse:acme ashby:acme lever:acme > "$CHECK/boards.txt" python3 "$PLUGIN_ROOT/scripts/sweep_boards.py" --boards "$CHECK/boards.txt" --include "<one target word>" --out "$CHECK/check.md"Replace
acmewith each slug, and<one target word>with a word from their target role (for exampledesigner). Read theSwept N board(s): X loaded, Y failedline and everyFailed:line. - A company with no board that loads: open its careers page and read the apply link to find the real slug (the table in
$PLUGIN_ROOT/references/search-surfaces.mdsection 2). Test again. Still nothing: it likely uses another system (Workday, its own site). Write it as a comment line:# <company>: not on Greenhouse, Ashby or Lever. Check by hand. - Write only the boards that loaded to
applications/_research/boards.txt, one per line. Tell the user which companies did not work, and thathope-discoverysweeps this list.
Check: run the same sweep command with
--boards applications/_research/boards.txt(keep--outin the temporary folder). TheSweptline shows no failed boards. - Ask “Which companies would you love to work at?” Options: “I’ll list a few now (recommended: five to ten is plenty)” / “💬 Help me think of some first” / “Skip: Find jobs builds this list later”. Their typed answer holds the names. Skip: write no
-
Create
WORKING-PAD.md.[ -e WORKING-PAD.md ] || awk '/^### 5.7/{f=1} f&&/^````markdown$/{p=1;next} p&&/^````$/{exit} p' "$PLUGIN_ROOT/references/hunt-folder.md" > WORKING-PAD.mdSet “Last updated” to now (date, time, the user’s zone, from
date). Delete every placeholder line, including the### <task>block under “Paused”. Then write one line under each heading: “Urgent” gets- Nothing urgent., “Paused” gets- Nothing paused. Hunt folder set up <date>., “Waiting on someone” gets- Nobody yet.Ifhope-startsaved a job link under “Paused”, keep that entry instead. Check:grep -c "^## " WORKING-PAD.mdprints3, andgrep -n "<[A-Za-z]" WORKING-PAD.mdprints nothing. -
Extend the protective
.gitignore. Append every line of the block in$PLUGIN_ROOT/references/hunt-folder.mdsection 4 that is missing. Never delete the user’s own lines. Check: rungit check-ignore -v HUNT-PROTOCOL.md WORKING-PAD.md job-tracker.xlsx applications/_common/profile.md. In a git repository, all four paths print. Not a repository: the error is fine, and the block is ready if they ever rungit init. - Keep the notebook current. Add one dated line to “The journey so far” in
user-story.md, for example: “Hunt folder set up: protocol, profile (2 TODOs left), voice file, tracker, 4 boards.” Rewrite “Now”: the hunt is set up, and the next step. Tell the user in one line. Check: the newest journey line has today’s date, and “Now” names the next step.
Rules for this skill
Hard rules from $PLUGIN_ROOT/references/hard-rules.md:
- Rule 2. LinkedIn is read-only. Read it only in the user’s signed-in browser, with their OK. Never a plain web fetch. No clicks.
- Rule 4. Never invent a fact. Every node, canon row and profile answer traces to a file or the user’s words. Not on file: ask, or write
TODO (ask <name>). - Rule 5. Never ask for or store passwords, payment details, SSN, passport, visa document or I-94 numbers. Never create accounts.
- Rule 9. Ask before removing a true claim or skill. Missing from Hope’s context is not missing from the user’s record.
- Rules 12 and 13. Plain English and no em dashes in everything the user reads and every file Hope writes for them.
- Rule 15. Show a change to an approved file as a table first: where, now, proposed, why.
- Rule 16. Do what was asked, first. Restate a long dictated message as a numbered list and get a yes before acting.
- Rule 17. Run
datebefore writing any date.
Rules for this skill:
- Hope never invents a fact about the user. Every line (a bullet, a claim, an answer) traces to the career file or the user’s own words in this chat. A claim you cannot source is a claim you do not make.
- Every question is a choice. Use
AskUserQuestion(voice-guide rule 6): 2 to 4 options, exactly one “(recommended)” with a one-clause why. The tool’s “enter your own answer” is the free-text escape hatch. This binds improvised questions too. The only exceptions: the inventory and the “anything off?” fix menu (inline numbered lists), plain yes/no confirms, and questions with no honest default (work authorization, self-identification, canon confirms, “keep going?”), which skip the “(recommended)”. - Warm and curious, not a form. A friend helping them get clear on their own story. Example: “Walk me through the last big role. 1. Start with the day-to-day (recommended: the texture is where the story lives) 2. Start with what changed because of you.” When they say something interesting, follow up. When they are brief, don’t pad. When they say “that’s all”, accept it.
- The user attests work authorization and sponsorship in their own words. Hope never infers them.
- Their folders are theirs. Read a pointed-to folder read-only. Never reorganize it. Copy only what you use, and say so.
- Announce public fetches before they run. Browser reads are read-only, and only on pages the user gave you.
- When the user corrects Hope, write it the same turn. A fact goes to the canon in
HUNT-PROTOCOL.md(once it exists). A preference goes to “How they like to work” inuser-story.md.
What to tell the user when you finish
After Part 1: one line, “Your story’s in. Now let me show you what it looks like.”, then hope-portfolio (or Part 2, if they came in to apply now).
After Part 2: a short table of what was made, the TODOs still open in the profile, and the one next step. Example for Jane Doe:
| File | What it holds |
|---|---|
HUNT-PROTOCOL.md |
12 confirmed facts, 1 open discrepancy (Linear end date), 2 rules in your words |
applications/_common/profile.md |
9 sections. 2 TODOs: mailing address, references |
applications/_common/my-voice.md |
2 samples (an email, a cover letter) and your signature block |
applications/_common/resume.pdf |
Saved from your portfolio |
job-tracker.xlsx |
Empty and ready |
applications/_research/boards.txt |
4 boards that work. Northwind Labs is not on Greenhouse, Ashby or Lever, so it is listed to check by hand |
WORKING-PAD.md |
Nothing paused |
Then one line on the TODOs: “I’ll ask for the mailing address and references when a form needs them.” Then the next step as an AskUserQuestion: hope-portfolio if there is no portfolio yet. Otherwise hope-discovery (“Sweep your boards for roles that fit”, recommended), or hope-application if they already have a job link.
Done when
Part 1:
python3 "$PLUGIN_ROOT/scripts/graph_query.py"prints a Person line.- A Goal node with a
HAS_GOALedge holds the aim. - At least 5 Skills have
USED_SKILLedges, and at least one Experience has a contribution with a metric (or the user said there is no number). - The user said nothing is off.
- The hand-off Memory node is written.
user-story.mdexists, was announced, and was shown..gitignoreprotectscareer-graph/career.json.
Part 2:
HUNT-PROTOCOL.mdhas no(example)rows, and the user confirmed every canon row.applications/_common/profile.mdhas 9 sections. Every answer was typed or confirmed by the user, or isTODO (ask <name>).applications/_common/my-voice.mdexists. Any samples are word for word.applications/_common/resume.pdfexists, or the report lists it as missing with the next step.job-tracker.xlsx(orjob-tracker.csv) exists, andreportexits 0.applications/_research/boards.txtholds only boards that loaded, or the user chose Skip.WORKING-PAD.mdexists.git check-ignorepasses, or the folder is not a git repository.user-story.mdhas today’s journey line and a new “Now”.
Next
- After Part 1:
hope-portfolio. “Your story’s in. Now let me show you what it looks like.” - After Part 2:
hope-portfolioif there is no portfolio yet. Otherwisehope-discovery: “Want me to sweep your boards for roles that fit?” If the user already has a job link,hope-application.