resume manages a personal resume as version-controlled structured data (JSON Resume v1 plus an x_linkedin extension). Storage is one YAML file per entity; git is a first-class primitive, so every mutation auto-commits. The sections below group the commands by task. For each command you get its purpose, the key usage, and the flags that matter most.
The CLI is agent-first and deterministic — no prompts, no editor, no network calls. Every command accepts a global
--json flag (or set RESUME_JSON=1 in the environment) to switch output to a structured envelope: {"ok":true,"data":{...}} on stdout for success, {"ok":false,"error":{"code":"...","message":"..."}} on stderr for failure. Run resume cheatsheet to print the exhaustive in-binary reference (the same content an agent harness loads).Conventions
- A
<section>is one of the 13 section names:basics,x_linkedin(singletons),work,education,volunteer,awards,publications,certificates,projects(ordered, newest-first), andskills,languages,interests,references(unordered, alphabetical). - A
<spec>is<section>for singletons (e.g.basics) or<section>/<slug>for multi-entity sections (e.g.work/anthropic). --require-clean(global) refuses any mutation when the working tree is dirty.- Mutations serialize via an advisory lock at
.resume-as-code/lock; tune the wait withRESUME_LOCK_WAIT_MS(default 5000ms).
0 success; 1 VALIDATION / ALREADY_EXISTS / E_ENTITLEMENT / E_LICENSE_INVALID; 2 NOT_FOUND; 3 GIT; 4 IO; 64 USAGE; 70 INTERNAL. The envelope’s error.code disambiguates the codes that share an exit number.
Setup & first run
resume bootstrap
A read-only first-run readiness report: it inspects the environment and the current repo and tells you whether everything for the workflow is in place — whether you are inside a resume repo, whether git is initialized, whether this is a fresh first run, and which optional rendering/import dependencies are available. It performs no mutation and always exits 0; findings live in the envelope, not the exit code. It also works outside any repo (reportsinRepo: false).
inRepo, repoRoot, gitInitialized, firstRun, a dependencies block (pdfImport, pdfExport, docx, ocr), healthy, and recommendations. pdfImport.ok is always true — the binary bundles an unpdf fallback when pdftotext (Poppler) is absent.
resume init
Scaffold a new resume-as-code repo. Createsresume/, a starter resume/basics.yaml, .gitignore, and the agent-bootstrap files CLAUDE.md + AGENTS.md; initializes a git repo if one does not exist and makes the seed commit. Refuses to scaffold into a non-empty directory (only pre-existing .git* entries are allowed).
basics: { name: "Your Name" } — edit it with resume edit basics --field name="...".
resume init-skill
Install the bundled agent skill (SKILL.md + companion docs + examples/) into an agent harness so the agent automatically knows how to drive the CLI. Human-facing setup — the agent never calls this itself.
--target <harness> (default claude-code, which installs to ~/.claude/skills/resume-as-code), --dir <path> (explicit destination, overrides --target), --force (overwrite a non-empty destination).
resume cheatsheet
Print the embedded comprehensive usage doc to stdout — the canonical agent-facing reference baked into the binary. With--json, the text is wrapped in an envelope under data.cheatsheet. Does not require a repo.
Resume data
resume add
Add a new entity to a section, validate it against the section schema, write it as YAML, and auto-commit. The slug is derived from a name-like field (name, title, organization, institution, or language) unless overridden with --slug. For ordered sections, the start-date field becomes a <YYYY>- or <YYYY-MM>- filename prefix so listings stay chronological.
--data <json>, --from-stdin, or one-or-more --field key=value. --field values starting with [ or { are JSON-parsed (arrays/objects); all others are strings — for booleans or numbers use --data or --from-stdin. Adding a duplicate slug, or a singleton that already exists, fails with ALREADY_EXISTS.
resume edit
Edit an existing entity.--data / --from-stdin replace the stored entity entirely (omitted fields are removed); --field shallow-merges the supplied keys (other fields preserved). The merged result is validated, written atomically, and auto-committed. edit is idempotent — a byte-identical result makes no commit and returns changed: false.
<YYYY[-MM]>- prefix goes stale the envelope carries a warnings array explaining how to re-sort (resume mv, or remove + re-add).
resume rm
Remove an entity from disk and auto-commit the deletion.basics is required by the schema and cannot be removed (rm basics → USAGE); the optional x_linkedin singleton is removable.
resume show
Print a single entity. Human mode renders YAML to stdout; JSON mode puts the entity indata with the absolute file path as a sibling path field. Read-only — no commit, no schema validation.
resume list
List entities. Without an argument, lists every entity in every section; with a section name, lists only that section. Ordered sections are newest-first; unordered are alphabetical. Human mode skips empty sections; JSON mode includes every section (empty arrays for those with none).resume mv
Rename a non-singleton entity in place — same section, new slug, with the existing<YYYY[-MM]>- prefix preserved for ordered sections. The rename uses git mv so history follows the file. If the normalized new slug equals the current one, it is a no-op (renamed: false, commit: null).
<spec>). A collision with an existing entity fails with ALREADY_EXISTS.
resume validate
Walk the entireresume/ tree, parse every YAML file, and validate the assembled document against the root schema (which requires basics). Reports per-section entity counts. The right command to gate a commit in CI.
resume schema
Emit a JSON Schema for the whole resume (no argument) or a single section’s entity shape. This is the self-discovery surface — the schema is the contractadd and edit enforce. schema always produces JSON; --json only controls whether it is wrapped in the success envelope.
resume build
Assemble the canonical JSON Resume document: load every section, validate against the root schema, and write pretty-printed JSON. Default output isdist/resume.json (gitignored). build does not auto-commit the artifact, and empty sections are omitted from the document.
-o, --output <path> (default <repo>/dist/resume.json).
Import & export
resume import
Three modes, dispatched by the detected (or--format-overridden) input type and flags:
- Text extraction (PDF/DOCX/HTML/TXT/MD) — extract text into a structured envelope with
sectionHintsfor the agent to consume. PDFs usepdftotext(Poppler) with anunpdffallback, auto-falling-back totesseractOCR for thin-text PDFs. - Structured import (
.jsonmatching JSON Resume v1, or a LinkedIn data-export.zipcontainingProfile.csv) — write entities directly to the tree, one commit per entity. - Mechanical structuring (
--structureon a text format) — extract, then deterministically structure the text into schema entities (no LLM) and write them.
--stage (also write the full envelope to .resume-as-code/staging/<id>.json), --no-ocr / --ocr-threshold <n> (control the OCR auto-fallback; 0 disables it), --format <fmt> (override detection: pdf, docx, html, txt, md, json-resume, linkedin-export), and for structured/--structure writes: --overwrite, --dry-run, --prefix <slug>. Structured imports require a resume/ repo; per-entity failures are reported in data.failed and do not abort the run.
resume export
Emit the canonical document, optionally filtered, in several formats. Read-only — no commit, no lock,--require-clean is a no-op. export is the surface for “give me a tailored slice”; build always emits the full doc.
--include <list> / --exclude <list> (comma-separated sections), --since <YYYY[-MM]> (drops earlier entries from ordered sections only), --audience <tag> (keeps entities whose audiences[] contains the tag; untagged entities are universal), --format json|yaml|html|pdf|docx (default json), --theme <name> (HTML/PDF/DOCX; bundled default/compact, an jsonresume-theme-* npm package, or a local path), --page-size letter|a4|legal (PDF only), --branch <ref> (render from a git ref without checkout), and -o, --output <path>. The first PDF render downloads pinned Chrome for Testing (~170MB to ~/.cache/puppeteer/); progress goes to stderr.
Tier behavior: Free PDF/HTML exports carry a discreet footer watermark (Pro removes it). On Free, DOCX export,
--page-size, and the filter flags (--include/--exclude/--since/--audience) are Pro-only and return a non-fatal E_ENTITLEMENT envelope rather than being silently ignored. The watermark is applied to exported artifacts only — never the live preview server.resume themes
List themes available for export: local forks (<repo>/themes/<name>/), bundled (default, compact), and jsonresume-theme-* npm packages discoverable from the cwd. Read-only; works from any directory. Local forks shadow same-named bundled/npm themes during --theme resolution.
resume theme fork
Copy a theme into the resume repo at<repo>/themes/<slug>/ so it can be edited locally. The fork is version-controlled with the resume, shadows same-named bundled/npm themes, carries a .resume-fork.json provenance marker, and auto-commits.
--as <slug> (local slug, normalized; defaults to the source name), --force (overwrite an existing fork). After forking, edit index.js (HTML) and style.css directly, then render with resume export --theme <slug>.
resume preview
Run a local HTTP preview server bound to127.0.0.1 (default port 4444, not 4000). Foreground process — Ctrl+C to stop. The theme/resume views are read-only, but the /jobs tracker page is editable in the browser (add a job, change status, edit fields, append notes, delete) — those edits commit to the orphan jobs branch exactly like the CLI.
--port <n>, --no-open (don’t open a browser tab), --no-watch (disable live reload), --theme <name>. Routes include /, /preview/:theme, /pdf/:theme, /resume.json, /jobs, /api/branches, /api/jobs, and /events (SSE). Filter query params (audience, since, include, exclude, pageSize, branch) apply to the render routes.
Versions & history
resume branch
Create a new git branch for a resume variant: normalize the name, create and check out the branch, write lineage metadata to.resume-as-code/branch-meta.yaml, and auto-commit. Use the role/<role-type> convention for a reusable role-positioned variant.
--from <ref> (source branch; default is the current branch). Always branch variants --from main so global changes can be merged down into each variant.
resume branches
List the resume variant branches (main plus tailor/* and other variants) as a hierarchy, each with its role label (resolved from basics.label, falling back to basics.name). Read-only — never checks out, creates, or modifies a branch. The orphan jobs store branch is excluded.
resume history
Print the git commit log for one entity, scoped to its file and following renames (git log --follow). Read-only. Newest-first; SHAs are abbreviated to 7 chars and can be passed straight to resume revert.
--limit <n> (default 20; must be a positive integer).
resume revert
Restore a single entity to its content at a prior git ref: readgit show <ref>:<path>, validate against the current schema, write atomically, and auto-commit. Idempotent — reverting to the on-disk state makes no commit. If the schema has evolved and the historical content no longer parses, it refuses with VALIDATION (reconcile manually via resume edit <spec> --from-stdin).
<git-ref> (optional; default HEAD~1; accepts a SHA, tag, HEAD~N, or branch).
resume snapshot
Create an annotated git tag at HEAD. The label is normalized and prefixed withresume- to namespace it from other tags. Refuses with ALREADY_EXISTS on a duplicate. Does not honor --require-clean — tagging is independent of working-tree state.
-m, --message <msg> (default snapshot at <ISO-date>). Tags are local until pushed (git push --tags); list them with git tag --list 'resume-*'.
Jobs & matching
Job applications live on a dedicated orphanjobs git branch, checked out in a linked worktree at .resume-as-code/jobs-wt/jobs/<slug>/ — durable across every resume branch. Manage them through the jobs subcommands; do not read or write the YAML directly. Unlike resume add, jobs add auto-disambiguates slugs on collision rather than failing.
resume jobs add
Save a new job application (company + role, plus an optional job description and a rich set of metadata fields). When a JD is supplied, the CLI parses it deterministically (keyword extraction, requirement classification) and stores the result.--company, --role. JD input (mutually exclusive): --jd <path>, --jd-text <text>, --stdin. Common extras: --location, --tags <tags...>, --source-url, --seniority, --department, --team, --employment-type, --work-arrangement (with --work-detail/--timezone/--office-days), --posted-at, --expires-at, --headcount, --visa-sponsorship/--no-visa-sponsorship, --travel, --interest, --metadata <json>, and --resume-branch (usually set automatically by jobs tailor). See resume cheatsheet or the full reference for every flag.
resume jobs edit
Edit a job application — partial merge of the specified fields. Idempotent (no-op if nothing changes); auto-commits.jobs add, plus --add-tag/--remove-tag. --data <json> applies a JSON patch via the shared merge path (mutually exclusive with the field flags; can set fields the flags cannot, notably source_url). See resume cheatsheet for the full flag table.
resume jobs delete
Delete a job application and all its files. Two-pass: without--confirm it previews what would be deleted; with --confirm it deletes and auto-commits.
resume jobs list
List tracked jobs. Read-only.--status <state> (a state name, or the meta-filters active / terminal), --tag <tag>, --added-within <dur>, --updated-within <dur>. Format: --format brief|full|json|pipeline (pipeline groups jobs by state in state-machine order).
resume jobs show
Show full detail on one job (record, status history, notes). Read-only.resume jobs status
Show or update a job’s status. Without--set, read-only; with --set, transition the state machine and auto-commit. States: saved → applied → screening → interviewing → offer → accepted (with declined off offer); any non-terminal can go to withdrawn / rejected / closed.
--set <state>, --note <text>, --variant <branch> (records the variant sent on the history entry), --file <path>.
resume jobs note
Append a timestamped note to a job. Auto-commits to thejobs branch.
resume jobs remind
Add, list, or clear reminders for a job. Adding requires--note plus one of --at or --in.
--at <timestamp>, --in <duration>, --note <text> (required on add), --list, --clear.
resume jobs history
Show a job’s git commit history on thejobs branch (changes to job.yaml / status.yaml / notes.md / analyses/). The jobs-branch analogue of resume history. Read-only.
--limit <n> (default 50).
resume jobs tailor
Create (or adopt) a tailored resume branch for a job, link it (setresume_branch), and check it out — in one step. This is the blessed way to start tailoring: because the link is established at tailor time, resume match --job <slug> automatically scores against the tailored resume.
--from <ref> (base; default current branch), --name <branch> (default tailor/<slug>). If the branch exists it is adopted (no error); either way job.resume_branch is set.
resume jobs sync
Sync job applications with the cloud queue. Not yet implemented — requires a resume-as-code cloud account.resume match
Match a resume against a job description via deterministic keyword extraction, classification, and coverage analysis. The CLI emits a structured envelope (keyword_score, keywords_present, keywords_missing, near_misses); the agent performs the semantic pass on top.
--job <slug> (uses stored JD; scores the linked resume_branch → tailor/<slug> → base HEAD), --jd <path>, --stdin, or --all. Options: --branch <name> (default HEAD), --label <name>, --no-save, --render (human-readable output). With --job, the analysis is saved under the job’s analyses/ dir and the job record’s latest_analysis is updated.
Licensing & bridge
resume license
Inspect or change the Free/Pro tier.resume runs Free by default and unlocks Pro with a license; daily verification is offline (an embedded Ed25519 public key — no network call during normal use). Human-facing setup — an agent doesn’t call license itself, but should recognize the non-fatal E_ENTITLEMENT envelope and offer the upgrade at https://resume-as-code.ai/pro.
status (tier, sku, expiry, source env/file/none; always exits 0), activate <key> (auto-detects a store key vs. a raw token; writes ~/.config/resume-as-code/license.json; invalid → E_LICENSE_INVALID), deactivate (revert to Free; idempotent), refresh (re-validate; online when activated from a store key). Source precedence: a RESUME_LICENSE_KEY env token overrides the cached file, which overrides Free.
resume serve —bridge
Run a localhost (127.0.0.1) token-gated bridge for a paired browser extension that fills job-application forms from resume-as-code data. Reuses the preview-server core and adds three token-gated /api/* endpoints. Foreground (Ctrl+C); read-only with respect to resume/.
--port <n>, --no-open, --print-token. A stable pairing token is generated once at ~/.config/resume-as-code/bridge.json; every /api/* request requires the X-Bridge-Token header. Endpoints: GET /api/profile?branch=<ref> (resume JSON for a variant), GET /api/apply-profile (the application profile; sensitive — never served without the token), and POST /api/map-fields (a 3-tier field-to-value mapper: ATS adapters live in the extension, a deterministic heuristic in the CLI, and an opt-in Claude fallback that uses ANTHROPIC_API_KEY set only in the CLI).
resume apply-profile
Manage the application profile — reusable answers to the boilerplate a job-application form asks that are not part of the resume: work authorization, sponsorship needs, voluntary EEO self-ID, salary expectation, references, availability, and site-specific answers. Stored as one versioned YAML file, validated, auto-committed, and branch-aware.get (print the profile; {} when unset) and set (merge fields, validate, write, auto-commit — via --field k=v with dot-paths, --data <json> deep-merge, or --from-stdin).