Resume Composer
A private, chat-first local Codex plugin for tailoring résumés, CVs, and cover letters. It uses a local SQLite evidence bank, versioned application drafts, and an isolated XeLaTeX renderer. The chat model composes and reviews the documents; the server handles evidence references, revisions, approval, and export.
Build from this repository
Clone this repository, then run the commands below from its root. Building from source generates the plugin bundle; the Git repository does not contain installed binaries or applicant data.
npm ci --ignore-scripts
npm run build
node scripts/package.mjs /absolute/path/to/new-marketplace
See architecture and data boundaries for how the plugin works and contributing for testing and safe sharing.
Install on macOS
Requirements: Node.js 24+, the Codex desktop app/CLI, and Docker Desktop for preview/export. The bank and editing tools work without Docker. If Codex's GUI cannot find Node, install Node 24+ in a standard location (e.g. Homebrew), or provide the absolute executable as RESUME_COMPOSER_NODE in its MCP environment.
For the packaged local marketplace, unzip it to a permanent folder. From that folder run:
docker build -t resume-composer-renderer:0.1.0 plugins/resume-composer/renderer
codex plugin marketplace add "$PWD"
codex plugin add resume-composer@resume-composer-local
Restart the desktop app if the plugin is not visible, then select Resume Composer in a new local Codex chat. This does not publish anything or create a cloud service. To remove the plugin and catalogue:
codex plugin remove resume-composer@resume-composer-local
codex plugin marketplace remove resume-composer-local
The private bank and exports are deliberately retained when you uninstall. Delete them manually after backing up what you need.
Build and test from source
npm ci --ignore-scripts
npm run build
npm test
npm run renderer:build
npm run test:render
node scripts/package.mjs /absolute/path/to/new-marketplace
The package command creates a local marketplace directory and ZIP. It excludes dependencies, test data, application documents and databases; the bundled MCP server needs no npm install at runtime.
Typical workflow
- Tell Resume Composer to start your bank from an existing résumé or facts you supply. Review the extracted facts before it stores them. Your source documents are never edited.
- Ask for bullet options by emphasis and choose which to save. A bullet or prose entry links to confirmed facts; unsupported qualifications stay visible as gaps. The bank is shared across applications, but wording edited in one draft does not change it.
- Paste a job posting and choose a résumé, CV, or letter. Review proposed text, evidence and missing job terms. Ask for a swap, reordering, or small edits as needed. You can reopen drafts by ID and revision.
- Preview if desired. Confirm the exact revision using the displayed approval phrase and ask to export. A successful export returns absolute paths to PDF and TeX, plus YAML for YAMLResume styles. The plugin never submits an application.
By default résumés and CVs use the YAMLResume Jake style. Switch to the sample-based résumé starter, a CV starter, or an imported style via its template ID. YAMLResume's schema requires an explicit proficiency level for each skill. Confirm levels before using them or choose a starter/custom style that needs no level. For publications, research, or other nonstandard sections, use the CV starter or a custom template. Cover letters default to the letter starter.
Custom LaTeX templates
Choose a self-contained UTF-8 .tex file (max 64 KiB, no external assets), and tell the plugin which document type it is for. It must load geometry and setspace before the layout marker. Put each marker and the begin/end document commands on their own lines, exactly once:
\documentclass[11pt,letterpaper]{article}
\usepackage{fontspec}
\usepackage{geometry}
\usepackage{setspace}
% RESUME_COMPOSER_LAYOUT
\begin{document}
% RESUME_COMPOSER_BODY
\end{document}
Use the local imports folder from the status tool, or select an attachment and explicitly authorize importing its source. The body marker expands to the full ordered document, including the header; control its appearance with standard LaTeX section, list, and typography settings. Template source outside these markers is preserved. Remove placeholder or reference-person text from the template; it is not treated as dynamic content. A PDF is a visual reference, not an importable template.
The renderer adjusts only layout and never rewrites or deletes text to fit. Résumés and letters target one US Letter page; CVs may span pages with compact, normal or relaxed leading. On overflow or failed text/geometry checks it returns diagnostics and does not publish final files. Check the exported PDF visually before submitting; text extraction and job-term checks are not an ATS guarantee.
Data and trust
- The default private folder is ~/Library/Application Support/Resume Composer. It contains a 0600 SQLite database, imports, previews, and exports. Set RESUME_COMPOSER_HOME to an absolute path for an isolated instance.
- The plugin does not upload, sync, log application content to stderr, or require an AI API key. Material you choose to share with Codex in chat or via MCP is still processed by Codex; local storage is not offline model execution.
- Custom TeX is executable source. The renderer accepts only a local Unix Docker socket, builds a container without network or host mounts, and runs without root, capabilities, or TeX shell escape. Only the render payload is sent via stdin, and the container uses temporary files. It rejects unsafe PDF actions and checks text extraction, page count, and bounding boxes before publishing. Review source before compiling exported TeX outside the sandbox.
- The skill asks for user confirmation; the backend checks reference IDs, role scope, and revision-specific approval. Neither can independently prove a factual claim, and a local MCP client can call tools directly.