@nextwebb/career-agent
v1.3.0
Published
Agentic job application workflow for Claude Code and Codex — generate tailored CVs and hand off ATS forms safely
Downloads
1,478
Maintainers
Readme
career-agent
Agentic job application workflow for Claude Code and Codex.
One command generates a tailored CV + cover letter PDF per role with deterministic quality gates. For browser workflows with enough platform evidence and safe field classification, the agent fills safe ATS fields, then hands off sensitive, consent, attestation, legal, and Submit controls to you.
Not a template engine. Not a job tracker. An agent-assisted workflow with deterministic handoff points.
Design philosophy: keep the workflow lightweight, keep career data local, and make generated application materials comprehensive enough for review without pretending to guarantee recruiter or ATS outcomes.
📖 Live Demo & Docs | ⭐ Star on GitHub
Public docs describe npm latest. For pinned installs, use the README and files shipped with that npm package version plus the changelog.

What it does
/setup-profile: Buildprofile.jsonfrom your CV or LinkedIn PDF, extract work history, generate 3 CV variants, and draft source-backed per-job bullets for review/source: Discover leads from available public/search sources, verify open roles on company-controlled pages, and rank them with a documented heuristic fit score/new-role: Scaffold a new role config interactively by scraping the JD/generate-cv: Build ATS-safe CV + cover letter PDFs tailored to the role, then run deterministic quality gates/apply: Open the job URL in a browser, fill safe fields only when the ATS case is understood, upload PDFs when safe, answer safe custom questions, then hand off to you for sensitive fields and Submit/track: View your application pipeline, update statuses, add notes
The agent never submits on your behalf. That boundary is intentional.
/source evidence and ranking rules are documented in docs/source-methodology.md.
Why this is different
| | career-agent | career-ops |
|---|---|---|
| Profile bootstrap from CV/LinkedIn | ✅ /setup-profile | ❌ manual markdown file |
| CV variant system (A/B/C by audience) | ✅ per-role | ❌ single template |
| Per-role cover letter PDF | ✅ | ✅ /cover |
| Browser form filling | ✅ guarded handoff with Greenhouse, Lever, Workable notes | ✅ /apply |
| ATS-aware single-column PDF | ✅ reportlab | ✅ HTML→PDF |
| Human-in-loop handoff | ✅ sensitive fields + Submit | ✅ |
| Profile data local + gitignored | ✅ | ✅ |
| npx setup check | ✅ | ✅ |
| Claude Code CLI + desktop | ✅ | ✅ + Gemini/OpenCode |
| Codex plugin metadata | ✅ | ❌ |
Testing & Quality
- CI/CD: GitHub Actions with focused checks on every PR
- Security: CodeQL + Trivy + bandit + safety scanning (daily + on push)
- Code Quality: Ruff linting + mypy type checking
- Tests: Smoke tests (structure/syntax) + integration tests (real PDF generation with synthetic non-PII fixtures)
- Python Support: 3.10, 3.11, 3.12
All checks must pass before merge. See ENGINEERING_PRINCIPLES.md for detailed standards.
Support matrix
| Workflow | Claude Code | Codex |
|---|---|---|
| Setup and doctor | ✅ supported | ✅ supported |
| Profile bootstrap | ✅ /setup-profile | ✅ $setup-profile or skill selector |
| Job sourcing | ✅ /source | ✅ $source or natural language |
| Role config | ✅ /new-role | ✅ $new-role or natural language |
| CV and cover letter PDFs | ✅ /generate-cv | ✅ $generate-cv or natural language |
| Pipeline tracking | ✅ /track | ✅ $track or natural language |
| ATS form filling | ✅ with Claude in Chrome | ⚠️ experimental; see Codex Chrome verification |
Codex support means the package includes .codex-plugin/plugin.json, Codex-compatible skill metadata, host-neutral skill instructions, and Codex-aware setup checks. It does not mean npx installs the plugin into Codex. How you make the plugin available in Codex depends on the Codex surface and configured plugin source.
Prerequisites
- Claude Code CLI or Codex CLI/app
- Python 3.10+ with
reportlabandpypdf(pip install -r requirements.txt) - Node 18+ for the
npxsetup and doctor commands - Browser automation for
/apply:- Claude Code: Claude in Chrome extension
- Codex: Browser for public pages, Chrome for signed-in browser state; see ATS platform support notes
Install
Setup check
# Check Python 3.10+, PDF dependencies, Claude/Codex host availability, and create profile.json
npx @nextwebb/career-agentRun a health check without creating profile.json:
npx @nextwebb/career-agent doctorClaude Code plugin install
claude plugin marketplace add nextwebb/career-agent
claude plugin install career-agentCodex setup
npx @nextwebb/career-agent checks local prerequisites and creates local starter files. It does not install the Codex plugin.
Install the Codex plugin from this repository's marketplace:
codex plugin marketplace add nextwebb/career-agent
codex plugin add career-agent@career-agentThe Claude marketplace commands above are Claude Code setup only.
Then bootstrap your profile:
/setup-profile # Claude Code alias
$setup-profile # Codex skill invocation
/source Germany backend # Find and verify matching role leads
/new-role # Create role config
/generate-cv <role_id> # Generate PDFs
/apply <role_id> # Browser form handoff
/track # View pipelineProfile setup
The fastest way is to let the agent build it for you:
/setup-profile # Upload or paste your CV/LinkedIn PDFThe agent extracts your work history, infers three CV variants (AI/LLM, Data Platform, Backend), and writes one default bullet set plus three audience-specific variants, ready for /generate-cv or $generate-cv immediately.
Or create it manually: profile.json (gitignored: never committed) holds your personal data:
{
"name": { "first": "Jane", "last": "Doe" },
"email": "[email protected]",
"phone": { "country_code": "+1", "number": "5551234567" },
"location": "Berlin, Germany",
"relocation": "Open to EU/UK relocation with visa sponsorship",
"links": {
"linkedin": "https://www.linkedin.com/in/janedoe/",
"github": "https://github.com/janedoe",
"website": "https://janedoe.dev",
"twitter": "https://x.com/janedoe"
},
"headline": "Senior Software Engineer: Python · Distributed Systems · AI",
"summary": "7+ years building production Python systems..."
}See profile.example.json for the full schema including variants, impact_statements, and per-job bullet sets.
Role config
Each role lives in roles/<role_id>.json (gitignored):
{
"role_id": "stripe_backend_2026",
"company": "Stripe",
"title": "Senior Backend Engineer",
"url": "https://stripe.com/jobs/listing/...",
"ats_platform": "greenhouse",
"variant": "C",
"cover_letter": {
"paragraphs": [
"Stripe's payment infrastructure serves...",
"My background in distributed systems...",
"...",
"I would welcome a conversation..."
]
},
"custom_answers": {
"why_company": "...",
"hear_about_us": "LinkedIn"
}
}See roles.example/example_role.json for the full schema including CV bullet overrides.
CV variants
Define named variants in profile.json under "variants". Each variant emphasises a different slice of your experience:
- A: AI/LLM/Evaluation focused
- B: Data Platform/Pipelines focused
- C: Senior Backend/APIs focused
The role config picks a variant. The CV builder selects the matching experience ordering and impact statements.
ATS platform support notes
These are implementation notes for supported ATS patterns, not a guarantee that every live form variant will work. Verify each form before filling, and stop on unsupported ATS pages, login walls, CAPTCHA, ambiguous consent, or hidden fields that cannot be classified.
Codex Chrome /apply is not stable by assumption. Use the Codex Chrome verification matrix to decide whether a platform has non-submitting evidence for a Codex run. As of 2026-06-18, no live Codex Chrome ATS tests are committed in this repository, so all named ATS rows below are experimental for Codex Chrome. Failed, ambiguous, or unverified platforms should use manual fallback and handoff.
| Platform | General behavior | Codex Chrome status |
|---|---|---|
| Greenhouse (direct) | Fill safe fields, upload resume, answer safe custom questions | Experimental until a non-submitted evidence record exists |
| Greenhouse (iframe embed) | Use the embed URL as a top-level page, not a company iframe | Experimental until a non-submitted evidence record exists |
| Greenhouse (EU domain) | Keep ats_platform normalized to greenhouse unless a separate supported value is intentionally added and tested | Experimental until EU URL/domain handling is verified |
| Lever | Upload resume, paste cover-letter text when a field exists, answer safe custom questions | Experimental until a non-submitted evidence record exists |
| Workable | Use /apply/ URL, upload resume, handle dropdowns and multi-step forms carefully | Experimental until a non-submitted evidence record exists |
| Unknown/unsupported ATS | Stop and provide manual guidance | Unsupported for automation |
| More | PRs welcome | Experimental until verified |
Human-in-the-loop handoff
The agent fills safe fields it can verify from your profile and the role config. It does not:
- Click Submit
- Fill EEO/voluntary self-identification fields (gender, race, ethnicity, veteran status, disability)
- Enter passwords or credentials
- Enter national IDs, SSN/tax IDs, passport/visa document numbers, or dates of birth
- Enter bank, payment, or payroll details
- Select privacy, GDPR, data-retention, talent-pool, terms, consent, or attestation checkboxes
- Solve CAPTCHA or anti-bot challenges
- Answer fields requiring legal judgment or uncertain interpretation
This is a deliberate design boundary, not a limitation. The agent flags exactly what it has filled and what remains for you.
Project structure
career-agent/
├── README.md
├── AGENTS.md # Codex repo guidance
├── CLAUDE.md # Claude Code context + slash commands
├── plugin.json # Legacy/shared plugin manifest
├── .claude-plugin/plugin.json # Claude Code plugin manifest
├── .codex-plugin/plugin.json # Codex plugin manifest
├── requirements.txt # pip install reportlab and pypdf
├── profile.example.json # Copy → profile.json (gitignored)
├── .gitignore
│
├── skills/
│ ├── setup-profile/SKILL.md # Bootstrap profile.json from CV or LinkedIn PDF
│ ├── source/SKILL.md # Find + verify open role leads from your profile
│ ├── new-role/SKILL.md # Scaffold a new role JSON interactively
│ ├── generate-cv/SKILL.md # Build PDF from profile + role config
│ ├── apply/SKILL.md # Fill ATS form + upload + handoff
│ └── track/SKILL.md # Application pipeline tracker
│
├── src/
│ ├── cv_builder.py # reportlab Platypus PDF engine
│ ├── cl_builder.py # Cover letter PDF builder
│ ├── generate_application.py # CLI: python src/generate_application.py <role_id>
│ └── tracker.py # Pipeline tracker CLI
│
├── roles.example/
│ └── example_role.json # Role config schema reference
│
├── roles/ # gitignored: your role configs
├── generated/ # gitignored: output PDFs
├── tracker.json # gitignored: application pipeline
└── profile.json # gitignored: your profile dataTroubleshooting
npx @nextwebb/career-agent fails with "career-agent: command not found"
This is usually a stale shell hash from a prior global install. Clear it and retry:
hash -r # zsh / bash: clears the command hash table
npx @nextwebb/career-agentIf that doesn't help, use the explicit form that bypasses hash resolution:
npx --package=@nextwebb/career-agent career-agentPDF generation fails
Ensure reportlab and pypdf are installed and use the correct flag syntax:
pip install -r requirements.txt
python src/generate_application.py --role <role_id> # correct
python src/generate_application.py <role_id> # wrong: positional args not acceptedThe generated/ output directory is created automatically on first run.
Contributing
ATS platforms to add: Ashby, SmartRecruiters, Taleo, iCIMS, BambooHR.
Each platform needs:
- A
src/ats/<platform>.pyhelper (optional: for complex flows) - Notes in the
applyskill about platform-specific quirks (hidden file inputs, React comboboxes, cross-origin iframes, etc.)
Before contributing:
- Read ENGINEERING_PRINCIPLES.md for coding standards
- Install pre-commit hooks:
pip install pre-commit && pre-commit install - Run tests locally:
pytest tests/ && bash tests/integration_test.sh - Open an issue before starting to avoid duplication
CI Requirements:
- All code must pass Ruff linting + mypy type checking
- Security scans (bandit) must pass
- Smoke tests + integration tests must pass
- Conventional commit message format required
License
MIT
