Skip to content

Repository files navigation

dossier

Agent pipeline that scrapes 13 job boards plus your ICP companies' ATS portals (Greenhouse / Ashby / Lever), scores postings against your skills, finds hiring managers, and drafts personalized pitches. Anti-mass-apply.

Quick start

Requires the Claude Code terminal CLI. The pipeline is driven by the lead-0 agent, which can only be launched as the primary agent from the CLI (claude --agent lead-0). It cannot be started from the Claude Desktop app or claude.ai/code. See Claude Desktop & claude.ai below.

git clone https://github.com/0xQuinto/dossier.git
cd dossier
claude --agent lead-0

That's it. On first run, lead-0 detects missing setup and walks you through everything:

  • Installing prerequisites (Python 3.12+, git, Homebrew, Node.js 20+)
  • Setting up the virtual environment and dependencies
  • Installing Playwright + Chromium for CV PDF rendering
  • Configuring the EXA_API_KEY credential for contact research
  • Building your skills inventory and resume from your existing materials (CV, portfolio, GitHub, LinkedIn)

Manual alternative. python3 setup_wizard.py handles venv + deps + the EXA_API_KEY credential (exported to your shell profile) without the profile builder. (On Windows, if bare python opens the Microsoft Store, use the real interpreter; see Development.)

Claude Desktop & claude.ai

This pipeline runs only in the Claude Code terminal CLI. Both the Desktop app and claude.ai/code load this repo's .claude/ config (CLAUDE.md, settings, MCP servers, skills, and the agent files themselves), but neither lets you launch a custom agent as the main thread. There is no --agent equivalent or agent picker. Because lead-0 orchestrates by spawning subagents (scout-1, ranker-7, …) and a custom agent can only be made the main thread via the CLI, the orchestrator can't be started on those surfaces. The same applies to the on-demand agents (letter-5, pdf-9, applier-2, filler-10); they're custom agents too.

Surface Reads .claude/ config Launch lead-0 / on-demand agents Run the pipeline
Terminal CLI claude --agent <name>
Claude Desktop (local) ❌ no agent launcher ❌ use the CLI
claude.ai/code (cloud) ✅ (cloned in) ❌ no agent launcher ❌ use the CLI
  • Claude Desktop is a full local Claude Code engine (runs bash, edits files, shares config with the CLI), but it has no UI to make lead-0 the primary agent. Run the pipeline from a terminal instead. The raw scraper (board-aggregator) still works in any shell.
  • claude.ai/code cloud sessions can be started from the CLI with claude --remote "<task>" (push your commits first, since it clones from GitHub), but --remote cannot be combined with --agent, so it can't drive lead-0. Cloud sessions are fine for other repo tasks, just not this pipeline.

Docs: sub-agents (CLI-only) · Claude Code on the web · Desktop

How the pipeline works

Phase 1 — Scrape       scout-1 runs board-aggregator CLI across 13 boards + ATS portal scan of your ICP companies
Phase 2 — Rank         ranker-7 scores each posting against your skills inventory
Phase 3 — Research     recon-3 finds hiring managers via Exa (parallel per company)
Phase 4 — Pitch        (optional) scripter-11 drafts the video pitch, then composer-4 produces DM drafts + STAR+R stories — skipped by default, offered after the other phases finish

The pipeline orchestrator (lead-0) runs phases sequentially. Phase 3 spawns one subagent per company in parallel. Phase 4 is optional, skipped by default and offered once the other phases finish.

Two scrape sources, one merged feed:

  • Generic boards. 13 public boards (Indeed, LinkedIn, RemoteOK, Himalayas, HN, crypto/web3 boards, 80,000 Hours, …). Wide net, noisy.
  • Per-company ATS portals. Direct hits to Greenhouse / Ashby / Lever public APIs for the companies in portals.yml. Narrow, high-signal, no auth needed. Scout-1 marks portals inactive after 30 days with no openings; discoverer-6 adds new ones.

Portal discovery. If portals.yml is missing or has no active companies, lead-0 offers to run discoverer-6 to auto-discover companies matching your skills-inventory and populate it before Phase 1. You can also run discoverer-6 standalone anytime to expand the list.

Each run writes to a timestamped directory under research/runs/. The most recent run is symlinked at research/latest/.

On-demand agents (outside the pipeline):

  • applier-2 generates copy-paste answers for application forms (human-in-the-loop)
  • letter-5 generates ATS cover letters (keyword injection + SOAR proof points)
  • pdf-9 generates tailored ATS PDF CVs (keyword injection + bullet reordering)
  • filler-10 submits via API for Lever/Ashby and delegates other ATSes to applier-2 for manual submission (human-in-the-loop)

Utilities:

  • scripts/tracker.py is the application status tracker CLI (add, update, import-run, dedup, show)
  • dashboard/ is a Go TUI for browsing applications (Bubble Tea + Lipgloss)
  • scripts/generate-pdf.mjs renders the ATS PDF via Playwright

Hiring Without Whiteboards signal

Every posting is checked against poteto/hiring-without-whiteboards (MIT), a community-maintained list of companies that run real-work interviews instead of whiteboard/LeetCode-style trivia. A match sets hww_listed: true on the posting and carries the list's own process note (hww_process) into the CSV, markdown, and compact index output. ranker-7 treats a match as a tie-breaker bonus, not a scoring dimension.

The list is cached at ~/.cache/board-aggregator/hww-readme.md and refetched after 7 days; pass --no-hww to skip the lookup entirely (no network call, no cache write).

Pass --hww-only to keep only postings whose company matched the list, dropping every other posting from the run's output. It requires --hww (the default) and errors if combined with --no-hww. Coverage caveat. --hww-only filters what the 13 boards + portal scanner already returned; it does not scrape the listed companies' own careers pages, so an HWW company that never posts on those boards will not appear even with the filter on.

Provenance caveat. The list is community-sourced and not independently verified by dossier. hww_listed is a lead worth weighing, not a verified claim about a company's actual interview process. Treat hww_process as a note to confirm, not a guarantee.

Seeded discovery. --hww-pool exports the list as JSON (name, url, location, process, remote) instead of scraping, honoring --remote-only/--include-onsite the same way the scrape path does. discoverer-6 can use that pool as its candidate list instead of an Exa name-discovery run, so Exa spend goes only toward validating each candidate's ATS board, not finding names; see its "HWW-seeded mode" in .claude/agents/discoverer-6.md. The budget is the same config.max_discovery_calls cap either way.

Architecture

graph TB
    subgraph Pipeline["Claude Agent Pipeline"]
        Lead[lead-0<br/>Orchestrator]
        Primer[primer-8<br/>Onboarding]
        Scout[scout-1<br/>Scrape]
        Ranker[ranker-7<br/>Rank]
        Recon[recon-3<br/>Contacts]
        Scripter[scripter-11<br/>Video Script]
        Composer[composer-4<br/>DMs + Stories]
        Discoverer[discoverer-6<br/>Discovery]
        Applier[applier-2<br/>Forms]
        Letter[letter-5<br/>Cover Letter]
        PDF[pdf-9<br/>ATS PDF]
        Filler[filler-10<br/>ATS Submit]
    end

    subgraph Scraper["board-aggregator CLI"]
        CLI[Click CLI]
        Scrapers["13 scrapers<br/>(generic boards)"]
        PortalScanner["portal_scanner<br/>Greenhouse / Ashby / Lever"]
        PortalsYml[("portals.yml<br/>ICP companies")]
    end

    Lead -->|"foreground (if needed)"| Primer
    Lead -->|foreground| Scout
    Lead -->|foreground| Ranker
    Lead -->|"background ×N companies"| Recon
    Lead -.->|"optional, per company"| Scripter
    Lead -.->|"optional, per company"| Composer
    Lead -->|"foreground (if portals empty)"| Discoverer
    Lead -.->|on-demand| Applier
    Lead -.->|on-demand| PDF
    Discoverer -->|writes| PortalsYml
    Scout --> CLI
    CLI --> Scrapers
    CLI --> PortalScanner
    PortalScanner --> PortalsYml
Loading

Adding a scraper

  1. Create board_aggregator/scrapers/your_board.py
  2. Subclass BaseScraper and implement scrape()
  3. Decorate with @register
  4. Import in board_aggregator/cli.py
  5. Add a test with a fixture in tests/

See board_aggregator/scrapers/remoteok.py for a minimal example.

Development

git clone https://github.com/0xQuinto/dossier.git
cd dossier
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest

Windows note: bare python often resolves to the Microsoft Store stub, which exits with code 49 and prints "Python was not found" instead of running. Install real Python 3.12+ (winget install Python.Python.3.12 or python.org), create the venv with it, and call the venv interpreter by path (.venv\Scripts\python.exe). Set PYTHONUTF8=1 to avoid cp1252 mojibake in localized (non-English) Windows shells.

License

MIT. See LICENSE.

About

Agent pipeline that scrapes 13 job boards + your ICP companies' ATS portals (Greenhouse/Ashby/Lever), scores postings, finds hiring managers, and drafts personalized pitches. Anti-mass-apply.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages