mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-09-17 00:26:26 +00:00
feat(add-template): make /add-template engine-agnostic (#238)
* feat(add-template): make /add-template engine-agnostic so Typst can register alongside LaTeX /add-template hardcoded a lualatex|xelatex|pdflatex engine enum and .tex assumptions, so custom templates could only be LaTeX. Replace the enum with a declared source extension + compile command, so any toolchain (Typst via `typst compile`, or others) registers the same way stock LaTeX templates did. Stock CV/cover-letter pipeline stays LaTeX and untouched (per #181). Also fixes a latent bug this surfaced: apply.md's compile step ignored the ACTIVE-TEMPLATE block and always ran lualatex/xelatex on .tex regardless of the active template, and .gitignore's cv/main_*.tex pattern would not have ignored a non-.tex draft (personal-data leak). Both now resolve from the declared extension/command. * fix(add-template): satisfy security_guards on the .gitignore Typst fix security_guards.py pins the personal-data ignore rules by exact string and gates negations through an allowlist, so broadening cv/main_*.tex and cover_letters/cover_*.tex to *.* (for .typ drafts) needed a matching update to REQUIRED_IGNORE_RULES. Also tighten the .gitignore itself per review: keep the re-include negations at .tex instead of widening them to *.* too. The stock example files are always LaTeX, so .tex is enough to re-include them, and a wildcard negation would have also re-included build artifacts (main_example.pdf/.aux) that should stay ignored. ALLOWED_IGNORE_NEGATIONS needs no change since the negations are unchanged. Also adds a CHANGELOG entry under Unreleased for the Typst/custom-template support.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# /add-template - Register a Custom CV or Cover Letter Template
|
# /add-template - Register a Custom CV or Cover Letter Template
|
||||||
|
|
||||||
You are helping the user register their own LaTeX template with the AI Job Search framework. The framework ships with moderncv (banking style) for CVs and a custom `cover.cls` for cover letters. This command lets the user swap in their own template: store the template files, capture usage instructions (compile engine, fonts, style rules, page limits), verify the template compiles, and wire it into the `/apply` workflow so every future application uses it.
|
You are helping the user register their own CV or cover letter template with the AI Job Search framework — LaTeX, Typst, or any other toolchain that compiles to PDF from the command line. The framework ships with moderncv (banking style) for CVs and a custom `cover.cls` for cover letters. This command lets the user swap in their own template: store the template files, capture usage instructions (source extension, compile command, fonts, style rules, page limits), verify the template compiles, and wire it into the `/apply` workflow so every future application uses it.
|
||||||
|
|
||||||
`$ARGUMENTS` may contain a subcommand, a file path, or nothing.
|
`$ARGUMENTS` may contain a subcommand, a file path, or nothing.
|
||||||
|
|
||||||
@@ -22,9 +22,9 @@ Use Glob with `templates/**/TEMPLATE.md` to find registered templates. For each,
|
|||||||
```
|
```
|
||||||
## Registered Templates
|
## Registered Templates
|
||||||
|
|
||||||
| Name | Type | Engine | Fonts | Active |
|
| Name | Type | Source | Toolchain | Fonts | Active |
|
||||||
|------|------|--------|-------|--------|
|
|------|------|--------|-----------|-------|--------|
|
||||||
| <name> | CV / Cover letter | lualatex/xelatex/pdflatex | <main font> | yes/no |
|
| <name> | CV / Cover letter | .tex/.typ/... | lualatex/typst/... | <main font> | yes/no |
|
||||||
```
|
```
|
||||||
|
|
||||||
A template is **active** if `05-cv-templates.md` (CV) or `06-cover-letter-templates.md` (cover letter) contains an `ACTIVE-TEMPLATE` managed block naming it. If no custom templates exist, say so and explain that `/add-template` registers one. Stop here.
|
A template is **active** if `05-cv-templates.md` (CV) or `06-cover-letter-templates.md` (cover letter) contains an `ACTIVE-TEMPLATE` managed block naming it. If no custom templates exist, say so and explain that `/add-template` registers one. Stop here.
|
||||||
@@ -39,14 +39,16 @@ If `$ARGUMENTS` contains `--use <name>`:
|
|||||||
4. If more than one manifest matches, stop and list the matching manifest paths. Ask the user to rename one of the templates; activation must be unambiguous.
|
4. If more than one manifest matches, stop and list the matching manifest paths. Ask the user to rename one of the templates; activation must be unambiguous.
|
||||||
5. Read the matching `TEMPLATE.md` and extract:
|
5. Read the matching `TEMPLATE.md` and extract:
|
||||||
- **Type:** `CV` or `Cover letter`
|
- **Type:** `CV` or `Cover letter`
|
||||||
- **Engine:** `lualatex`, `xelatex`, or `pdflatex`
|
- **Source extension:** e.g. `.tex`, `.typ`
|
||||||
|
- **Compile command:** the full declared command
|
||||||
|
- **Engine/toolchain:** e.g. `lualatex`, `typst` (display label)
|
||||||
- **Page limit:** `<N> page(s)`
|
- **Page limit:** `<N> page(s)`
|
||||||
- **Fonts:** the full font summary line
|
- **Fonts:** the full font summary line
|
||||||
6. Derive the template folder from the manifest path and verify `template.tex` exists in the same folder. If it is missing, stop with an error; the template registration is incomplete.
|
6. Derive the template folder from the manifest path and verify `template<source-extension>` exists in the same folder. If it is missing, stop with an error; the template registration is incomplete.
|
||||||
7. Derive `<type>` for Step 5 from the manifest path:
|
7. Derive `<type>` for Step 5 from the manifest path:
|
||||||
- `templates/cv/<name>/TEMPLATE.md` -> `cv`
|
- `templates/cv/<name>/TEMPLATE.md` -> `cv`
|
||||||
- `templates/cover_letters/<name>/TEMPLATE.md` -> `cover_letters`
|
- `templates/cover_letters/<name>/TEMPLATE.md` -> `cover_letters`
|
||||||
8. Continue to Step 5 using the resolved `<name>`, `<type>`, `<engine>`, font summary, page limit, template skeleton path, and manifest path. Do not re-run Steps 1-4; `--use` switches an already-registered template.
|
8. Continue to Step 5 using the resolved `<name>`, `<type>`, `<source-extension>`, `<compile-command>`, engine/toolchain label, font summary, page limit, template skeleton path, and manifest path. Do not re-run Steps 1-4; `--use` switches an already-registered template.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -56,28 +58,32 @@ Ask the user (skip anything already answered by `$ARGUMENTS`):
|
|||||||
|
|
||||||
1. **Type:** Is this a **CV** template or a **cover letter** template?
|
1. **Type:** Is this a **CV** template or a **cover letter** template?
|
||||||
2. **Source:** Where is the template? Accept any of:
|
2. **Source:** Where is the template? Accept any of:
|
||||||
- A path or @-mention of a `.tex` file (plus optional `.cls`/`.sty` files)
|
- A path or @-mention of a source file in any toolchain (`.tex` plus optional `.cls`/`.sty`, `.typ` plus optional local packages, or another compile-to-PDF format)
|
||||||
- Pasted LaTeX content
|
- Pasted template content
|
||||||
- A directory containing the template and its assets (class files, fonts, images)
|
- A directory containing the template and its assets (class/package files, fonts, images)
|
||||||
|
|
||||||
Read every provided file. If the template references a document class or package that is not part of standard TeX distributions (e.g. a custom `.cls`), confirm the user has the file and ask for it if missing — the template cannot compile without it.
|
Read every provided file. If the template references an include the declared toolchain doesn't ship by default — a custom `.cls`/`.sty` not part of standard TeX distributions, a Typst package imported via a local `#import`, or an equivalent for another toolchain — confirm the user has the file and ask for it if missing — the template cannot compile without it.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Step 2: Capture Template Instructions
|
## Step 2: Capture Template Instructions
|
||||||
|
|
||||||
Interview the user for the metadata that `/apply` needs to use the template correctly. Infer as much as possible from the LaTeX source first (documentclass, `\fontspec` calls, geometry, colors) and present your inferences for confirmation rather than asking blind questions.
|
Interview the user for the metadata that `/apply` needs to use the template correctly. Infer as much as possible from the source first (LaTeX: documentclass, `\fontspec` calls, geometry, colors; Typst: `#set`/`#show` rules, `#import`s; other toolchains: whatever the format exposes) and present your inferences for confirmation rather than asking blind questions.
|
||||||
|
|
||||||
Collect:
|
Collect:
|
||||||
|
|
||||||
1. **Name** - short kebab-case identifier (e.g. `awesome-cv`, `classic-serif`). Must not collide with an existing folder in `templates/`.
|
1. **Name** - short kebab-case identifier (e.g. `awesome-cv`, `classic-serif`). Must not collide with an existing folder in `templates/`.
|
||||||
2. **Compile engine** - `lualatex`, `xelatex`, or `pdflatex`. If the source uses `fontspec` or loads font files by path, it requires `xelatex` or `lualatex`; tell the user this rather than letting them pick `pdflatex`.
|
2. **Source extension** - the main file's extension (`.tex`, `.typ`, ...), inferred from the provided source file.
|
||||||
3. **Fonts** - which font(s) the template uses and where they come from:
|
3. **Compile command** - the full command `/apply` and Step 4's test compile will run, using `<file>` (no extension) as the placeholder for the output basename:
|
||||||
- **Bundled font files** (`.ttf`/`.otf` shipped with the template): copy them into the template folder in Step 3 and record the relative `Path` used in `\fontspec` calls.
|
- **`.tex` source**: infer the engine the same way as before - if the source uses `fontspec` or loads font files by path, it requires `xelatex` or `lualatex`; tell the user this rather than letting them pick `pdflatex`. Render as `lualatex -interaction=nonstopmode <file>.tex` (or the appropriate engine).
|
||||||
- **System / TeX-distribution fonts**: record the font name and note that the user's machine must have it installed.
|
- **`.typ` source**: default to `typst compile <file>.typ <file>.pdf` - Typst has a single binary, no engine choice.
|
||||||
4. **Style rules** - anything the drafter must preserve when filling the template: color scheme, section order, heading style, spacing conventions, bullet formatting, date format.
|
- **Anything else**: no built-in guidance; ask the user for the exact compile command.
|
||||||
5. **Page limit** - hard page count for the compiled PDF. Default: **2 pages** for a CV, **1 page** for a cover letter. `/apply`'s compile-and-inspect loop enforces this.
|
4. **Fonts** - which font(s) the template uses and where they come from:
|
||||||
6. **Known pitfalls** (optional) - macros that break with certain content (like the stock template's `\lettercontent{}`/`itemize` interaction), characters that need escaping, sections that must not be reordered.
|
- **Bundled font files** (`.ttf`/`.otf` shipped with the template): copy them into the template folder in Step 3 and record the relative path used to load them (LaTeX `\fontspec` `Path`, Typst `#import`/font path, or equivalent).
|
||||||
|
- **System / distribution fonts**: record the font name and note that the user's machine must have it installed.
|
||||||
|
5. **Style rules** - anything the drafter must preserve when filling the template: color scheme, section order, heading style, spacing conventions, bullet formatting, date format.
|
||||||
|
6. **Page limit** - hard page count for the compiled PDF. Default: **2 pages** for a CV, **1 page** for a cover letter. `/apply`'s compile-and-inspect loop enforces this.
|
||||||
|
7. **Known pitfalls** (optional) - macros/rules that break with certain content (like the stock template's `\lettercontent{}`/`itemize` interaction), characters that need escaping, sections that must not be reordered.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -90,23 +96,24 @@ Create the template folder:
|
|||||||
|
|
||||||
Write into it:
|
Write into it:
|
||||||
|
|
||||||
1. **`template.tex`** - the template skeleton. Replace all personal data in the source with `[PLACEHOLDER]` tokens (`[YOUR_NAME]`, `[YOUR_EMAIL]`, `[YOUR_PHONE]`, `[YOUR_LINKEDIN_URL]`, ...) so the template is shareable and profile-agnostic. Keep the structure, preamble, and styling exactly as provided.
|
1. **`template<source-extension>`** (e.g. `template.tex`, `template.typ`) - the template skeleton. Replace all personal data in the source with `[PLACEHOLDER]` tokens (`[YOUR_NAME]`, `[YOUR_EMAIL]`, `[YOUR_PHONE]`, `[YOUR_LINKEDIN_URL]`, ...) so the template is shareable and profile-agnostic. Keep the structure, preamble, and styling exactly as provided.
|
||||||
2. **Class/style files** - copy any `.cls`/`.sty` files alongside `template.tex`.
|
2. **Class/style/package files** - copy any companion files (`.cls`/`.sty` for LaTeX, local Typst packages, or equivalents) alongside the skeleton.
|
||||||
3. **`fonts/`** - copy bundled font files here, preserving any directory layout the `\fontspec` `Path` options expect. Adjust `Path` values in `template.tex` to be relative to the template folder.
|
3. **`fonts/`** - copy bundled font files here, preserving any directory layout the toolchain's font-loading mechanism expects (LaTeX `\fontspec` `Path`, Typst font path, ...). Adjust those path values in the skeleton to be relative to the template folder.
|
||||||
4. **`TEMPLATE.md`** - the manifest. Use exactly this format:
|
4. **`TEMPLATE.md`** - the manifest. Use exactly this format:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# Template: <name>
|
# Template: <name>
|
||||||
|
|
||||||
- **Type:** CV | Cover letter
|
- **Type:** CV | Cover letter
|
||||||
- **Engine:** lualatex | xelatex | pdflatex
|
- **Source extension:** .tex | .typ | ...
|
||||||
|
- **Engine/toolchain:** lualatex | xelatex | pdflatex | typst | <other> (display label only)
|
||||||
- **Page limit:** <N> page(s)
|
- **Page limit:** <N> page(s)
|
||||||
- **Fonts:** <main font> (<bundled in fonts/ | system font - must be installed>)
|
- **Fonts:** <main font> (<bundled in fonts/ | system font - must be installed>)
|
||||||
- **Class/packages:** <documentclass and any non-standard packages, or "standard">
|
- **Class/packages:** <documentclass/imports and any non-standard packages, or "standard">
|
||||||
|
|
||||||
## Compile command
|
## Compile command
|
||||||
|
|
||||||
cd <output dir> && <engine> -interaction=nonstopmode <file>.tex
|
cd <output dir> && <the full declared command, e.g. lualatex -interaction=nonstopmode <file>.tex or typst compile <file>.typ <file>.pdf>
|
||||||
|
|
||||||
## Style rules
|
## Style rules
|
||||||
|
|
||||||
@@ -122,16 +129,16 @@ Write into it:
|
|||||||
|
|
||||||
## Step 4: Verify the Template Compiles (MANDATORY)
|
## Step 4: Verify the Template Compiles (MANDATORY)
|
||||||
|
|
||||||
Never register a template without a successful test compile. LaTeX templates that "look fine" routinely fail on missing fonts, missing classes, or engine mismatches.
|
Never register a template without a successful test compile. Templates that "look fine" routinely fail on missing fonts, missing classes/packages, or a wrong compile command.
|
||||||
|
|
||||||
1. Copy `template.tex` to a scratch file in the same folder (e.g. `_compile_test.tex`) and fill every `[PLACEHOLDER]` with realistic dummy data (name, contact line, one education entry, one job entry with 3 bullets — enough content to exercise the layout).
|
1. Copy `template<source-extension>` to a scratch file in the same folder (e.g. `_compile_test.tex` or `_compile_test.typ`) and fill every `[PLACEHOLDER]` with realistic dummy data (name, contact line, one education entry, one job entry with 3 bullets — enough content to exercise the layout).
|
||||||
2. Compile with the declared engine:
|
2. Compile with the declared compile command, substituting `_compile_test` for `<file>`:
|
||||||
```bash
|
```bash
|
||||||
cd templates/<type>/<name> && <engine> -interaction=nonstopmode _compile_test.tex
|
cd templates/<type>/<name> && <declared compile command with <file> -> _compile_test>
|
||||||
```
|
```
|
||||||
3. If the compile fails: show the user the relevant error lines, diagnose (missing font file, wrong engine, missing class), fix what you can (e.g. font `Path` values), and re-compile. If the fix needs input only the user has (a missing font file, a license-restricted class), ask for it and wait.
|
3. If the compile fails: show the user the relevant error lines, diagnose (missing font file, wrong engine/command, missing class or package), fix what you can (e.g. font path values), and re-compile. If the fix needs input only the user has (a missing font file, a license-restricted class), ask for it and wait.
|
||||||
4. On success, Read the PDF and confirm the layout renders sensibly (no overlapping text, fonts loaded, page count plausible for dummy content). Record any surprises in the manifest's "Known pitfalls".
|
4. On success, confirm a PDF was produced and Read it to check the layout renders sensibly (no overlapping text, fonts loaded, page count matches the declared page limit for the dummy content). Record any surprises in the manifest's "Known pitfalls".
|
||||||
5. Delete the scratch files and generated artifacts for the test compile: `_compile_test.tex`, `_compile_test.pdf`, `_compile_test.aux`, `_compile_test.log`, `_compile_test.out`, `_compile_test.fls`, `_compile_test.fdb_latexmk`, `_compile_test.synctex.gz`, and any other `_compile_test.*` byproducts.
|
5. Delete the scratch source file, the scratch PDF, and any other intermediate files the compile command produced (LaTeX toolchains typically leave `_compile_test.aux`/`.log`/`.out`/`.fls`/`.fdb_latexmk`/`.synctex.gz`; other toolchains may leave nothing beyond the PDF — check what actually landed in the folder and remove all `_compile_test.*` byproducts).
|
||||||
|
|
||||||
Do not proceed to Step 5 until the test compile passes.
|
Do not proceed to Step 5 until the test compile passes.
|
||||||
|
|
||||||
@@ -139,7 +146,7 @@ Do not proceed to Step 5 until the test compile passes.
|
|||||||
|
|
||||||
## Step 5: Activate the Template
|
## Step 5: Activate the Template
|
||||||
|
|
||||||
Activation wires the template into `/apply` by adding a **managed block** to the top of the relevant guidance file — `05-cv-templates.md` for CVs, `06-cover-letter-templates.md` for cover letters. `/apply` reads these files in its drafting step, so the block is all it takes.
|
Activation wires the template into `/apply` by adding a **managed block** to the top of the relevant guidance file — `05-cv-templates.md` for CVs, `06-cover-letter-templates.md` for cover letters. `/apply` reads these files in both its drafting step and its compile step, so the block is all it takes.
|
||||||
|
|
||||||
If Step 5 was reached from Switch Mode, use the template metadata resolved from `TEMPLATE.md`. If Step 5 was reached after registering a new template, use the metadata collected and verified in Steps 2-4.
|
If Step 5 was reached from Switch Mode, use the template metadata resolved from `TEMPLATE.md`. If Step 5 was reached after registering a new template, use the metadata collected and verified in Steps 2-4.
|
||||||
|
|
||||||
@@ -151,12 +158,13 @@ Insert (or replace, if one exists) this block immediately after the file's H1 ti
|
|||||||
>
|
>
|
||||||
> A custom template is active. Where this block conflicts with the stock guidance below, this block wins. Structural advice below (tailoring, page-budget, cutting rules) still applies.
|
> A custom template is active. Where this block conflicts with the stock guidance below, this block wins. Structural advice below (tailoring, page-budget, cutting rules) still applies.
|
||||||
>
|
>
|
||||||
> - **Template skeleton:** `templates/<type>/<name>/template.tex` — use this as the structural reference instead of the stock template
|
> - **Template skeleton:** `templates/<type>/<name>/template<source-extension>` — use this as the structural reference instead of the stock template
|
||||||
> - **Manifest:** `templates/<type>/<name>/TEMPLATE.md` — read this for style rules and known pitfalls before drafting
|
> - **Manifest:** `templates/<type>/<name>/TEMPLATE.md` — read this for style rules and known pitfalls before drafting
|
||||||
> - **Compile with:** `<engine>` (not the engine named in the stock guidance below)
|
> - **Source extension:** `<source-extension>` (not `.tex` unless the template's own toolchain is LaTeX)
|
||||||
> - **Fonts:** <font summary, including any Path note for bundled fonts>
|
> - **Compile command:** `<the full declared command>` (not the command named in the stock guidance below — `/apply`'s compile step must use this instead)
|
||||||
|
> - **Fonts:** <font summary, including any path note for bundled fonts>
|
||||||
> - **Page limit:** exactly <N> page(s)
|
> - **Page limit:** exactly <N> page(s)
|
||||||
> - **Output file:** unchanged (`cv/main_<company>_<role>.tex` / `cover_letters/cover_<company>_<role>.tex`); copy any class/font files the template needs into the output directory, or reference them by relative path
|
> - **Output file:** `cv/main_<company>_<role><source-extension>` / `cover_letters/cover_<company>_<role><source-extension>`; copy any class/package/font files the template needs into the output directory, or reference them by relative path
|
||||||
<!-- END ACTIVE-TEMPLATE -->
|
<!-- END ACTIVE-TEMPLATE -->
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -174,8 +182,8 @@ Present a summary:
|
|||||||
|
|
||||||
> **Template `<name>` registered and activated.**
|
> **Template `<name>` registered and activated.**
|
||||||
>
|
>
|
||||||
> - Files: `templates/<type>/<name>/` (skeleton, manifest<, class files><, fonts>)
|
> - Files: `templates/<type>/<name>/` (skeleton, manifest<, class/package files><, fonts>)
|
||||||
> - Test compile: passed with `<engine>` (<N> page(s))
|
> - Test compile: passed with `<compile command>` (<N> page(s))
|
||||||
> - `/apply` will now draft <CVs | cover letters> from this template.
|
> - `/apply` will now draft <CVs | cover letters> from this template.
|
||||||
>
|
>
|
||||||
> Useful follow-ups:
|
> Useful follow-ups:
|
||||||
|
|||||||
+23
-18
@@ -14,7 +14,7 @@ This rule is the input side of the Step 3 Factual Grounding Audit, not a competi
|
|||||||
- Never re-Read a file whose contents are already in your context from an earlier step. If you read it in Step 1, it is still available in Step 2.
|
- Never re-Read a file whose contents are already in your context from an earlier step. If you read it in Step 1, it is still available in Step 2.
|
||||||
- When dispatching the reviewer agent, pass draft content **inline in the agent prompt** rather than asking the agent to Read files you already have in memory.
|
- When dispatching the reviewer agent, pass draft content **inline in the agent prompt** rather than asking the agent to Read files you already have in memory.
|
||||||
- Run the full verification checklist exactly once, at the end (Step 6). The reviewer focuses on content critique, not verification.
|
- Run the full verification checklist exactly once, at the end (Step 6). The reviewer focuses on content critique, not verification.
|
||||||
- Step 5 (compile and inspect PDFs) is mandatory and non-skippable — LaTeX page-break decisions are unpredictable, and `.tex` files that look fine often produce broken PDFs (orphaned entry titles, cover letters spilling to page 2, bullet fonts mismatching).
|
- Step 5 (compile and inspect PDFs) is mandatory and non-skippable — page-break decisions are unpredictable, and source files that look fine often produce broken PDFs (orphaned entry titles, cover letters spilling to page 2, bullet fonts mismatching).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -66,9 +66,11 @@ Read only the reference files you do not yet have:
|
|||||||
- `.claude/skills/job-application-assistant/05-cv-templates.md`
|
- `.claude/skills/job-application-assistant/05-cv-templates.md`
|
||||||
- `.claude/skills/job-application-assistant/06-cover-letter-templates.md`
|
- `.claude/skills/job-application-assistant/06-cover-letter-templates.md`
|
||||||
|
|
||||||
|
**Resolve the active template (do this once, reuse everywhere below):** if `05-cv-templates.md` or `06-cover-letter-templates.md` opens with an `ACTIVE-TEMPLATE` managed block (inserted by `/add-template`), read its declared **source extension** and **compile command** — these override the stock `.tex`/lualatex (CV) and `.tex`/xelatex (cover letter) defaults for the rest of this workflow. Call these `<CV_EXT>`/`<CV_COMPILE>` and `<COVER_EXT>`/`<COVER_COMPILE>`; where no block is present, they default to `.tex`, the stock lualatex command, and the stock xelatex command respectively. Every `.tex` reference below is really `<CV_EXT>` or `<COVER_EXT>` — stock behavior is unchanged, this only matters when a custom template is active.
|
||||||
|
|
||||||
Also read the most recent existing CV and cover letter files for concrete structural reference (one of each is enough):
|
Also read the most recent existing CV and cover letter files for concrete structural reference (one of each is enough):
|
||||||
- Read any existing `cv/main_*.tex` file as a LaTeX template reference
|
- Read any existing `cv/main_*<CV_EXT>` file as a structural reference
|
||||||
- Read any existing `cover_letters/cover_*.tex` or `cover_letters/Cover_*.tex` file as a template reference
|
- Read any existing `cover_letters/cover_*<COVER_EXT>` or `cover_letters/Cover_*<COVER_EXT>` file as a structural reference
|
||||||
|
|
||||||
*The master candidate profile (`01-candidate-profile.md`), the master CV (`cv/main_example.tex`), and CLAUDE.md's Candidate Profile section are the sole source of truth for facts; existing tailored CVs may be read for structure and phrasing only, never as a source of claims.*
|
*The master candidate profile (`01-candidate-profile.md`), the master CV (`cv/main_example.tex`), and CLAUDE.md's Candidate Profile section are the sole source of truth for facts; existing tailored CVs may be read for structure and phrasing only, never as a source of claims.*
|
||||||
|
|
||||||
@@ -77,7 +79,7 @@ Also read the most recent existing CV and cover letter files for concrete struct
|
|||||||
- **Engage nice-to-haves by name** where the profile supports honest adjacency (e.g. "conceptually aligned with <named tool>"), and use the posting's own term over a synonym wherever it is truthfully applicable - including in CV section headings (a posting hiring for "MLOps" should find a heading containing "MLOps", not only a paraphrase).
|
- **Engage nice-to-haves by name** where the profile supports honest adjacency (e.g. "conceptually aligned with <named tool>"), and use the posting's own term over a synonym wherever it is truthfully applicable - including in CV section headings (a posting hiring for "MLOps" should find a heading containing "MLOps", not only a paraphrase).
|
||||||
- **Address stated logistics and prerequisites** in the cover letter where the posting raises them: security clearance willingness, start date or availability, commute or location fit, and the posting's reference/job ID where one exists. When the employer operates across several countries, a truthful language-capabilities sentence mapped to their footprint is high-value targeting.
|
- **Address stated logistics and prerequisites** in the cover letter where the posting raises them: security clearance willingness, start date or availability, commute or location fit, and the posting's reference/job ID where one exists. When the employer operates across several countries, a truthful language-capabilities sentence mapped to their footprint is high-value targeting.
|
||||||
|
|
||||||
### CV (`cv/main_<company>_<role>.tex`)
|
### CV (`cv/main_<company>_<role><CV_EXT>`)
|
||||||
- In the **CV language from the profile** (the `CV language:` line in CLAUDE.md's Identity section). When the profile does not set one, default to **English**. Never switch language per posting - the CV language is a profile-level choice, so all CVs stay consistent and reusable
|
- In the **CV language from the profile** (the `CV language:` line in CLAUDE.md's Identity section). When the profile does not set one, default to **English**. Never switch language per posting - the CV language is a profile-level choice, so all CVs stay consistent and reusable
|
||||||
- Follow the moderncv/banking format from `05-cv-templates.md`
|
- Follow the moderncv/banking format from `05-cv-templates.md`
|
||||||
- Tailor the profile statement and experience bullets to the specific role
|
- Tailor the profile statement and experience bullets to the specific role
|
||||||
@@ -85,7 +87,7 @@ Also read the most recent existing CV and cover letter files for concrete struct
|
|||||||
- Keep to 2 pages
|
- Keep to 2 pages
|
||||||
- **Grounding Audit:** Before writing to disk, audit all tailored bullet points against the union of three sources: `.claude/skills/job-application-assistant/01-candidate-profile.md` + the master CV (`cv/main_example.tex`) + `CLAUDE.md`'s Candidate Profile section to verify that all dates, roles, and metrics match exactly (zero profile drift or fabrication).
|
- **Grounding Audit:** Before writing to disk, audit all tailored bullet points against the union of three sources: `.claude/skills/job-application-assistant/01-candidate-profile.md` + the master CV (`cv/main_example.tex`) + `CLAUDE.md`'s Candidate Profile section to verify that all dates, roles, and metrics match exactly (zero profile drift or fabrication).
|
||||||
|
|
||||||
### Cover Letter (`cover_letters/cover_<company>_<role>.tex`)
|
### Cover Letter (`cover_letters/cover_<company>_<role><COVER_EXT>`)
|
||||||
- **Match the language of the job posting** (Danish posting -> Danish cover letter, English posting -> English cover letter)
|
- **Match the language of the job posting** (Danish posting -> Danish cover letter, English posting -> English cover letter)
|
||||||
- Follow the structure from `06-cover-letter-templates.md`
|
- Follow the structure from `06-cover-letter-templates.md`
|
||||||
- Use the `cover.cls` template
|
- Use the `cover.cls` template
|
||||||
@@ -100,7 +102,7 @@ Write both files to disk. Keep the exact text of both drafts in working memory
|
|||||||
|
|
||||||
## Step 3: REVIEWER - Research & Critique
|
## Step 3: REVIEWER - Research & Critique
|
||||||
|
|
||||||
Use the **Agent tool** to spawn a `general-purpose` reviewer agent. The reviewer gets a fresh context, so pass the drafts **inline in the prompt** below (do not make the reviewer Read them). Scope the reviewer's file reads to content-critique essentials only — the reviewer does not need the LaTeX template files (`05`, `06`) to critique content, since those govern structural/LaTeX concerns the drafter already applied.
|
Use the **Agent tool** to spawn a `general-purpose` reviewer agent. The reviewer gets a fresh context, so pass the drafts **inline in the prompt** below (do not make the reviewer Read them). Scope the reviewer's file reads to content-critique essentials only — the reviewer does not need the template structure files (`05`, `06`) to critique content, since those govern structural/toolchain concerns the drafter already applied.
|
||||||
|
|
||||||
Replace `<COMPANY>`, `<ROLE>`, `<INSERT_JOB_POSTING_TEXT_HERE>`, `<INSERT_CV_DRAFT_HERE>`, and `<INSERT_COVER_LETTER_DRAFT_HERE>` with actual values before dispatching.
|
Replace `<COMPANY>`, `<ROLE>`, `<INSERT_JOB_POSTING_TEXT_HERE>`, `<INSERT_CV_DRAFT_HERE>`, and `<INSERT_COVER_LETTER_DRAFT_HERE>` with actual values before dispatching.
|
||||||
|
|
||||||
@@ -128,7 +130,7 @@ Read these reference files — and only these — to ground your critique:
|
|||||||
- The master CV baseline template (`cv/main_example.tex`)
|
- The master CV baseline template (`cv/main_example.tex`)
|
||||||
- The workspace root `CLAUDE.md` file (specifically the Candidate Profile section)
|
- The workspace root `CLAUDE.md` file (specifically the Candidate Profile section)
|
||||||
|
|
||||||
Do NOT read `05-cv-templates.md` or `06-cover-letter-templates.md` — those govern LaTeX structure the drafter already applied and are not needed for content critique.
|
Do NOT read `05-cv-templates.md` or `06-cover-letter-templates.md` — those govern template structure the drafter already applied and are not needed for content critique.
|
||||||
|
|
||||||
### 3. Factual Grounding Audit
|
### 3. Factual Grounding Audit
|
||||||
Compare every date, employer, job title, and quantitative metric in both drafts against the union of three sources: `.claude/skills/job-application-assistant/01-candidate-profile.md` + the master CV baseline template (`cv/main_example.tex`) + `CLAUDE.md`'s Candidate Profile section. A claim is grounded if ANY of these sources supports it. Mismatches between these three sources themselves must be reported to the user as a profile-consistency warning rather than treated as draft drift. Draft mismatches must be flagged as Part A edits with `"reason": "grounding"` so they can be distinguished from style changes. Keep the tolerance honest: reframed emphasis is fine; changed facts and escalated numbers are not.
|
Compare every date, employer, job title, and quantitative metric in both drafts against the union of three sources: `.claude/skills/job-application-assistant/01-candidate-profile.md` + the master CV baseline template (`cv/main_example.tex`) + `CLAUDE.md`'s Candidate Profile section. A claim is grounded if ANY of these sources supports it. Mismatches between these three sources themselves must be reported to the user as a profile-consistency warning rather than treated as draft drift. Draft mismatches must be flagged as Part A edits with `"reason": "grounding"` so they can be distinguished from style changes. Keep the tolerance honest: reframed emphasis is fine; changed facts and escalated numbers are not.
|
||||||
@@ -136,11 +138,11 @@ Compare every date, employer, job title, and quantitative metric in both drafts
|
|||||||
### 4. Drafts to Review
|
### 4. Drafts to Review
|
||||||
Both drafts are provided inline below. Do NOT use the Read tool on the draft files — use these exact texts.
|
Both drafts are provided inline below. Do NOT use the Read tool on the draft files — use these exact texts.
|
||||||
|
|
||||||
<CV_DRAFT file="cv/main_<COMPANY>_<ROLE>.tex">
|
<CV_DRAFT file="cv/main_<COMPANY>_<ROLE><CV_EXT>">
|
||||||
<INSERT_CV_DRAFT_HERE>
|
<INSERT_CV_DRAFT_HERE>
|
||||||
</CV_DRAFT>
|
</CV_DRAFT>
|
||||||
|
|
||||||
<COVER_LETTER_DRAFT file="cover_letters/cover_<COMPANY>_<ROLE>.tex">
|
<COVER_LETTER_DRAFT file="cover_letters/cover_<COMPANY>_<ROLE><COVER_EXT>">
|
||||||
<INSERT_COVER_LETTER_DRAFT_HERE>
|
<INSERT_COVER_LETTER_DRAFT_HERE>
|
||||||
</COVER_LETTER_DRAFT>
|
</COVER_LETTER_DRAFT>
|
||||||
|
|
||||||
@@ -157,7 +159,7 @@ Return your feedback in **two parts**:
|
|||||||
A JSON array of concrete edits the drafter can apply directly without re-reading the files. Each edit is an object:
|
A JSON array of concrete edits the drafter can apply directly without re-reading the files. Each edit is an object:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"file": "cv/main_<COMPANY>_<ROLE>.tex" | "cover_letters/cover_<COMPANY>_<ROLE>.tex",
|
"file": "cv/main_<COMPANY>_<ROLE><CV_EXT>" | "cover_letters/cover_<COMPANY>_<ROLE><COVER_EXT>",
|
||||||
"old_string": "<exact text currently in the draft>",
|
"old_string": "<exact text currently in the draft>",
|
||||||
"new_string": "<replacement text>",
|
"new_string": "<replacement text>",
|
||||||
"reason": "<one-line rationale: keyword match / company angle / reframing / style / grounding>"
|
"reason": "<one-line rationale: keyword match / company angle / reframing / style / grounding>"
|
||||||
@@ -200,17 +202,20 @@ After all edits are applied, the two files on disk are the final drafts.
|
|||||||
|
|
||||||
## Step 5: DRAFTER - Compile & Inspect PDFs (MANDATORY)
|
## Step 5: DRAFTER - Compile & Inspect PDFs (MANDATORY)
|
||||||
|
|
||||||
**Never skip this step.** The `.tex` files looking fine is not sufficient — LaTeX page-break decisions are unpredictable and commonly produce broken layouts (orphaned job titles separated from their bullets, cover letters spilling to 2 pages, bullet fonts not matching body text). Compile both documents and visually verify the PDFs before presenting.
|
**Never skip this step.** The source files looking fine is not sufficient — page-break decisions are unpredictable and commonly produce broken layouts (orphaned job titles separated from their bullets, cover letters spilling to 2 pages, bullet fonts not matching body text). Compile both documents and visually verify the PDFs before presenting.
|
||||||
|
|
||||||
### 5a. Compile
|
### 5a. Compile
|
||||||
|
|
||||||
|
Use `<CV_COMPILE>` and `<COVER_COMPILE>` resolved in Step 2 (the active template's declared compile command, or the stock defaults below if no custom template is active):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd cv && lualatex -interaction=nonstopmode main_<company>_<role>.tex
|
cd cv && lualatex -interaction=nonstopmode main_<company>_<role>.tex
|
||||||
cd ../cover_letters && xelatex -interaction=nonstopmode cover_<company>_<role>.tex
|
cd ../cover_letters && xelatex -interaction=nonstopmode cover_<company>_<role>.tex
|
||||||
```
|
```
|
||||||
|
|
||||||
- CV uses **lualatex** — pdflatex fails on modern MiKTeX with fontawesome5 font-expansion errors. lualatex handles the same sources cleanly.
|
- **Stock CV** uses **lualatex** — pdflatex fails on modern MiKTeX with fontawesome5 font-expansion errors. lualatex handles the same sources cleanly.
|
||||||
- Cover letter uses **xelatex** — cover.cls requires fontspec.
|
- **Stock cover letter** uses **xelatex** — cover.cls requires fontspec.
|
||||||
|
- **Custom template active:** run its declared `<CV_COMPILE>`/`<COVER_COMPILE>` command instead, substituting the actual filename for `<file>`. Never fall back to lualatex/xelatex when a custom template's compile command is a different toolchain (e.g. `typst compile`) — that command is what the manifest actually verified in `/add-template` Step 4.
|
||||||
|
|
||||||
If either compile fails, fix the error and re-compile until clean.
|
If either compile fails, fix the error and re-compile until clean.
|
||||||
|
|
||||||
@@ -231,7 +236,7 @@ Read both PDFs via the Read tool and verify:
|
|||||||
|
|
||||||
### 5c. Iterate until clean
|
### 5c. Iterate until clean
|
||||||
|
|
||||||
If the layout has problems, edit the `.tex` files and recompile. Common fixes (see `05-cv-templates.md` and `06-cover-letter-templates.md` for full details):
|
If the layout has problems, edit the source files (`<CV_EXT>`/`<COVER_EXT>`) and recompile. Common fixes below are **LaTeX-specific** (stock templates, or a custom LaTeX template) — see `05-cv-templates.md` and `06-cover-letter-templates.md` for full details, and consult the active template's own manifest ("Known pitfalls") for a non-LaTeX toolchain:
|
||||||
|
|
||||||
- **Orphaned CV entry title:** `\usepackage{needspace}` in preamble, then `\needspace{5\baselineskip}` immediately before the problematic `\cventry`
|
- **Orphaned CV entry title:** `\usepackage{needspace}` in preamble, then `\needspace{5\baselineskip}` immediately before the problematic `\cventry`
|
||||||
- **CV spills to page 3 with only a trailing section:** `\enlargethispage{2-3\baselineskip}` before a late section
|
- **CV spills to page 3 with only a trailing section:** `\enlargethispage{2-3\baselineskip}` before a late section
|
||||||
@@ -262,7 +267,7 @@ Read the `.txt` file.
|
|||||||
- [ ] **Reading order matches the visual order** — section headings appear in the same sequence as on the page, and lines from different sections are not interleaved. The stock banking template is single-column and safe; custom templates registered via `/add-template` with sidebars or multi-column layouts are where this breaks.
|
- [ ] **Reading order matches the visual order** — section headings appear in the same sequence as on the page, and lines from different sections are not interleaved. The stock banking template is single-column and safe; custom templates registered via `/add-template` with sidebars or multi-column layouts are where this breaks.
|
||||||
- [ ] **Dates recognizable** — each role and degree has its years present in the extraction.
|
- [ ] **Dates recognizable** — each role and degree has its years present in the extraction.
|
||||||
|
|
||||||
Failures here are template-level problems: fix them in the `.tex` (e.g. print the email as text rather than icon-only), then re-run 5a–5c and re-extract. If a custom template's layout fundamentally scrambles extraction order, tell the user prominently — they may be trading ATS compatibility for looks.
|
Failures here are template-level problems: fix them in the `<CV_EXT>` source (e.g. print the email as text rather than icon-only), then re-run 5a–5c and re-extract. If a custom template's layout fundamentally scrambles extraction order, tell the user prominently — they may be trading ATS compatibility for looks.
|
||||||
|
|
||||||
**3. Keyword coverage.** Reuse the required/preferred keyword list you extracted in Step 1 — do not re-derive it. Match each keyword against the extracted text, **in the posting's language** (when the posting's language differs from the CV language — e.g. a Danish posting against an English CV — a concept the CV legitimately covers in its own language counts as synonym-only; note the language difference). Report a table:
|
**3. Keyword coverage.** Reuse the required/preferred keyword list you extracted in Step 1 — do not re-derive it. Match each keyword against the extracted text, **in the posting's language** (when the posting's language differs from the CV language — e.g. a Danish posting against an English CV — a concept the CV legitimately covers in its own language counts as synonym-only; note the language difference). Report a table:
|
||||||
|
|
||||||
@@ -279,7 +284,7 @@ Failures here are template-level problems: fix them in the `.tex` (e.g. print th
|
|||||||
|
|
||||||
### 5e. Clean up build artifacts
|
### 5e. Clean up build artifacts
|
||||||
|
|
||||||
After the final clean compile, delete the `.aux`, `.log`, `.out` files (keep the `.tex` and `.pdf`).
|
After the final clean compile, delete intermediate build files the compile command left behind — LaTeX toolchains leave `.aux`/`.log`/`.out`; a custom template's toolchain may leave nothing beyond the PDF. Keep the source file and the `.pdf`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -299,8 +304,8 @@ Summarize 3-5 key decisions made to tailor the application:
|
|||||||
|
|
||||||
### Files Created
|
### Files Created
|
||||||
List the files written:
|
List the files written:
|
||||||
- `cv/main_<company>_<role>.tex`
|
- `cv/main_<company>_<role><CV_EXT>`
|
||||||
- `cover_letters/cover_<company>_<role>.tex`
|
- `cover_letters/cover_<company>_<role><COVER_EXT>`
|
||||||
|
|
||||||
Tell the user: "Both files are ready for your review. Open them to check the final output before compiling."
|
Tell the user: "Both files are ready for your review. Open them to check the final output before compiling."
|
||||||
|
|
||||||
|
|||||||
+9
-3
@@ -50,11 +50,17 @@ Thumbs.db
|
|||||||
skills-lock.json
|
skills-lock.json
|
||||||
|
|
||||||
# Personal application output files (generated by /apply — do not share)
|
# Personal application output files (generated by /apply — do not share)
|
||||||
cv/main_*.tex
|
# Extension-agnostic on the ignore side: a custom template registered via
|
||||||
|
# /add-template (e.g. Typst) writes main_<company>_<role>.typ instead of
|
||||||
|
# .tex, and it must be ignored just as reliably as the stock LaTeX output.
|
||||||
|
# The negations stay .tex-only - the stock example files are always LaTeX,
|
||||||
|
# and a wildcard negation (!cv/main_example.*) would also re-include build
|
||||||
|
# artifacts like main_example.pdf/.aux.
|
||||||
|
cv/main_*.*
|
||||||
!cv/main_example.tex
|
!cv/main_example.tex
|
||||||
cv/*.txt
|
cv/*.txt
|
||||||
cover_letters/cover_*.tex
|
cover_letters/cover_*.*
|
||||||
cover_letters/Cover_*.tex
|
cover_letters/Cover_*.*
|
||||||
!cover_letters/cover_example.tex
|
!cover_letters/cover_example.tex
|
||||||
|
|
||||||
# documents/ subfolder contents are personal — only README and folder structure are tracked
|
# documents/ subfolder contents are personal — only README and folder structure are tracked
|
||||||
|
|||||||
+4
-1
@@ -13,7 +13,10 @@ per-file diff commands.
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
_Changes landed on `master` since the last release will be listed here._
|
- **Custom templates: any compile-to-PDF toolchain (Typst, ...)** - `/add-template` no longer
|
||||||
|
hardcodes a `lualatex`/`xelatex`/`pdflatex` engine enum. Custom templates now declare a
|
||||||
|
source extension and a full compile command, so Typst (`typst compile`) registers the same
|
||||||
|
way a custom LaTeX template does. Stock CV/cover letter templates stay LaTeX, unchanged.
|
||||||
|
|
||||||
## [1.0.0] - 2026-07-22
|
## [1.0.0] - 2026-07-22
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ After creating or updating a CV or cover letter, re-read the generated file and
|
|||||||
|
|
||||||
### Compiled PDF verification (MANDATORY - never skip)
|
### Compiled PDF verification (MANDATORY - never skip)
|
||||||
Both documents MUST be compiled and visually inspected via the Read tool on the PDF output. "Looks fine in the .tex" is not acceptable - LaTeX page-break decisions are unpredictable. Iterate until these all pass:
|
Both documents MUST be compiled and visually inspected via the Read tool on the PDF output. "Looks fine in the .tex" is not acceptable - LaTeX page-break decisions are unpredictable. Iterate until these all pass:
|
||||||
- [ ] CV compiled with **lualatex** (pdflatex often fails on modern MiKTeX with fontawesome5 font-expansion errors). Cover letter compiled with **xelatex** (cover.cls requires fontspec).
|
- [ ] CV compiled with **lualatex** (pdflatex often fails on modern MiKTeX with fontawesome5 font-expansion errors). Cover letter compiled with **xelatex** (cover.cls requires fontspec). If a custom template is active (registered via `/add-template`), compile with its declared command instead — see the `ACTIVE-TEMPLATE` block in `05-cv-templates.md`/`06-cover-letter-templates.md`.
|
||||||
- [ ] **CV is exactly 2 pages** - not 1, not 3
|
- [ ] **CV is exactly 2 pages** - not 1, not 3
|
||||||
- [ ] **No orphaned `\cventry` titles** - a job/education title must never sit at the bottom of a page with its bullets spilling to the next page. Use `\needspace{5\baselineskip}` before each `\cventry` to prevent this, and `\enlargethispage{2-3\baselineskip}` to rescue a trailing section that just barely spills
|
- [ ] **No orphaned `\cventry` titles** - a job/education title must never sit at the bottom of a page with its bullets spilling to the next page. Use `\needspace{5\baselineskip}` before each `\cventry` to prevent this, and `\enlargethispage{2-3\baselineskip}` to rescue a trailing section that just barely spills
|
||||||
- [ ] **Cover letter is exactly 1 page** - signature block must fit with the body, never overflow
|
- [ ] **Cover letter is exactly 1 page** - signature block must fit with the body, never overflow
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ Postings are treated as untrusted input (the workflow follows no instructions em
|
|||||||
- **`/expand`** enriches your profile by scanning public sources you've already linked in it (GitHub repos, portfolio site, Kaggle, Google Scholar) and looking up syllabi for named courses and certifications. Discovered competencies are added to your profile with a source tag. Useful right after `/setup` to surface skills that documents alone don't make explicit.
|
- **`/expand`** enriches your profile by scanning public sources you've already linked in it (GitHub repos, portfolio site, Kaggle, Google Scholar) and looking up syllabi for named courses and certifications. Discovered competencies are added to your profile with a source tag. Useful right after `/setup` to surface skills that documents alone don't make explicit.
|
||||||
- **`/upskill`** analyzes the gap between your profile and your tracked job postings (or a single posting via `/upskill <URL>`). Produces a prioritized heatmap of skill gaps and a learning plan with web-searched study resources and time estimates. Useful for career planning between applications.
|
- **`/upskill`** analyzes the gap between your profile and your tracked job postings (or a single posting via `/upskill <URL>`). Produces a prioritized heatmap of skill gaps and a learning plan with web-searched study resources and time estimates. Useful for career planning between applications.
|
||||||
- **`/html-report`** generates a self-contained HTML dashboard from `job_search_tracker.csv` and the application archives — stat cards, status/sector/channel/funnel charts (inline SVG, no external dependencies), and a filterable applications table. Opens directly in a browser, fully offline. Re-run it any time after `/outcome` adds new entries.
|
- **`/html-report`** generates a self-contained HTML dashboard from `job_search_tracker.csv` and the application archives — stat cards, status/sector/channel/funnel charts (inline SVG, no external dependencies), and a filterable applications table. Opens directly in a browser, fully offline. Re-run it any time after `/outcome` adds new entries.
|
||||||
- **`/add-template`** registers your own LaTeX CV or cover letter template in place of the stock ones. It captures the template's instructions (compile engine, fonts, style rules, page limit), runs a mandatory test compile, and wires the template into `/apply`. See [LaTeX templates](#latex-templates) below.
|
- **`/add-template`** registers your own CV or cover letter template (LaTeX, Typst, or another toolchain) in place of the stock ones. It captures the template's instructions (source extension, compile command, fonts, style rules, page limit), runs a mandatory test compile, and wires the template into `/apply`. See [Custom templates](#custom-templates) below.
|
||||||
- **`/add-portal`** generates a job-portal search skill for a job board in your market. It investigates the portal (search URL pattern, result structure, access rules), scaffolds the CLI skill from the same structure as the shipped ones, and test-runs a live query before registering. See [Job search tools](#job-search-tools) below.
|
- **`/add-portal`** generates a job-portal search skill for a job board in your market. It investigates the portal (search URL pattern, result structure, access rules), scaffolds the CLI skill from the same structure as the shipped ones, and test-runs a live query before registering. See [Job search tools](#job-search-tools) below.
|
||||||
|
|
||||||
`/reset` is also available, see [Starting over](#starting-over) below.
|
`/reset` is also available, see [Starting over](#starting-over) below.
|
||||||
@@ -160,7 +160,7 @@ ai-job-search/
|
|||||||
│ │ ├── apply.md # /apply workflow (drafter-reviewer)
|
│ │ ├── apply.md # /apply workflow (drafter-reviewer)
|
||||||
│ │ ├── setup.md # /setup onboarding (documents folder, CV import, or interview)
|
│ │ ├── setup.md # /setup onboarding (documents folder, CV import, or interview)
|
||||||
│ │ ├── expand.md # /expand competency enrichment from documents and online presence
|
│ │ ├── expand.md # /expand competency enrichment from documents and online presence
|
||||||
│ │ ├── add-template.md # /add-template register custom LaTeX templates
|
│ │ ├── add-template.md # /add-template register custom templates (LaTeX, Typst, ...)
|
||||||
│ │ ├── add-portal.md # /add-portal generate a job-portal search skill for your market
|
│ │ ├── add-portal.md # /add-portal generate a job-portal search skill for your market
|
||||||
│ │ ├── rank.md # /rank triage scraped jobs into a ranked shortlist
|
│ │ ├── rank.md # /rank triage scraped jobs into a ranked shortlist
|
||||||
│ │ ├── outcome.md # /outcome record application results, archive materials
|
│ │ ├── outcome.md # /outcome record application results, archive materials
|
||||||
@@ -267,17 +267,17 @@ As your priorities evolve, you can reconfigure just the job search without re-ru
|
|||||||
|
|
||||||
This re-runs the search configuration interview: which roles to target, which skills to search for, which locations, and which portals. It also suggests role types you may not have considered based on your profile.
|
This re-runs the search configuration interview: which roles to target, which skills to search for, which locations, and which portals. It also suggests role types you may not have considered based on your profile.
|
||||||
|
|
||||||
### LaTeX templates
|
### Custom templates
|
||||||
|
|
||||||
The CV uses [moderncv](https://ctan.org/pkg/moderncv) (banking style). The cover letter uses a custom `cover.cls` with Lato/Raleway fonts.
|
The CV uses [moderncv](https://ctan.org/pkg/moderncv) (banking style). The cover letter uses a custom `cover.cls` with Lato/Raleway fonts. Both are LaTeX — the reference engine this repo ships and maintains.
|
||||||
|
|
||||||
To use your own template instead, run:
|
To use your own template instead — LaTeX, [Typst](https://typst.app/), or any other toolchain that compiles to PDF from the command line — run:
|
||||||
|
|
||||||
```
|
```
|
||||||
/add-template
|
/add-template
|
||||||
```
|
```
|
||||||
|
|
||||||
Point it at your `.tex` file (plus any `.cls`/`.sty` files or bundled fonts). The command interviews you for the template's instructions — compile engine, fonts and where they live, style rules to preserve, hard page limit — stores everything under `templates/`, runs a mandatory test compile, and activates the template so `/apply` drafts from it. Templates are stored with `[PLACEHOLDER]` tokens instead of personal data, so they're safe to commit and share.
|
Point it at your source file (a `.tex` file plus any `.cls`/`.sty` files or bundled fonts; a `.typ` file plus any local packages; or an equivalent for another toolchain). The command interviews you for the template's instructions — source extension, compile command, fonts and where they live, style rules to preserve, hard page limit — stores everything under `templates/`, runs a mandatory test compile, and activates the template so `/apply` drafts and compiles from it. Templates are stored with `[PLACEHOLDER]` tokens instead of personal data, so they're safe to commit and share.
|
||||||
|
|
||||||
- `/add-template --list` shows registered templates
|
- `/add-template --list` shows registered templates
|
||||||
- `/add-template --use <name>` switches between them
|
- `/add-template --use <name>` switches between them
|
||||||
|
|||||||
+6
-6
@@ -1,6 +1,6 @@
|
|||||||
# Custom Templates
|
# Custom Templates
|
||||||
|
|
||||||
This folder holds user-registered LaTeX templates, managed by the `/add-template` command. The framework works out of the box with its stock templates (moderncv for CVs, `cover.cls` for cover letters) — this folder only gets content when you register your own.
|
This folder holds user-registered templates (LaTeX, Typst, or any other toolchain with a declared compile command), managed by the `/add-template` command. The framework works out of the box with its stock templates (moderncv for CVs, `cover.cls` for cover letters) — this folder only gets content when you register your own.
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
@@ -8,9 +8,9 @@ This folder holds user-registered LaTeX templates, managed by the `/add-template
|
|||||||
templates/
|
templates/
|
||||||
├── cv/
|
├── cv/
|
||||||
│ └── <template-name>/
|
│ └── <template-name>/
|
||||||
│ ├── template.tex # Profile-agnostic skeleton ([PLACEHOLDER] tokens)
|
│ ├── template.<ext> # Profile-agnostic skeleton ([PLACEHOLDER] tokens), e.g. template.tex or template.typ
|
||||||
│ ├── TEMPLATE.md # Manifest: engine, fonts, page limit, style rules, pitfalls
|
│ ├── TEMPLATE.md # Manifest: source extension, compile command, fonts, page limit, style rules, pitfalls
|
||||||
│ ├── *.cls / *.sty # Custom class/style files (if the template needs them)
|
│ ├── *.cls / *.sty # Custom class/style files, or Typst packages (if the template needs them)
|
||||||
│ └── fonts/ # Bundled font files (if not using system fonts)
|
│ └── fonts/ # Bundled font files (if not using system fonts)
|
||||||
└── cover_letters/
|
└── cover_letters/
|
||||||
└── <template-name>/
|
└── <template-name>/
|
||||||
@@ -19,8 +19,8 @@ templates/
|
|||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
- `/add-template` interviews you for the template's instructions (compile engine, fonts, style rules, page limit), stores the files here, and runs a mandatory test compile before registering anything.
|
- `/add-template` interviews you for the template's instructions (source extension, compile command, fonts, style rules, page limit), stores the files here, and runs a mandatory test compile before registering anything.
|
||||||
- Activating a template adds a managed block to `05-cv-templates.md` or `06-cover-letter-templates.md`, which is what `/apply` reads when drafting — no other wiring needed.
|
- Activating a template adds a managed block to `05-cv-templates.md` or `06-cover-letter-templates.md`, which is what `/apply` reads when drafting and compiling — no other wiring needed.
|
||||||
- `/add-template --list` shows registered templates; `/add-template --use <name>` switches; `/add-template --use default` reverts to the stock templates.
|
- `/add-template --list` shows registered templates; `/add-template --use <name>` switches; `/add-template --use default` reverts to the stock templates.
|
||||||
|
|
||||||
Templates are stored with `[PLACEHOLDER]` tokens instead of personal data, so they are safe to commit and share.
|
Templates are stored with `[PLACEHOLDER]` tokens instead of personal data, so they are safe to commit and share.
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ REQUIRED_IGNORE_RULES = [
|
|||||||
# to its own directory, so the state file lands under .claude/skills/... and
|
# to its own directory, so the state file lands under .claude/skills/... and
|
||||||
# a repo-rooted rule silently fails to match it.
|
# a repo-rooted rule silently fails to match it.
|
||||||
"**/job_scraper/seen_jobs.json",
|
"**/job_scraper/seen_jobs.json",
|
||||||
"cv/main_*.tex",
|
"cv/main_*.*",
|
||||||
"!cv/main_example.tex",
|
"!cv/main_example.tex",
|
||||||
"cover_letters/cover_*.tex",
|
"cover_letters/cover_*.*",
|
||||||
"documents/cv/**",
|
"documents/cv/**",
|
||||||
"documents/linkedin/**",
|
"documents/linkedin/**",
|
||||||
"documents/diplomas/**",
|
"documents/diplomas/**",
|
||||||
|
|||||||
Reference in New Issue
Block a user