# 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.` 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