CV Builder
Drive the CV through $CV — the source of truth; this skill is the runbook. No content
generation here: every build is a deterministic filter over the master file, never a rewrite.
This setup is not hardcoded. The actual CV content (name, employer, contact info) lives in
$AXON_PERSONAL_ROOT/data/cv/master_cv.yaml, never in this skill or in Axon. If that file is
missing, stop and tell the user to copy capabilities/cv/master_cv.schema.yaml there and fill
it in — do not draft CV content yourself.
Variables
| var |
value |
notes |
$CV |
capabilities/cv/cv |
launcher, relative to $AXON_ROOT |
$MASTER |
$AXON_PERSONAL_ROOT/data/cv/master_cv.yaml |
the one file to maintain; $CV refuses to run without it |
$PROFILE |
one of $CV list-profiles' output |
e.g. swe, quant, consulting, general |
$LANG |
en or de |
defaults to en if the user doesn't say |
Workflow
$CV list-profiles — read the actual tags currently defined (don't assume the list from
memory; it's just data and changes as the master file changes).
- Match the user's ask to the closest tag:
- A job posting/description or a stated role type ("SWE role", "consulting") → pick the
closest existing tag from step 1's output.
- Ambiguous, or nothing close enough → ask the user to pick from the actual list rather than
guessing.
- Pick
$LANG from what the user said (German posting/company → de; otherwise en unless
told).
$CV build --profile $PROFILE --lang $LANG → report the printed output path back to the
user. Building every profile/lang at once: $CV build --all (optionally --all --lang de
to restrict to one language).
Iterating on the master file rather than producing one PDF: $CV watch --profile $PROFILE --lang $LANG recompiles on every save. Tell the user to open the PDF in a viewer that
reloads on change (Preview, Skim, a browser tab) — watch blocks until they stop it.
- Never edit
$MASTER on the user's behalf mid-conversation to "tailor" wording for a specific
posting — that recreates the AI-tailoring flow this design deliberately left out. If the
user wants new content, tell them to add it (with the right profiles: tags) to the master
file themselves.
Gotchas
- An unknown profile tag now fails the build (changed 2026-08-16). It used to render a
generic baseline CV, because items without a
profiles list are always included — so a typo
produced a real-looking PDF that was quietly missing most of its content. $CV build --profile <unknown> exits 1 and prints the known tags. Still run list-profiles first, but
a wrong tag is now a loud error rather than a silent quality problem.
--all respects a profile's declared languages. The master may carry
profile_langs: {<tag>: [en]}; --all skips the excluded pairs, so its output is not
always profiles × 2. An explicit --profile x --lang de is never blocked by this.
$CV requires typst and yq on PATH (brew install typst yq) — it checks and errors
clearly if either is missing, no need to pre-check yourself.
- Experience and education dates aren't bilingual. Their
date fields are plain strings
(e.g. "Sep. 2025 - Present"), so a German build still shows English month abbreviations by
design. Free-section entries are the exception: their label and meta accept either a
plain string or an {en, de} pair (added 2026-08-16 for "since Jun 2025" / "seit Juni 2025").
- Output PDFs and the master file are personal data — they live under
$AXON_PERSONAL_ROOT/data/cv/, gitignored, never in this skill or in Axon's own repo. Don't
copy CV content into this skill file, a commit message, or anywhere else in the public repo.
Provenance and maintenance
$CV → $AXON_ROOT/capabilities/cv/cv (bash launcher, execs typst compile). Re-verify on
drift:
- master file present:
test -f "$AXON_PERSONAL_ROOT/data/cv/master_cv.yaml" && echo ok
- launcher present + executable:
test -x "$AXON_ROOT/capabilities/cv/cv" && echo ok
- deps on PATH:
command -v typst && command -v yq
1---2name: cv-builder3description: Builds a job-tailored CV PDF from a single profile-tagged master CV file, via the local `cv` CLI — pick the closest profile tag (or ask), pick a language, run the build, hand back the PDF path. Use when the user wants a CV/resume for a specific job application, role type, or language. Do not use for writing or editing CV content itself (that's the master file, edited by hand) or for any content-generation/AI-tailoring flow — this skill only filters and renders what's already in the master file.4---56# CV Builder78Drive the CV through **`$CV`** — the source of truth; this skill is the runbook. No content9generation here: every build is a deterministic filter over the master file, never a rewrite.1011**This setup is not hardcoded.** The actual CV content (name, employer, contact info) lives in12`$AXON_PERSONAL_ROOT/data/cv/master_cv.yaml`, never in this skill or in Axon. If that file is13missing, stop and tell the user to copy `capabilities/cv/master_cv.schema.yaml` there and fill14it in — do not draft CV content yourself.1516## Variables1718| var | value | notes |19|-----|-------|-------|20| `$CV` | `capabilities/cv/cv` | launcher, relative to `$AXON_ROOT` |21| `$MASTER` | `$AXON_PERSONAL_ROOT/data/cv/master_cv.yaml` | the one file to maintain; `$CV` refuses to run without it |22| `$PROFILE` | one of `$CV list-profiles`' output | e.g. `swe`, `quant`, `consulting`, `general` |23| `$LANG` | `en` or `de` | defaults to `en` if the user doesn't say |2425## Workflow26271. `$CV list-profiles` — read the actual tags currently defined (don't assume the list from28 memory; it's just data and changes as the master file changes).292. Match the user's ask to the closest tag:30 - A job posting/description or a stated role type ("SWE role", "consulting") → pick the31 closest existing tag from step 1's output.32 - Ambiguous, or nothing close enough → ask the user to pick from the actual list rather than33 guessing.343. Pick `$LANG` from what the user said (German posting/company → `de`; otherwise `en` unless35 told).364. `$CV build --profile $PROFILE --lang $LANG` → report the printed output path back to the37 user. Building every profile/lang at once: `$CV build --all` (optionally `--all --lang de`38 to restrict to one language).39 Iterating on the master file rather than producing one PDF: `$CV watch --profile $PROFILE40 --lang $LANG` recompiles on every save. Tell the user to open the PDF in a viewer that41 reloads on change (Preview, Skim, a browser tab) — `watch` blocks until they stop it.425. Never edit `$MASTER` on the user's behalf mid-conversation to "tailor" wording for a specific43 posting — that recreates the AI-tailoring flow this design deliberately left out. If the44 user wants new content, tell them to add it (with the right `profiles:` tags) to the master45 file themselves.4647## Gotchas4849- **An unknown profile tag now fails the build** (changed 2026-08-16). It used to render a50 generic baseline CV, because items without a `profiles` list are always included — so a typo51 produced a real-looking PDF that was quietly missing most of its content. `$CV build52 --profile <unknown>` exits 1 and prints the known tags. Still run `list-profiles` first, but53 a wrong tag is now a loud error rather than a silent quality problem.54- **`--all` respects a profile's declared languages.** The master may carry55 `profile_langs: {<tag>: [en]}`; `--all` skips the excluded pairs, so its output is not56 always profiles × 2. An explicit `--profile x --lang de` is never blocked by this.57- **`$CV` requires `typst` and `yq` on `PATH`** (`brew install typst yq`) — it checks and errors58 clearly if either is missing, no need to pre-check yourself.59- **Experience and education dates aren't bilingual.** Their `date` fields are plain strings60 (e.g. "Sep. 2025 - Present"), so a German build still shows English month abbreviations by61 design. Free-section entries are the exception: their `label` and `meta` accept either a62 plain string or an `{en, de}` pair (added 2026-08-16 for "since Jun 2025" / "seit Juni 2025").63- **Output PDFs and the master file are personal data** — they live under64 `$AXON_PERSONAL_ROOT/data/cv/`, gitignored, never in this skill or in Axon's own repo. Don't65 copy CV content into this skill file, a commit message, or anywhere else in the public repo.6667## Provenance and maintenance6869`$CV` → `$AXON_ROOT/capabilities/cv/cv` (bash launcher, execs `typst compile`). Re-verify on70drift:71- master file present: `test -f "$AXON_PERSONAL_ROOT/data/cv/master_cv.yaml" && echo ok`72- launcher present + executable: `test -x "$AXON_ROOT/capabilities/cv/cv" && echo ok`73- deps on PATH: `command -v typst && command -v yq`