Resume CLI for init, profile switching, section management, tailoring, ATS checks, and application tracking.
cv now uses a modular Python architecture with a thin entrypoint (cv_core.py) and package modules under cvapp/.
./install.shThe installer creates an isolated runtime at ~/.local/bin/.cv-runtime, installs dependencies from requirements.txt and requirements-ats.txt, and writes a launcher so cv runs without manual venv activation.
For PDF generation (cv gen), the installer also ensures lualatex is installed.
Re-running install is incremental: dependency install is skipped when requirements.txt has not changed. Use --force to reinstall dependencies.
Optional dependencies:
python3 -m pip install -r requirements.txt
python3 -m pip install -r requirements-ats.txtDefault install target is ~/.local/bin/cv.
cv init john-bang-gang
cv jobs frontend
cv title Frontend Developercv now uses a global home directory at ~/Resume.
Use this flow when adding or changing commands:
- Define command behavior and input/output format first.
- Add or update route wiring in
cvapp/commands.py. - Put command-level behavior in
cvapp/features/<feature>/api.py. - Put low-level adapters in
cvapp/internal/(Telegram, scraping, browser automation, LLM). - Keep
cv_core.pyas a thin compatibility entry wrapper only. - Keep command names and existing behavior stable unless intentionally changed.
- Run fast local checks:
python3 -m py_compile cv cv_core.py
./cv help- Run feature smoke tests for changed commands (text, URL, and interactive paths when applicable).
- Reinstall local binary after changes:
sh ./install.sh- Validate behavior in a real resume project directory.
- Update docs in this README when command behavior changes.
Project layout after init:
~/Resume/
.cv/state.env
.cv/auto.env
jobs/
tailored/
cv init <name> creates ~/Resume and .cv state only. A job workspace is created when you run cv jobs <job> [name].
Resume versions are stored at:
jobs/<job>/<name>.md
Source layout:
cv
cv_core.py
cvapp/
app.py
commands.py
config.py
errors.py
strings.py
utils.py
features/
ats/
content/
profile/
resume/
fit/
track/
posts/
auto/
internal/
ats.py
project.py
telegram.py
web.py
browser.py
llm.py
cv init <name>
cv current
cv jobs [job] [name]
cv title <new title>
cv section [list|show|set|add|edit] ...
cv skills [list|add|rm|manage] ...
cv exp [list|add|rm|manage] ...
cv tags [text|url]
cv say <question>
cv fit <text|url>
cv gen [current|all|<path>]
cv tailor [text|url]
cv track [item] [status]
cv posts [fetch|fit|list|all|filtered|show <index>]
cv filters [name|list]
cv auto [status|enable|disable|schedule|unschedule]
cv ats [senior]
cv ci telegram [setup|status|send] [message]
cv help
Use profile-based filters to control which fetched posts are accepted during cv posts fit and cv auto enable:
cv filters
cv filters frontend
cv filters listProfiles are stored in filters/<name>.json and include:
- seniority tokens
- preferred locations
- remote acceptance
- phone and email identity fields
- minimum salary
- job types
See docs/integrations.md for setup and script usage of Telegram integration.
See docs/automation.md for automated seek/filter/analyze/grade/store/apply/track/notify flow.
See docs/architecture.md for architecture boundaries, routing design, and decision rationale.
cv skills
cv skills add "TypeScript"
cv skills rm "Skill 1"
cv skills manageList experience summaries, total years, gap months, and title relevancy:
cv expAdd entry format:
cv exp add "Company|Role|YYYY-MM|YYYY-MM"
cv exp add "Company|Role|YYYY-MM|Present"Accepted parser formats:
### Company | Title | YYYY-MM to YYYY-MM
### Company
Title (or **Title** or Position: Title)
YYYY-MM to YYYY-MM
- Description bullets...
cv tailor
cv tailor https://example.com/jobs/frontend-engineer
cv tailor "Senior frontend role with React TypeScript"Interactive prompts:
- Company (only for
cv tailorandcv tailor "...") - Job title (only for
cv tailorandcv tailor "...") - Job description (only when no text/url argument is provided; paste, then Ctrl-D)
For URL input, cv tailor <url> fetches and truncates posting text, does not prompt for company/title, and asks AI to keep the job title exactly as written in the source text.
cv tailor also uses external ATS parser fields as validation hints for AI tailoring.
Output:
tailored/<company>/<title>/<name>.md
tailored/<company>/<title>/<name>.docx
For URL input, output path uses a safe source bucket:
tailored/from-url/<source-ref>/<name>.md
tailored/from-url/<source-ref>/<name>.docx
Requires:
copilotCLI for AI tailoring.pandocfor.docxexport.
cv say "Why are you relevant candidate for this role?"Loads context from markdown files in current project.
cv tags
cv tags "Senior frontend engineer with React, TypeScript, GraphQL"
cv tags https://example.com/jobs/frontend-engineerPrints meaningful resume tags, total count, and whether total fits recommended 25-35 range. With optional text or URL, also prints job tags and resume coverage of job tags.
cv fit "Senior Frontend role with React and TypeScript"
cv fit https://example.com/jobs/frontend-engineerBehavior:
- For text input: uses provided text as job description.
- For URL input: fetches page and extracts primary readable content, including JSON-LD/script-embedded descriptions used by JS-heavy job pages.
- Runs non-AI keyword overlap precheck and AI fit review.
cv track "Company Frontend"
cv track "Company Frontend" i2
cv track "Company Frontend" status
cv trackStatus aliases:
applied/ainterview/i/int/i2/int2rejected/roffer/oghosted/g
Ghosted status auto-applies after 30 days for open applications.
Storage location is job-local:
jobs/<job>/track.csv
cv posts fetch stores fetched post records in:
.cv/posts.db
Score and filter cached posts with:
cv posts fitView cached and filtered lists with:
cv posts fetch
cv posts fit
cv posts
cv posts all
cv posts filtered
cv posts show 1cv auto status
cv auto enable
cv auto disablecv auto enable runs one automation cycle using .cv/auto.env settings:
- fetch jobs with JobSpy (
AUTO_SEARCH_TERMS,AUTO_JOB_SITES,AUTO_SEARCH_LOCATION) - parse and cache posts in
.cv/posts.db - apply fit filters on cached posts (not during fetch)
- optionally auto-apply with Playwright (
AUTO_APPLY=1) - track successful applies in
jobs/<job>/track.csv - optionally notify via Telegram (
AUTO_NOTIFY=1)
Full setup and config reference: docs/automation.md.
cv ats
cv ats seniorSteps:
- External ATS parse source:
pyresparser(if installed). - Automatic external fallback:
spaCy NERparser whenpyresparseris unavailable or broken. - Structure + parser field score.
- AI score and actionable advice via
copilot.
If external ATS parser is not installed, cv ats attempts auto-setup first and prints detailed setup errors if it still fails.
cv ats senior emulates a practical senior-profile ATS filter with pass/fail checks (experience years, title signal, leadership signal, skill overlap, multi-company history).
External ATS parser fields are also reused by:
cv tagsfor tag enrichment.cv expfor extraction validation hints.cv fitfor resume keyword enrichment.cv tailorfor ATS-guided prompt context.