setup-searches
Skill4 starsChanged 10 days agoMITView on GitHub
Build and maintain source config from candidate targeting through `careerrat searches` — generate a baseline from role buckets, curate enabled sources, add or import individual searches (including pasted board URLs with embedded filters preserved), and tune global filters. Upstream of search-jobs; does not scan.
In this repository31 other files it gives its agents.
- AGENTS.mdAGENTS.md
- templates/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- templates/CLAUDE.mdCLAUDE.md
- answer-questionSkill
- apply-jobSkill
- calendar-syncSkill
- coach-gapsSkill
- company-healthSkill
- configureSkill
- discover-companiesSkill
- email-commsSkill
- evaluate-jobSkill
- ingest-mailSkill
- ingest-messagesSkill
- ingest-profileSkill
- intake-extractSkill
- interview-prepSkill
- optimize-linkedinSkill
- reevaluate-strategySkill
- relationship-sourcingSkill
- report-issueSkill
- research-boardsSkill
- research-companySkill
- research-compSkill
- resume-extractSkill
- schedule-meetingSkill
- search-jobsSkill
- sync-statusSkill
- tailor-applicationSkill
- track-outcomesSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
25 rules. About 0 are common, 9 are distinctive, and 16 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈9
Distinctive · estimate
This author's own choices. Worth a look.
16
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 12
Run careerrat doctor and inspect the output.
- Very specific: line 14
If candidate profile/targeting config is missing or fails schema, halt.
- Very specific: line 15
If candidate targeting exists but role_buckets is empty or absent: halt.
- Very specific: line 16
If candidate profile + targeting pass and role_buckets is non-empty: proceed to STEP 1.
- Distinctive: line 20
Read candidate targeting config through the shared DB-first accessor and report back the detected values that will drive generation:
- Distinctive: line 26
Read candidate profile config through the shared DB-first accessor and report:
- Very specific: line 42
If the command emits warnings (empty role_buckets, no aggregator found for domain, missing schema field): surface them verbatim to the user.
- Distinctive: line 87
Do not assume HiringCafe is the only importable provider.
- Very specific: line 102
Use careerrat searches to get current indices before enabling/disabling by index.
- Very specific: line 128
After tuning, run careerrat doctor to confirm the schema validates.
- Very specific: line 130
Use careerrat searches to review the current state before finalizing.
- Distinctive: line 134
Verify the auto-selected aggregator and board set is appropriate for the candidate's domain:
- Very specific: line 136
If the candidate is not in the domain that matches the aggregator (e.g.
- Distinctive: line 137
If the user mentions a board or aggregator they always want included: add it now, and apply the gate write-back below.
- Very specific: line 150
Read the ## Curated Board Registry table in docs/SOURCES.md.
- Very specific: line 157
Verify support with careerrat searches --providers --json.
- Distinctive: line 174
Wait for explicit confirmation.
- Distinctive: line 183
If the candidate's domain has no matching registry boards beyond the general aggregators (which are already auto-generated), say so …
- Distinctive: line 200
If the user stated a new preference during this session that should survive future regenerations:
- Very specific: line 206
Do not write board preferences to candidate/targeting.yml or candidate/profile.yml — those files govern targeting and identity, not source …
- Distinctive: line 233
When source config is ready, continue the post-onboarding discovery pipeline in this exact order:
- Very specific: line 270
Never fabricate sources or filters: Only add entries the user explicitly requested or that --from-targeting derives from real targeting …
- Very specific: line 271
Preserve embedded filters: when importing a pasted URL.
- Very specific: line 272
Salary floor is
compensation.minimum_base: Never read or surface current_base — it is private and must not appear in any output or log. - Very specific: line 274
Domain-general: No board name, aggregator, or provider is hardcoded as canonical in this skill's prose.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
setup-searches
Runs under AGENTS.md. These contracts bind without being restated here: Privacy Invariant (
current_basenever outbound), Honesty Firewall, Placeholder/Bracket Ban, Gate Write-back, Domain-Neutral Rule, Browser Automation Contract, Activity Pulse logging, Tracker verify+snapshot, and Sent-Clears-Draft. Inline reminders at point-of-use are intentional; standalone restatements point back to the relevant AGENTS.md section. Barecandidate/,workspace/,config/, and.internal/paths below are symbolic; resolve them per AGENTS.md's Path Resolution rule.
STEP 0 — Preflight
Run careerrat doctor and inspect the output.
- If candidate profile/targeting config is missing or fails schema, halt. Instruct the user to run
ingest-profile(careerrat ingest) first, then return here. In DB workspaces, read this through the shared DB-first config accessor; YAML is legacy fallback only. - If candidate targeting exists but
role_bucketsis empty or absent: halt. The baseline generator will produce only a stub with no role-specific searches — a search catalog with no titles is useless. Tell the user to populaterole_bucketsthrough onboarding/ingest-profilebefore continuing. - If candidate profile + targeting pass and
role_bucketsis non-empty: proceed to STEP 1.
STEP 1 — Read targeting and profile
Read candidate targeting config through the shared DB-first accessor and report back the detected values that will drive generation:
role_buckets— names, titles per bucket, priority flagskeep_signals,cut_signals— these becometitle_filter.positive/title_filter.negative; note ifcut_signalsis empty (hardcoded Intern/Junior fallback will apply per Foundation C)excluded_companies— will be noted but does not affect search-source generation
Read candidate profile config through the shared DB-first accessor and report:
candidate.domain— drives board/aggregator selection (e.g. "software engineering" → tech aggregator + job board; other domains → domain-appropriate boards, or no aggregator if none configured). Echo back detected domain so the user can correct before generation.compensation.minimum_base— this is the value used forsalary_filter.min. Do not read or surfacecurrent_base— it is private and must not appear in any output.location.remote,location.home,location.relocation— these feedlocation_filter
Echo a summary to the user: detected domain, board catalog that will be used, minimum_base as the salary floor, and number of titles across all role buckets. Ask the user to correct anything before proceeding.
STEP 2 — Generate baseline
careerrat searches --from-targetingIdempotency: a search is added only when no existing entry matches provider + query (case-insensitive). Existing manual entries are preserved. If the user runs this on an already-populated config, confirm that only new titles will be appended and nothing will be overwritten.
If the command emits warnings (empty role_buckets, no aggregator found for domain, missing schema field): surface them verbatim to the user.
Note the aggregator entry behavior: if profile.candidate.domain maps to a known aggregator, one RSS source is generated for it. If no domain-appropriate aggregator is configured, the generator omits the aggregator entry entirely rather than emitting a nonsensical one. If the user is in a non-tech domain and sees an unexpected tech aggregator entry, flag it in STEP 5.
STEP 3 — Curate sources
Perform any curation the user requested (or all of (a)–(d) on initial setup):
(a) Add keyword searches — one per title or per explicit user request:
careerrat searches --add-query "<title or keyword>" [--label "<l>"]This is the HiringCafe query builder. To add a deterministic Career Ops adapter,
inspect careerrat searches --providers, then use one of these instead:
careerrat searches --add-provider "<provider>" --query "<title or keyword>" [--label "<label>"]
careerrat searches --add-provider "<provider>" --url "<branded board URL>" [--label "<label>"]Public boards that need no key and work for any field: remotive, remoteok, workingnomads, himalayas, jobicy, arbeitnow, and themuse (paged, so add it by hand with a query). hackernews reads the monthly "Who is hiring" thread and suits tech roles. Keyed sources read a key from the environment (USAJobs is free; Adzuna is paid after 25 trial calls):
careerrat searches --add-provider "usajobs" --query "<title or keyword>" [--location "<place>"]
careerrat searches --add-provider "adzuna" --query "<title or keyword>" --country "<us|gb|ca|au|de|fr|...>" [--location "<place>"]careerrat searches --from-targeting seeds them only when the key is already set. careerrat searches --providers shows which keys are set and where to sign up. A keyed source with no key fails loudly in the scan summary; it never returns an empty list quietly.
(b) Import a pasted board URL — when the user pastes a URL from any job board:
careerrat searches --add-url "<full URL>" [--label "<label>"]For hiring.cafe URLs: the embedded searchState and query-string filters are parsed and written into the searchState block verbatim. Do not strip, normalize, or drop query params.
For wellfound.com URLs: routed to provider Wellfound, source_type: browser (Wellfound is a SPA — agent must use a browser tool for liveness checks and browsing).
For jobs.lever.co or api.lever.co URLs: routed to provider Lever, source_type: ats; the company slug is derived from the URL path automatically.
For any URL recognized by the pinned Career Ops registry: routed to its deterministic provider with source_type: ats.
For an unrecognized branded host whose adapter is known: use --add-provider <id> --url <url> instead of importing it as a browser source.
For other hosts: the entry becomes source_type: browser.
A company board URL on a supported ATS (Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Workday and the rest of the registry) always becomes a direct ats source, even when a caller asked for a browser source. Browser sources and login-backed sites (LinkedIn, Indeed, Glassdoor, Wellfound) can't be searched from the terminal, so when one of them lists an employer, look for that employer's own ATS board and add it with --add-url or --add-provider <id> --url <board URL> instead.
Do not assume HiringCafe is the only importable provider. Any board URL a user pastes can be imported — label it clearly.
(b.1) Authenticated browser sources (LinkedIn / Indeed / Glassdoor)
When the user pastes a search or results URL from LinkedIn, Indeed, or Glassdoor, --add-url creates a browser source bound to that site. Ask one question in the current conversation: “Do you want to log into LinkedIn so I can use it?” with Yes and No choices. Yes enables that source and opens its exact URL in the visible CareerRat browser. No leaves that source disabled and continues with every other source. Do not send the user to Settings or require a capability, platform, consent, or terms-of-service switch matrix.
CareerRat never stores the password. The browser session holds the login. Stop for CAPTCHA, 2FA, or an unexpected account-selection screen so the user can handle it visibly, then resume the same source.
(c) Enable / disable entries:
careerrat searches --enable <index or label>
careerrat searches --disable <index or label>Use careerrat searches to get current indices before enabling/disabling by index.
(d) Surface disabled entries. List intentionally disabled sources with careerrat searches. When the user wants one, ask the site-specific Yes/No login question in the current conversation.
STEP 4 — Tune global filters
Review the generated filters and adjust as needed:
title_filter.positive— must include all titles fromrole_buckets. If a bucket title is missing, add it.title_filter.negative— must reflecttargeting.cut_signals. Ifcut_signalsis populated, these values override the hardcoded['Intern', 'Junior']defaults. Ifcut_signalsis empty, the Intern/Junior defaults apply — confirm with the user this is correct for their seniority posture.salary_filter.min— must be set tocompensation.minimum_basefromprofile.yml. Verify this is present and matches.location_filter.allow/location_filter.block— must cover the candidate'slocation.remoteposture and any excluded regions fromprofile.yml.recency.modeandrecency.safetyMinutes— each search entry carries arecencyblock. The three valid modes are:since-last-run(default) — usesrecency.lastRunAtwatermark; setrecency.safetyMinutes(default 30) to overlap slightly and avoid missing results at the boundary.fixed-hours— always looks back a fixed window (recency.windowHours); use when a source does not support watermark-based deltas.manual— no automatic date filter; the agent applies no recency constraint (use for sources with their own pagination).
To tune: use the owning source-config command when available. Do not hand-edit exported source YAML in DB workspaces. If no DB-aware command exists for recency yet, stop and report the helper gap rather than editing
config/search-sources.yml. In legacy workspaces only, edit therecencyblock directly inconfig/search-sources.ymlfor the relevant entry. Example for a 7-day lookback on a fixed-hours source:recency: mode: fixed-hours windowHours: 168 safetyMinutes: 60After tuning, run
careerrat doctorto confirm the schema validates.
Use careerrat searches to review the current state before finalizing.
STEP 5 — Review aggregator and board catalog
Verify the auto-selected aggregator and board set is appropriate for the candidate's domain:
- If the candidate is not in the domain that matches the aggregator (e.g. a trucking candidate with a tech RSS feed), disable or replace the aggregator entry via
careerrat searches --disable <index>and add domain-appropriate boards via--add-urlor--add-provider. - If the user mentions a board or aggregator they always want included: add it now, and apply the gate write-back below.
Auto-seeded portals (review these):
- Wellfound (
wellfound.com) — tech-domain candidates only; one entry per primary role title,source_type: browser. If the candidate is not in a tech-adjacent domain, disable these entries. - Lever (
jobs.lever.co) — domain-neutral ATS; one entry per company intargeting.tracked_companies,source_type: ats. Verify each company slug matches the company's actual Lever subdomain — a wrong slug returns an empty result set (HTTP 200, no postings), not a 404.
STEP 5a — Optional: domain-gated starter menu from the board registry (initial setup only)
On initial setup, offer the user a one-time starter menu from the docs/SOURCES.md
Curated Board Registry. This step is optional — skip it if the user declines or if
source config already has more than the auto-generated baseline entries.
- Read the
## Curated Board Registrytable indocs/SOURCES.md. - Filter to rows where Domain tag includes
generalOR matchesprofile.candidate.domain(e.g. a candidate with domain "software engineering" seesgeneral+tech/software+tech/AI+remoteentries; a candidate with domain "finance" sees onlygeneralentries and gets a note that no domain-specific vetted boards exist yet for that domain). - Exclude rows already in the dedup set (any board whose root domain already appears in source config).
- Verify support with
careerrat searches --providers --json. Exclude any row that is not implemented; never infer support from prose alone. Present the filtered list as a pick-list:
Board registry matches for domain "<candidate.domain>": [1] HiringCafe (general / aggregator / high confidence) — already configured, skipped [2] Wellfound (tech/software / aggregator / high confidence) — already configured, skipped [3] Remote Vibe Coding Jobs (tech/software, remote / aggregator / high confidence) — already configured, skipped [4] Example Niche Board (your domain / niche-board / high confidence) — NEW [5] Example Specialist Aggregator (your domain / aggregator / high confidence) — NEW [6] Example Field Board (your domain / niche-board / borderline) — NEW (borderline: weak company attribution) Pick all, a subset by number, or none to skip.Wait for explicit confirmation. Do not add anything automatically. If the user picks boards, add each confirmed one via:
careerrat searches --add-url "<url>" --label "<label>"For niche boards with no canonical search URL yet, use
--add-provider "<provider>" --query "<role family keyword>"when the provider is implemented. Otherwise, note that the source needs an adapter and skip it.- If the candidate's domain has no matching registry boards beyond the general aggregators (which are already auto-generated), say so explicitly and do not prompt for picks.
This is a convenience starter menu — not a mandate. The auto-generated baseline from STEP 2 already includes the field-neutral defaults for the candidate's domain. This step adds domain-specific niche boards the candidate might want.
Known limitation — board-preference persistence: there is no canonical
source-preference document yet that makes per-candidate board preferences (e.g.
"always use this board", "never use LinkedIn") survive a future --from-targeting
regeneration. Comment-only state in exported source YAML is not durable, especially
in DB workspaces where the file is generated. Until a DB-backed helper ships,
explicitly warn the user after writing any persistent board preference, and prefer
encoding the intent as targeting keep/cut signals where possible.
STEP 6 — Gate write-back
If the user stated a new preference during this session that should survive future regenerations:
- "Never show me LinkedIn" or "exclude provider X" — confirm-first (consequential: affects every future scan). Once confirmed: disable the entry via
careerrat searches --disable <index>. Do not add comment-only state to exported source YAML in DB workspaces. Persist only supported source state throughcareerrat searches; until a DB-backed source-preference helper exists, warn that this preference may need to be re-applied after--from-targeting. - "Always use [board]" — confirm-first; add the entry via
careerrat searches. Do not add comment-only state to exported source YAML in DB workspaces. Persist only supported source state throughcareerrat searches; until a DB-backed source-preference helper exists, warn that this preference may need to be re-applied after--from-targeting. - Unambiguous, low-blast-radius preferences (one extra board the user just pasted) — write-and-report: add the entry via
--add-urlor--add-query, then echoAdded source: <label> (<provider>).
Do not write board preferences to candidate/targeting.yml or candidate/profile.yml — those files govern targeting and identity, not source mechanics.
STEP 7 — Verify
careerrat searchesConfirm for every entry:
provideris setlabelis human-readabletarget/query/url/rssUrlis present and non-emptyenabledis set intentionally (not accidentally true or false)
Then run:
careerrat doctorConfirm source config passes schema validation. If the CLI refused to write an invalid config, no errors should appear — but verify explicitly. If the doctor flags errors, fix them before handing off.
URL spot-check: For at least one url-query or rss entry, open the target or rssUrl value in a browser (or use WebFetch) and confirm it returns job results rather than a 404, redirect loop, or empty feed. If an entry resolves to an error page, disable it (careerrat searches --disable <index>) and report to the user before handing off.
Final handoff
When source config is ready, continue the post-onboarding discovery pipeline in this exact order:
setup-searches -> research-boards -> discover-companies -> search-jobsThis skill only produces the baseline source config. It does not discover new boards,
discover companies, scan, dedupe, gate, or score. Hand off next to research-boards
unless the user explicitly says to skip board discovery. After research-boards, run
discover-companies before the first search-jobs sweep so employer ATS boards are
wired into tracked-company source config through careerrat companies.
End every run by saying the next agent task plainly: research-boards next, or
careerrat next --skip research-boards --write if the user explicitly skipped board
discovery.
Intent → Command
| User intent | Command | |
| Generate baseline from targeting | careerrat searches --from-targeting | |
| See current searches | careerrat searches | |
| See current searches (JSON) | careerrat searches --json — emits { exists: bool, searches: [ { index, provider, label, target, enabled, recency? } ] } | |
| List deterministic providers | careerrat searches --providers | |
| Add a HiringCafe keyword search | careerrat searches --add-query "<query>" [--label "<label>"] | |
| Add a deterministic provider query or branded URL | `careerrat searches --add-provider "<id>" [--query "<query>" | --url "<url>"] [--label "<label>"]` |
| Import a pasted board URL | careerrat searches --add-url "<url>" [--label "<label>"] | |
| Enable a search | careerrat searches --enable <index or label> | |
| Disable a search | careerrat searches --disable <index or label> | |
| Health check | careerrat doctor | |
| Bail to onboarding | careerrat ingest |
Rules
- Never fabricate sources or filters. Only add entries the user explicitly requested or that
--from-targetingderives from real targeting data. - Preserve embedded filters when importing a pasted URL. The
searchStateblock must be written exactly as parsed from the URL — do not normalize, simplify, or drop query params. - Salary floor is
compensation.minimum_base. Never read or surfacecurrent_base— it is private and must not appear in any output or log. - Writes source config through CareerRat helpers; reads candidate config through DB-first accessors. In DB workspaces,
config/andcandidate/files are compatibility exports; never hand-edit them. Never commit candidate files. - Domain-general. No board name, aggregator, or provider is hardcoded as canonical in this skill's prose. Board selection follows
profile.candidate.domain. The skill must execute correctly for a trucking, nursing, or finance candidate. - Do not scan or gate here.
search-jobsowns discovery and intake.evaluate-jobis the fit gate.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

