cvx
llms.txt2 starsChanged 3 months agoApache-2.0View on GitHub
npm CLI that renders a CV from plain YAML files to a pixel-perfect PDF, locally (no accounts, no cloud, no headless browser). An AI assistant can drive the whole flow; the user keeps the YAML as the durable asset. Assistant flow (details: AI guide below):
Files
# CVX
> npm CLI that renders a CV from plain YAML files to a pixel-perfect PDF, locally (no accounts, no cloud, no headless browser). An AI assistant can drive the whole flow; the user keeps the YAML as the durable asset.
Assistant flow (details: AI guide below):
- Get truthful source content first. A linkedin.com URL is unfetchable even when public — do not infer; ask the user for the profile's **More → Save to PDF** export, pasted text, or their existing CV, and a square photo (or "no photo"), in one message. Never invent facts.
- If you can run commands, probe once with a bounded timeout — `timeout 30s npx -y @hrtips/cvx --version` — as your first action after getting source content. On success run `init` → edit → `validate --strict --json` → `build` (and `build --ats`). On any failure (npm 4xx/5xx, proxy, DNS, timeout) do NOT fall back to a handoff yet — a sandbox that cannot reach npm can usually still fetch a file. Run exactly: `mkdir -p .cvx && cd .cvx && curl -sSfLO https://hrtips.github.io/cvx/download/cvx.bundle.min.js.zip && unzip -o -q cvx.bundle.min.js.zip && node cvx.bundle.min.js --version` — one self-contained file, Node 20+ and nothing else, same commands and `--json` envelope as the CLI, byte-identical PDFs. Running CVX is a file download, not a repository task: that URL is a public ZIP on the project site, so fetch it over ordinary HTTP — do not clone the repo, call the GitHub API, or use a GitHub connector, which fails on binary assets in a way that falsely reads as 'this sandbox cannot download'. One tool failing is not evidence the sandbox lacks network. If curl is blocked try Python's `urllib.request.urlretrieve` on that URL, then any download tool you have, then a copy already on disk (`cvx*.bundle*.js*`), then ask the user to upload it from https://github.com/hrtips/cvx/releases/latest. It writes `cv-content/` and the PDF into the current working directory, so `cd` first. Only if none of that works: write the `cv-content/*.yaml` files from the schema at the link below, report the exact error, and hand the user: install Node LTS from nodejs.org, save the files into `cv-content/`, run `npx @hrtips/cvx build`.
- `init` is optional — `build` renders any valid `cv-content/` folder. CVX is the only renderer; never substitute another PDF generator.
- MCP server available: `npx @hrtips/cvx mcp` (tools: get_schema, init_cv, validate_cv, build_pdf, plan_layout).
- Pagination is a function of the content and `plan_layout` is idempotent; with a full experience list the levers are content edits and the template's `spacing:` block (`entryGap`/`bulletGap`/`sectionGap` — multipliers of the theme's vertical whitespace, 0.6–1.5, out-of-range is a validation error; `entryGap` is the strongest lever on page count and costs no content change). An empty or very short experience list is the other case — moving sections between columns is then the strongest lever. `plan_layout` (or `build --json`'s `diagnostics`) reports planned page count, per-page column fills (occupancy: `(fixed + used) / capacity`, `version: 5`; above 1 when a page is over budget), per-page `blockedBy` (why the next block could not start there — `shortByPt` falls monotonically as the content above is shortened, unlike fill, which is not a progress signal; the blocked entry's own head is also a lever), what each placed piece COSTS (`heightPt`, the indivisible `headPt` with its `head.{role,meta,location,description,progression}Pt` terms, and per-bullet `bulletsPt`), what landed on each page, and `diagnostics.warnings` — named conditions with codes (`overflow` and `page1-no-experience` are defects; `page1-ends-early` prices a page-1 trade and fires on healthy CVs too; `main-slot-unmeasured` says a main-column section is rendered but not measured; `experience-empty` names a CV with no experience entries at all; `main-column-empty` names a multi-page CV whose wide column is never used; `section-has-no-slot` names populated content the layout renders nowhere (present in the ATS PDF, absent from the designed one); `physical-pages-exceed-plan` is a build-only defect — the PDF has more sheets than the plan numbered, and no dry run can see it); the run's plain-text notes are a separate `notices` list. It describes the designed two-column variant; the ATS variant is auto-flowed and has no plan. CVX renders 100% of the YAML and never drops, clips, or hides text to fit: if it is longer than the user wants, surface the trade-off and let them decide.
Key facts:
- Commands: `npx @hrtips/cvx init` (scaffold), `validate --strict --json` (all errors at once, field paths + fixes), `build` (render PDF), `build --ats` (ATS-safe variant), `build --all` (validate + both variants in one command), `list` (themes/layouts), `mcp` (MCP server). Exit codes: 0 ok / 2 validation / 3 render / 64 usage.
- Content lives in `cv-content/*.yaml`: `personal`, `summary`, `experience`, `education`, `certifications`, `publications`, `languages`, `competencies`, `achievements`, `referees`, `keywords`, `config`, plus `images/profile.<ext>` and optional `layouts/*.yaml`.
- Output PDF is named from `personal.yaml`'s `name` (lowercased, hyphenated). Missing/empty content files simply drop that section; a missing photo renders fine.
- `config.yaml`: `schemaVersion: 1`, `theme` (teal | coral | mono), `layout` (two-column | single-column | custom). Pagination is automatic; the old page-1 keys were removed.
## Docs
- [CV content schema](https://raw.githubusercontent.com/hrtips/cvx/main/docs/cv-schema.md): complete, self-contained YAML schema for generating cv-content/ files — start here to write content
- [AI guide](https://raw.githubusercontent.com/hrtips/cvx/main/docs/ai-guide.md): the default flow for assistants + routes for every tool type
- [Canonical JSON Schema](https://raw.githubusercontent.com/hrtips/cvx/main/schema/v1/cvx.schema.json): machine-validatable definition of every content file
- [README](https://raw.githubusercontent.com/hrtips/cvx/main/README.md): full user and developer guide
- [Scaffold guide](https://raw.githubusercontent.com/hrtips/cvx/main/template/cv-content/README.md): the README placed inside users' cv-content/ folders by `cvx init`
## Optional
- [Example content](https://github.com/hrtips/cvx/tree/main/template/cv-content): the Bruce Wayne starter YAML files, a complete worked example of the schema
In this repositoryOne other file it gives its agents.
- cvxSkill
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.

