diff --git a/.claude/skills/resume-content-generation/SKILL.md b/.agents/skills/resume-content-generation/SKILL.md similarity index 93% rename from .claude/skills/resume-content-generation/SKILL.md rename to .agents/skills/resume-content-generation/SKILL.md index 0d04d50..d5b7bf5 100644 --- a/.claude/skills/resume-content-generation/SKILL.md +++ b/.agents/skills/resume-content-generation/SKILL.md @@ -3,20 +3,20 @@ name: resume-content-generation description: Use when resume strategy is set and you need to write or revise the resume's actual content — the format-agnostic resume_content.md (YAML + Markdown) that both the PDF and web renderers consume. Covers the summary, experience bullets, skills, highlights, and ATS keyword integration. Not for strategy/positioning decisions (resume-strategy) or for rendering to PDF/web (resume-render-*). --- -> **Bundled reference files.** Paths in this skill beginning with `docs/` or -> `resumes/templates/` are bundled with the plugin. When the plugin is installed, read -> them under `${CLAUDE_PLUGIN_ROOT}/` (e.g. `${CLAUDE_PLUGIN_ROOT}/docs/knowledge/…`) — the -> variable expands to the plugin's install directory automatically. When working from the -> source repository the variable is unset, so read the same paths relative to the repo root -> (exactly as written). Files under `resumes/customized/`, `resumes/compiled/`, and -> `docs/PERSONAL_PROFILE.md` are working files in the **current project**, not bundled. +> **Bundled reference files.** Paths beginning with `docs/` or `resumes/templates/` are +> bundled with this skill package and resolve relative to the **package (repository) root** — +> read them exactly as written when working inside the repo. If your agent installs the package +> outside the working directory and exposes its install root via a variable (e.g. Claude Code's +> `${CLAUDE_PLUGIN_ROOT}/`), prepend that. Files under `resumes/customized/`, +> `resumes/compiled/`, and `docs/PERSONAL_PROFILE.md` are working files in the **current +> project**, not bundled. You are an expert resume content generator specializing in transforming comprehensive personal profiles into targeted, compelling resume content. **Core Responsibility:** Generate `resume_content.md` files (YAML frontmatter + Markdown) from `docs/PERSONAL_PROFILE.md` data and strategic guidance. The generated file is format-agnostic and consumed by both the PDF renderer (`resume-render-pdf` skill) and the web renderer (`resume-render-web` skill). Your job is to create excellent content with strategic emphasis; renderers handle format-specific presentation. **Reference documents:** -- Personal profile schema: `.claude/skills/swiss-tech-resume-builder/references/personal_profile_schema.md` +- Personal profile schema: `.agents/skills/swiss-tech-resume-builder/references/personal_profile_schema.md` - ATS optimization guidelines: `docs/knowledge/ats_optimization.md` - Experience bullet budget & selection (shared with the reviewer): `docs/knowledge/experience_bullet_standards.md` - Tone & register — Swiss understatement, evidence over adjectives (shared with the reviewer): `docs/knowledge/tone_and_register.md` @@ -28,7 +28,7 @@ You are an expert resume content generator specializing in transforming comprehe Every **metric, named technology, scope figure, job title, date, and outcome** you put in `resume_content.md` MUST be traceable to a specific statement in `docs/PERSONAL_PROFILE.md`. Never invent, inflate, or approximate a number; never introduce a technology, employer, team size, or responsibility the profile does not support. When the profile lacks a number that would strengthen a bullet, **surface the gap** — tell the user and append it to `docs/MISSING_INFORMATION.md` (the durable profile-gap ledger the `resume-profile-coach` skill owns; check it first so you don't duplicate an item) rather than filling it. A missing metric is acceptable, an invented one is not. -This is the same rule the reviewer (`resume-content-review` / `swiss-tech-resume-reviewer`) verifies, and a confirmed ungrounded claim is an automatic review **fail**. The full standard — definitions, examples, and gate consequences — lives in `docs/knowledge/grounding_and_truthfulness.md` and is the single source of truth; read it before generating, and do not restate or soften it here. Reframing, emphasis, ATS-aligned wording, and responsibility→achievement transformation of **true** facts remain encouraged. +This is the same rule the reviewer (`resume-content-review`) verifies, and a confirmed ungrounded claim is an automatic review **fail**. The full standard — definitions, examples, and gate consequences — lives in `docs/knowledge/grounding_and_truthfulness.md` and is the single source of truth; read it before generating, and do not restate or soften it here. Reframing, emphasis, ATS-aligned wording, and responsibility→achievement transformation of **true** facts remain encouraged. --- @@ -309,7 +309,7 @@ When targeting Swiss positions, ensure: ## Revision Mode -When given reviewer feedback alongside an existing `resume_content.md` path (e.g., from the swiss-tech-resume-reviewer), **revise that file in place** rather than regenerating from scratch. Steps: +When given reviewer feedback alongside an existing `resume_content.md` path (e.g., from `resume-content-review`), **revise that file in place** rather than regenerating from scratch. Steps: 1. Read the existing `resume_content.md` carefully. 2. Read the reviewer feedback (content gaps, missing keywords, bullet improvements, reordering suggestions, quantification opportunities). diff --git a/.claude/skills/resume-content-review/SKILL.md b/.agents/skills/resume-content-review/SKILL.md similarity index 89% rename from .claude/skills/resume-content-review/SKILL.md rename to .agents/skills/resume-content-review/SKILL.md index da555a0..c2c9658 100644 --- a/.claude/skills/resume-content-review/SKILL.md +++ b/.agents/skills/resume-content-review/SKILL.md @@ -1,14 +1,35 @@ --- name: resume-content-review description: Review resume content (resume_content.md, or a rendered PDF's extracted text) for the Swiss tech market — ATS keyword match, content quality, and Swiss conventions — returning a structured verdict with a numeric rating. Use to gate resume content before or after rendering. +context: fork +metadata: + preferred-model: opus --- -> **Bundled reference files.** Paths in this skill beginning with `docs/` are bundled with -> the plugin. When the plugin is installed, read them under `${CLAUDE_PLUGIN_ROOT}/` (e.g. -> `${CLAUDE_PLUGIN_ROOT}/docs/knowledge/…`) — the variable expands to the plugin's install -> directory automatically. When working from the source repository the variable is unset, -> so read the same paths relative to the repo root (exactly as written). -> `docs/PERSONAL_PROFILE.md` is a working file in the **current project**, not bundled. +> **Bundled reference files.** Paths beginning with `docs/` are bundled with this skill +> package and resolve relative to the **package (repository) root** — read them exactly as +> written when working inside the repo. If your agent installs the package outside the working +> directory and exposes its install root via a variable (e.g. Claude Code's +> `${CLAUDE_PLUGIN_ROOT}/`), prepend that. `docs/PERSONAL_PROFILE.md` is a working file in the +> **current project**, not bundled. + +## Reviewer stance (run isolated / `context: fork`) + +You are reviewing with **fresh eyes** content you did not write — run this skill in an isolated +or forked context (a subagent, a `context: fork` turn, or a clean `/skill:` invocation) so prior +generation reasoning does not bias the verdict. Prefer the strongest available model (Opus on +Claude Code); content review is a high-judgment gate. + +Be deliberate about the **grounding pass** (criterion 8), because you are often handed only a +rendered PDF's extracted text: if `docs/PERSONAL_PROFILE.md` is readable, verify every quantified +claim and named technology/scope against it and apply the grounding override (a confirmed +ungrounded claim is an automatic `pass: false`, `rating ≤ 4.0`); if the profile is not available, +flag any implausibly precise or unverifiable claim as a High-priority weakness and recommend +confirming it against the profile. + +**Output discipline:** return ONLY the structured verdict defined below — `rating`, `ats_match`, +`pass`, and a `feedback` list of specific, actionable items — and nothing else. Do **not** edit +any files; you are a reviewer. ## Role diff --git a/.claude/skills/resume-design-review/SKILL.md b/.agents/skills/resume-design-review/SKILL.md similarity index 91% rename from .claude/skills/resume-design-review/SKILL.md rename to .agents/skills/resume-design-review/SKILL.md index fe2f048..c501ded 100644 --- a/.claude/skills/resume-design-review/SKILL.md +++ b/.agents/skills/resume-design-review/SKILL.md @@ -1,13 +1,24 @@ --- name: resume-design-review description: Review the visual design of a rendered resume (PDF or web) against the style guide, returning a structured verdict with a numeric rating. Use after rendering when layout, fonts, colors, or visual structure changed. +context: fork +metadata: + preferred-model: sonnet --- -> **Bundled reference files.** Paths in this skill beginning with `docs/` are bundled with -> the plugin. When the plugin is installed, read them under `${CLAUDE_PLUGIN_ROOT}/` (e.g. -> `${CLAUDE_PLUGIN_ROOT}/docs/style-guide/…`) — the variable expands to the plugin's install -> directory automatically. When working from the source repository the variable is unset, -> so read the same paths relative to the repo root (exactly as written). +> **Bundled reference files.** Paths beginning with `docs/` are bundled with this skill +> package and resolve relative to the **package (repository) root** — read them exactly as +> written when working inside the repo. If your agent installs the package outside the working +> directory and exposes its install root via a variable (e.g. Claude Code's +> `${CLAUDE_PLUGIN_ROOT}/`), prepend that. + +## Reviewer stance (run isolated / `context: fork`) + +You are reviewing the visual design of a rendered resume (PDF and/or web) with **fresh eyes** — +run this skill in an isolated or forked context (a subagent, a `context: fork` turn, or a clean +`/skill:` invocation). **Output discipline:** return ONLY the structured verdict defined below — +`rating`, `pass`, and a `feedback` list of specific, actionable design items — and nothing else. +Do **not** edit any files; you are a reviewer. ## Role diff --git a/.claude/skills/resume-market-analysis/SKILL.md b/.agents/skills/resume-market-analysis/SKILL.md similarity index 92% rename from .claude/skills/resume-market-analysis/SKILL.md rename to .agents/skills/resume-market-analysis/SKILL.md index 9232c17..dab8cbb 100644 --- a/.claude/skills/resume-market-analysis/SKILL.md +++ b/.agents/skills/resume-market-analysis/SKILL.md @@ -3,11 +3,12 @@ name: resume-market-analysis description: Research the Swiss tech job market for a target role — salary benchmarks, in-demand skills, ATS keywords, and competitive positioning. Use when analyzing a job posting or planning resume positioning for a Swiss tech position. --- -> **Bundled reference files.** Paths in this skill beginning with `docs/` are bundled with -> the plugin. When the plugin is installed, read them under `${CLAUDE_PLUGIN_ROOT}/` (e.g. -> `${CLAUDE_PLUGIN_ROOT}/docs/knowledge/…`) — the variable expands to the plugin's install -> directory automatically. When working from the source repository the variable is unset, -> so read the same paths relative to the repo root (exactly as written). +> **Bundled reference files.** Paths beginning with `docs/` are bundled with this skill +> package and resolve relative to the **package (repository) root** — read them exactly as +> written when working inside the repo. If your agent installs the package outside the working +> directory and exposes its install root via a variable (e.g. Claude Code's +> `${CLAUDE_PLUGIN_ROOT}/`), prepend that. `docs/PERSONAL_PROFILE.md` is a working file in the +> **current project**, not bundled. # Resume Market Analysis diff --git a/.claude/skills/resume-profile-coach/SKILL.md b/.agents/skills/resume-profile-coach/SKILL.md similarity index 91% rename from .claude/skills/resume-profile-coach/SKILL.md rename to .agents/skills/resume-profile-coach/SKILL.md index 8068077..831729a 100644 --- a/.claude/skills/resume-profile-coach/SKILL.md +++ b/.agents/skills/resume-profile-coach/SKILL.md @@ -3,12 +3,15 @@ name: resume-profile-coach description: Build out, strengthen, and audit the user's PERSONAL_PROFILE.md through conversation. Use when a user wants to create, build, improve, or review their personal profile; when they hand over source material (performance reviews, employment references / Arbeitszeugnisse, a LinkedIn profile, past CVs) to capture their experience; or to spot gaps between their career goals and what their profile actually supports. Invoked during first-run setup and any time profile work is needed. This is the coaching/intake step that feeds the rest of the resume pipeline. --- -> **Bundled reference files.** Paths beginning with `docs/` are bundled with the plugin: read -> them under `${CLAUDE_PLUGIN_ROOT}/` when installed (auto-substituted), or relative to the repo -> root from source. The profile schema lives in a sibling skill — read it at -> `../swiss-tech-resume-builder/references/personal_profile_schema.md` relative to this skill's -> directory (it resolves inside the plugin in both modes). `docs/PERSONAL_PROFILE.md` and -> `docs/MISSING_INFORMATION.md` are working files in the **user's current project**, not bundled. +> **Bundled reference files.** Paths beginning with `docs/` are bundled with this skill +> package and resolve relative to the **package (repository) root** — read them exactly as +> written when working inside the repo. If your agent installs the package outside the working +> directory and exposes its install root via a variable (e.g. Claude Code's +> `${CLAUDE_PLUGIN_ROOT}/`), prepend that. The profile schema lives in a sibling skill — read it +> at `../swiss-tech-resume-builder/references/personal_profile_schema.md` relative to this +> skill's directory (it resolves inside the package in both modes). `docs/PERSONAL_PROFILE.md` +> and `docs/MISSING_INFORMATION.md` are working files in the **user's current project**, not +> bundled. # Resume Profile Coach diff --git a/.claude/skills/resume-render-pdf/SKILL.md b/.agents/skills/resume-render-pdf/SKILL.md similarity index 88% rename from .claude/skills/resume-render-pdf/SKILL.md rename to .agents/skills/resume-render-pdf/SKILL.md index 8e58410..bcd39b6 100644 --- a/.claude/skills/resume-render-pdf/SKILL.md +++ b/.agents/skills/resume-render-pdf/SKILL.md @@ -3,13 +3,12 @@ name: resume-render-pdf description: Render an approved resume_content.md to a LaTeX moderncv PDF and compile it with XeLaTeX. Use when producing or fixing the PDF resume, or debugging moderncv compilation errors. --- -> **Bundled reference files.** Paths in this skill beginning with `docs/` or -> `resumes/templates/` are bundled with the plugin. When the plugin is installed, read them -> under `${CLAUDE_PLUGIN_ROOT}/` (e.g. `${CLAUDE_PLUGIN_ROOT}/resumes/templates/CV_template.tex`) — -> the variable expands to the plugin's install directory automatically. When working from -> the source repository the variable is unset, so read the same paths relative to the repo -> root (exactly as written). Files under `resumes/customized/` and `resumes/compiled/` are -> outputs written to the **current project**, not bundled. +> **Bundled reference files.** Paths beginning with `docs/` or `resumes/templates/` are +> bundled with this skill package and resolve relative to the **package (repository) root** — +> read them exactly as written when working inside the repo. If your agent installs the package +> outside the working directory and exposes its install root via a variable (e.g. Claude Code's +> `${CLAUDE_PLUGIN_ROOT}/`), prepend that. Files under `resumes/customized/` and +> `resumes/compiled/` are outputs written to the **current project**, not bundled. ## Role @@ -33,7 +32,7 @@ These rules are MANDATORY — never deviate from them: | Document | Purpose | |---|---| -| `.claude/skills/resume-render-pdf/references/moderncv_technical_guide.md` | Technical reference for all moderncv commands, troubleshooting, and package compatibility — **consult first for any LaTeX question** | +| `.agents/skills/resume-render-pdf/references/moderncv_technical_guide.md` | Technical reference for all moderncv commands, troubleshooting, and package compatibility — **consult first for any LaTeX question** | | `docs/style-guide/pdf/CV_STYLE_GUIDE.md` | Full design specification: typography, colors, layout, margins | | `docs/style-guide/pdf/VISUAL_DESIGN_REFERENCE.md` | One-page quick-reference checklist for compliance checks | | `docs/style-guide/pdf/LATEX_CODE_SNIPPETS.md` | Copy-paste boilerplate, section templates, experience entry templates | @@ -78,7 +77,7 @@ Incorrect (do NOT do this): Run the validation script from the repo root: ```bash -python3 .claude/skills/resume-render-pdf/scripts/validate_latex.py resumes/customized/{id}/{id}.tex +python3 .agents/skills/resume-render-pdf/scripts/validate_latex.py resumes/customized/{id}/{id}.tex ``` Fix all errors reported before proceeding. Common issues caught by validation: @@ -92,7 +91,7 @@ Fix all errors reported before proceeding. Common issues caught by validation: Run the compile script from the repo root: ```bash -bash .claude/skills/resume-render-pdf/scripts/compile_resume.sh resumes/customized/{id}/{id}.tex +bash .agents/skills/resume-render-pdf/scripts/compile_resume.sh resumes/customized/{id}/{id}.tex ``` The script runs XeLaTeX (two passes for cross-references) and reports errors. If compilation fails, diagnose the error message and fix the `.tex` file, then re-validate and re-compile. @@ -132,7 +131,7 @@ rm -f resumes/customized/{id}/*.aux \ | Blank gap after section header | Blank line between `\section{}` and first entry | Remove blank line — no paragraph break after section headers | | Missing `fontawesome` icons | Package not installed | Use `tlmgr install fontawesome` or omit icon | -For detailed troubleshooting, see `.claude/skills/resume-render-pdf/references/moderncv_technical_guide.md`. +For detailed troubleshooting, see `.agents/skills/resume-render-pdf/references/moderncv_technical_guide.md`. --- @@ -152,7 +151,7 @@ Style guide compliance checks: - Use `docs/style-guide/pdf/LATEX_CODE_SNIPPETS.md` for implementation templates. - Use `docs/style-guide/pdf/VISUAL_DESIGN_REFERENCE.md` as a quick compliance checklist. -After rendering is complete and content-approved, design quality assurance is handled via the `resume-design-review` skill / `design-reviewer` agent. +After rendering is complete and content-approved, design quality assurance is handled via the `resume-design-review` skill (run isolated / forked). **Iteration limits**: Up to 3 rounds of revisions per reviewer. If an issue cannot be resolved after 3 attempts, report to the user with: issue summary, attempts made, technical constraints, and recommendation. diff --git a/.claude/skills/resume-render-pdf/references/moderncv_technical_guide.md b/.agents/skills/resume-render-pdf/references/moderncv_technical_guide.md similarity index 100% rename from .claude/skills/resume-render-pdf/references/moderncv_technical_guide.md rename to .agents/skills/resume-render-pdf/references/moderncv_technical_guide.md diff --git a/.claude/skills/resume-render-pdf/scripts/compile_resume.sh b/.agents/skills/resume-render-pdf/scripts/compile_resume.sh similarity index 93% rename from .claude/skills/resume-render-pdf/scripts/compile_resume.sh rename to .agents/skills/resume-render-pdf/scripts/compile_resume.sh index 64854b4..2f5b16f 100755 --- a/.claude/skills/resume-render-pdf/scripts/compile_resume.sh +++ b/.agents/skills/resume-render-pdf/scripts/compile_resume.sh @@ -3,10 +3,10 @@ # Compile LaTeX resume using XeLaTeX and clean up build artifacts. # # Usage (run from the repository root): -# bash .claude/skills/swiss-tech-resume-builder/scripts/compile_resume.sh +# bash .agents/skills/swiss-tech-resume-builder/scripts/compile_resume.sh # # Example: -# bash .claude/skills/swiss-tech-resume-builder/scripts/compile_resume.sh \ +# bash .agents/skills/swiss-tech-resume-builder/scripts/compile_resume.sh \ # resumes/customized/2025_11_10_company_role.tex # # Requirements: diff --git a/.claude/skills/resume-render-pdf/scripts/validate_latex.py b/.agents/skills/resume-render-pdf/scripts/validate_latex.py similarity index 100% rename from .claude/skills/resume-render-pdf/scripts/validate_latex.py rename to .agents/skills/resume-render-pdf/scripts/validate_latex.py diff --git a/.claude/skills/resume-render-web/SKILL.md b/.agents/skills/resume-render-web/SKILL.md similarity index 100% rename from .claude/skills/resume-render-web/SKILL.md rename to .agents/skills/resume-render-web/SKILL.md diff --git a/.claude/skills/resume-strategy/SKILL.md b/.agents/skills/resume-strategy/SKILL.md similarity index 93% rename from .claude/skills/resume-strategy/SKILL.md rename to .agents/skills/resume-strategy/SKILL.md index 8e42cec..bc0074d 100644 --- a/.claude/skills/resume-strategy/SKILL.md +++ b/.agents/skills/resume-strategy/SKILL.md @@ -3,11 +3,12 @@ name: resume-strategy description: Plan resume content strategy for a Swiss tech role — positioning, section emphasis, and ATS keyword selection from market analysis plus the personal profile. Use after market analysis and before generating resume content. --- -> **Bundled reference files.** Paths in this skill beginning with `docs/` are bundled with -> the plugin. When the plugin is installed, read them under `${CLAUDE_PLUGIN_ROOT}/` (e.g. -> `${CLAUDE_PLUGIN_ROOT}/docs/knowledge/…`) — the variable expands to the plugin's install -> directory automatically. When working from the source repository the variable is unset, -> so read the same paths relative to the repo root (exactly as written). +> **Bundled reference files.** Paths beginning with `docs/` are bundled with this skill +> package and resolve relative to the **package (repository) root** — read them exactly as +> written when working inside the repo. If your agent installs the package outside the working +> directory and exposes its install root via a variable (e.g. Claude Code's +> `${CLAUDE_PLUGIN_ROOT}/`), prepend that. `docs/PERSONAL_PROFILE.md` is a working file in the +> **current project**, not bundled. # Resume Strategy diff --git a/.claude/skills/swiss-tech-resume-builder/SKILL.md b/.agents/skills/swiss-tech-resume-builder/SKILL.md similarity index 60% rename from .claude/skills/swiss-tech-resume-builder/SKILL.md rename to .agents/skills/swiss-tech-resume-builder/SKILL.md index f975cae..6162c55 100644 --- a/.claude/skills/swiss-tech-resume-builder/SKILL.md +++ b/.agents/skills/swiss-tech-resume-builder/SKILL.md @@ -6,13 +6,13 @@ description: Create ATS-optimized resumes for Swiss technology positions. This s # Swiss Tech Resume Builder > **Bundled reference files.** Paths in this skill (and its sub-skills) beginning with -> `docs/` or `resumes/templates/` are bundled with the plugin. When the plugin is installed, -> read them under `${CLAUDE_PLUGIN_ROOT}/` — the variable expands to the plugin's install -> directory automatically. When working from the source repository the variable is unset, so -> read the same paths relative to the repo root (exactly as written). `docs/PERSONAL_PROFILE.md` -> and everything under `resumes/customized/` and `resumes/compiled/` are working files in the -> **current project**, not bundled. `references/…` and `assets/…` paths are relative to this -> skill's own directory and resolve the same way in both modes. +> `docs/` or `resumes/templates/` are bundled with this skill package and resolve relative to +> the **package (repository) root** — read them exactly as written when working inside the repo. +> If your agent installs the package outside the working directory and exposes its install root +> via a variable (e.g. Claude Code's `${CLAUDE_PLUGIN_ROOT}/`), prepend that. +> `docs/PERSONAL_PROFILE.md` and everything under `resumes/customized/` and `resumes/compiled/` +> are working files in the **current project**, not bundled. `references/…` and `assets/…` paths +> are relative to this skill's own directory and resolve the same way in both modes. ## Overview @@ -27,16 +27,16 @@ This skill is the **lean orchestrator** for building Swiss-market tech resumes. ## The Pipeline -Run these steps in order. Each step names the sub-skill or agent to use and whether it runs **INLINE** (in this conversation) or as a **DISPATCHED SUBAGENT** (general-purpose subagent loading the named skill, or the named review agent). +Run these steps in order. Each step names the skill to use and whether it runs **INLINE** (in this conversation) or **ISOLATED** (in a fresh sub-context that loads the named skill with fresh eyes). Use whatever isolation mechanism your agent provides — a dispatched subagent, a forked skill context (`context: fork`), or an explicit `/skill:` invocation in a clean turn. The review skills declare `context: fork` so they isolate automatically where supported. 1. **Profile setup** — INLINE → `resume-profile-coach`. Ensure `docs/PERSONAL_PROFILE.md` exists, is current, and actually supports the target. The coach ingests the user's source material, audits the profile against the schema, and — when a specific role is in play — spots gaps between the user's goal and what the profile substantiates, logging open items to `docs/MISSING_INFORMATION.md`. Schema: `references/personal_profile_schema.md`. See "Profile setup" below. -2. **Market analysis** — DISPATCHED SUBAGENT → `resume-market-analysis`. Run when targeting a specific role/company; produces salary benchmarks, in-demand skills, and ATS keywords. Skip for a fully generic resume. +2. **Market analysis** — ISOLATED → `resume-market-analysis`. Run when targeting a specific role/company; produces salary benchmarks, in-demand skills, and ATS keywords. Skip for a fully generic resume. 3. **Strategy** — INLINE → `resume-strategy`. Decide positioning, section emphasis, and ATS keyword selection from market analysis + profile. Output is a compact strategy brief reused downstream. -4. **Content generation** — DISPATCHED SUBAGENT (on **Opus**) → `resume-content-generation`. Writes `resumes/customized/{id}/resume_content.md`. Pass the strategy brief and the target directory in the dispatch prompt. -5. **GATE — content review (Pattern A, pre-render)** — DISPATCH the `swiss-tech-resume-reviewer` agent (it loads `resume-content-review`). Branch on its verdict contract: **`pass` = rating ≥ 8.0 AND ats_match ≥ 75**. If not `pass` and iterations < 3: re-dispatch step 4 (content generation) with the reviewer feedback + the existing `resume_content.md` path. If the 3-iteration cap is hit without `pass`: escalate to the user. +4. **Content generation** — ISOLATED (on the strongest available model, e.g. **Opus** on Claude) → `resume-content-generation`. Writes `resumes/customized/{id}/resume_content.md`. Pass the strategy brief and the target directory in the dispatch prompt. +5. **GATE — content review (Pattern A, pre-render)** — run `resume-content-review` ISOLATED (it forks a fresh context to review with fresh eyes). Branch on its verdict contract: **`pass` = rating ≥ 8.0 AND ats_match ≥ 75**. If not `pass` and iterations < 3: re-dispatch step 4 (content generation) with the reviewer feedback + the existing `resume_content.md` path. If the 3-iteration cap is hit without `pass`: escalate to the user. 6. **GATE — user content review (pre-render)** — INLINE. Once the reviewer passes, **pause and hand `resume_content.md` to the user before rendering**. Surface the path, summarize the reviewer's verdict, and explicitly offer them the chance to read and edit the content. See "User content-review gate" below. Do **not** proceed to render until the user approves. If they request changes, either apply their edits directly or re-dispatch step 4 with their instructions, then re-run the step 5 gate before returning here. -7. **Render** — DISPATCHED SUBAGENT → `resume-render-pdf`, rendering the approved `resume_content.md` into a PDF. -8. **Post-render QA** — dispatch the `swiss-tech-resume-reviewer` agent to verify the content survived rendering (carry the ≥ 8.0 target forward) **and** the `design-reviewer` agent (it loads `resume-design-review`; **`pass` = rating ≥ 9.0**). Iterate ≤ 3 times, re-dispatching `resume-render-pdf` with the reviewer feedback. +7. **Render** — ISOLATED → `resume-render-pdf`, rendering the approved `resume_content.md` into a PDF. +8. **Post-render QA** — run `resume-content-review` ISOLATED to verify the content survived rendering (carry the ≥ 8.0 target forward) **and** `resume-design-review` ISOLATED (**`pass` = rating ≥ 9.0**). Iterate ≤ 3 times, re-running `resume-render-pdf` with the reviewer feedback. 9. **Finalize** — INLINE. Holistic review of the narrative (does it position for the target role, justify the salary target, fit the Swiss market?), then generate the paired `..._application_strategy.md`. See "Application-strategy generation" below. ## Profile setup @@ -44,9 +44,10 @@ Run these steps in order. Each step names the sub-skill or agent to use and whet `docs/PERSONAL_PROFILE.md` is the single source of truth — keep ALL experience here, then pull relevant slices per application. - If it does not exist, create it from the bundled example. Copy the example into the - current project: source it from `${CLAUDE_PLUGIN_ROOT}/docs/PERSONAL_PROFILE.example.md` - when installed, or `docs/PERSONAL_PROFILE.example.md` when working from the source repo — - writing to `docs/PERSONAL_PROFILE.md` in the user's project. + current project: source it from `docs/PERSONAL_PROFILE.example.md` (relative to the package + root; prepend your agent's install-root variable such as `${CLAUDE_PLUGIN_ROOT}/` if the + package is installed outside the working directory) — writing to `docs/PERSONAL_PROFILE.md` + in the user's project. - **Don't ask the user to fill it in by hand** — delegate to `resume-profile-coach`. It builds the profile out conversationally from the user's source material (performance reviews, employment references / *Arbeitszeugnisse*, LinkedIn, past CVs), audits it against the schema @@ -56,7 +57,7 @@ Run these steps in order. Each step names the sub-skill or agent to use and whet ## User content-review gate -After the `swiss-tech-resume-reviewer` agent passes (step 5) and **before** rendering (step 7), +After `resume-content-review` passes (step 5) and **before** rendering (step 7), give the user a real chance to read and shape the content while it is still cheap to change (plain markdown, no LaTeX/PDF round-trip yet). @@ -90,29 +91,30 @@ When the resume is finalized (step 9), always produce a paired strategy document the `{id}` and a strategy stub. It writes into `resumes/customized/` in the current project and finds the bundled template automatically. Run it from the user's project root: ```bash - # Installed plugin: - python3 "${CLAUDE_PLUGIN_ROOT}/.claude/skills/swiss-tech-resume-builder/scripts/init_application.py" --company google --role ml_engineer - # Source repository: - python3 .claude/skills/swiss-tech-resume-builder/scripts/init_application.py --company google --role ml_engineer + # From the repo (skills live under .agents/skills/, symlinked into each agent's skills dir): + python3 .agents/skills/swiss-tech-resume-builder/scripts/init_application.py --company google --role ml_engineer + # If the package is installed outside the working directory, prepend your agent's install + # root, e.g. Claude Code: + python3 "${CLAUDE_PLUGIN_ROOT}/.agents/skills/swiss-tech-resume-builder/scripts/init_application.py" --company google --role ml_engineer ``` ## Execution-model rule - **INLINE** when the output is compact AND reused later in this conversation: strategy brief, decision gates (content-review branch, holistic finalize). -- **DISPATCHED SUBAGENT** when the work is bulky AND the output is a file or a summary: market analysis, content generation, the render, and the reviews. -- Dispatch mechanics: `resume-market-analysis`, `resume-content-generation`, and `resume-render-pdf` run as **general-purpose subagents loading their skill**. Content review and design review run via the **named agents** `swiss-tech-resume-reviewer` and `design-reviewer` (which load `resume-content-review` and `resume-design-review` respectively). -- **Model selection**: dispatch `resume-content-generation` on **Opus** (`model: opus`). It is the highest-judgment step in the pipeline — selecting which achievements survive, combining related ones, and compressing to the bullet budget is exactly the reasoning that gates content-review quality (rating ≥ 8.0). The mechanical phases (render, market analysis) may run on the default model. +- **ISOLATED** when the work is bulky AND the output is a file or a summary: market analysis, content generation, the render, and the reviews. +- Isolation mechanics are agent-specific: use a dispatched subagent, a `context: fork` skill, or a clean `/skill:` turn. `resume-market-analysis`, `resume-content-generation`, and `resume-render-pdf` load their skill in the isolated context. `resume-content-review` and `resume-design-review` declare `context: fork`, so they review with fresh eyes wherever forking is supported. +- **Model selection**: run `resume-content-generation` on the strongest available model (**Opus** on Claude Code). It is the highest-judgment step in the pipeline — selecting which achievements survive, combining related ones, and compressing to the bullet budget is exactly the reasoning that gates content-review quality (rating ≥ 8.0). The mechanical phases (render, market analysis) may run on the default model. ## Pointers | Phase | Sub-skill / agent | |-------|-------------------| | Profile setup / coaching | `resume-profile-coach` (inline) | -| Market analysis | `resume-market-analysis` (subagent) | +| Market analysis | `resume-market-analysis` (isolated) | | Strategy | `resume-strategy` (inline) | -| Content generation | `resume-content-generation` (subagent) | -| Content review (gate) | `swiss-tech-resume-reviewer` agent → `resume-content-review` | -| PDF render | `resume-render-pdf` (subagent) | -| Design review (QA) | `design-reviewer` agent → `resume-design-review` | +| Content generation | `resume-content-generation` (isolated) | +| Content review (gate) | `resume-content-review` (isolated, `context: fork`) | +| PDF render | `resume-render-pdf` (isolated) | +| Design review (QA) | `resume-design-review` (isolated, `context: fork`) | **Bundled assets** (kept here, referenced above): `scripts/init_application.py`, `assets/application_strategy_template.md`, `references/personal_profile_schema.md`. diff --git a/.claude/skills/swiss-tech-resume-builder/assets/application_strategy_template.md b/.agents/skills/swiss-tech-resume-builder/assets/application_strategy_template.md similarity index 100% rename from .claude/skills/swiss-tech-resume-builder/assets/application_strategy_template.md rename to .agents/skills/swiss-tech-resume-builder/assets/application_strategy_template.md diff --git a/.claude/skills/swiss-tech-resume-builder/references/personal_profile_schema.md b/.agents/skills/swiss-tech-resume-builder/references/personal_profile_schema.md similarity index 98% rename from .claude/skills/swiss-tech-resume-builder/references/personal_profile_schema.md rename to .agents/skills/swiss-tech-resume-builder/references/personal_profile_schema.md index e0329d6..5b0d045 100644 --- a/.claude/skills/swiss-tech-resume-builder/references/personal_profile_schema.md +++ b/.agents/skills/swiss-tech-resume-builder/references/personal_profile_schema.md @@ -437,10 +437,11 @@ Always include at least one of: Create your PERSONAL_PROFILE.md in your project, from the bundled example: ```bash -# Installed plugin: -cp "${CLAUDE_PLUGIN_ROOT}/docs/PERSONAL_PROFILE.example.md" docs/PERSONAL_PROFILE.md -# Source repository: +# From the repo (package root is the working directory): cp docs/PERSONAL_PROFILE.example.md docs/PERSONAL_PROFILE.md +# If the package is installed outside the working directory, prepend your agent's install +# root, e.g. Claude Code: +cp "${CLAUDE_PLUGIN_ROOT}/docs/PERSONAL_PROFILE.example.md" docs/PERSONAL_PROFILE.md # Then fill in with your actual information ``` diff --git a/.claude/skills/swiss-tech-resume-builder/scripts/init_application.py b/.agents/skills/swiss-tech-resume-builder/scripts/init_application.py similarity index 91% rename from .claude/skills/swiss-tech-resume-builder/scripts/init_application.py rename to .agents/skills/swiss-tech-resume-builder/scripts/init_application.py index badc69e..c2377d9 100755 --- a/.claude/skills/swiss-tech-resume-builder/scripts/init_application.py +++ b/.agents/skills/swiss-tech-resume-builder/scripts/init_application.py @@ -25,8 +25,8 @@ from pathlib import Path -# The plugin/repo root is four levels up from this script: -# /.claude/skills/swiss-tech-resume-builder/scripts/init_application.py +# The package/repo root is four levels up from this script: +# /.agents/skills/swiss-tech-resume-builder/scripts/init_application.py PLUGIN_ROOT = Path(__file__).resolve().parents[4] @@ -38,10 +38,11 @@ def sanitize_name(name: str) -> str: def resolve_template(explicit: str | None) -> Path: """Find the bundled CV template. - Works both when running from the source repo and when running from an - installed plugin (where bundled files live under ${CLAUDE_PLUGIN_ROOT}). - Resolution order: explicit --template, $CLAUDE_PLUGIN_ROOT, this script's - own location, then the current working directory. + Works both when running from the source repo and when the package is + installed elsewhere. Resolution order: explicit --template, + $CLAUDE_PLUGIN_ROOT (set by Claude Code), this script's own location + (covers any agent, since the script ships inside the package), then the + current working directory. """ if explicit: return Path(explicit) @@ -197,7 +198,7 @@ def main(): - [ ] Research company and role in detail - [ ] Customize resume template with job-specific keywords - [ ] Prepare cover letter using strategy above -- [ ] Compile PDF: `bash {PLUGIN_ROOT}/.claude/skills/resume-render-pdf/scripts/compile_resume.sh {output_tex}` +- [ ] Compile PDF: `bash {PLUGIN_ROOT}/.agents/skills/resume-render-pdf/scripts/compile_resume.sh {output_tex}` - [ ] Review with the swiss-tech-resume-builder skill (content + design review gates) """ @@ -205,7 +206,7 @@ def main(): f.write(strategy_template) print(f"✅ Created: {output_strategy}") - render_scripts = PLUGIN_ROOT / ".claude/skills/resume-render-pdf/scripts" + render_scripts = PLUGIN_ROOT / ".agents/skills/resume-render-pdf/scripts" print(f"\n📋 Next steps:") print(f"1. Edit {output_tex} and replace [PLACEHOLDER] values") print(f"2. Validate: python3 {render_scripts}/validate_latex.py {output_tex}") diff --git a/.claude/skills/swiss-tech-resume-setup/SKILL.md b/.agents/skills/swiss-tech-resume-setup/SKILL.md similarity index 92% rename from .claude/skills/swiss-tech-resume-setup/SKILL.md rename to .agents/skills/swiss-tech-resume-setup/SKILL.md index e9e4c56..d0bd6ba 100644 --- a/.claude/skills/swiss-tech-resume-setup/SKILL.md +++ b/.agents/skills/swiss-tech-resume-setup/SKILL.md @@ -39,10 +39,10 @@ directory), never in the plugin cache. 1. **Personal profile** — the single source of truth. If `docs/PERSONAL_PROFILE.md` does not already exist, create it from the bundled example: - - The example ships with the plugin. Locate it at - `${CLAUDE_PLUGIN_ROOT}/docs/PERSONAL_PROFILE.example.md` when running as an - installed plugin, or `docs/PERSONAL_PROFILE.example.md` when running from - the source repo. Copy it to `docs/PERSONAL_PROFILE.md` in the user's project. + - The example ships with this package at `docs/PERSONAL_PROFILE.example.md` (relative to the + package root; prepend your agent's install-root variable such as `${CLAUDE_PLUGIN_ROOT}/` + if the package is installed outside the working directory). Copy it to + `docs/PERSONAL_PROFILE.md` in the user's project. - Then hand off to the **`resume-profile-coach`** skill to build the profile out conversationally — ingesting the user's performance reviews, employment references (Swiss *Arbeitszeugnisse*), LinkedIn profile, and past CVs, auditing it against the diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 7d71096..33f8b6e 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -11,8 +11,8 @@ { "name": "swiss-tech-resume-builder", "source": "./", - "description": "End-to-end resume builder for Swiss tech roles: market analysis, strategy, content generation, LaTeX/moderncv PDF rendering, and iterative content/design review. PDF pipeline only in v0.1.0.", - "version": "0.1.0", + "description": "End-to-end resume builder for Swiss tech roles: market analysis, strategy, content generation, LaTeX/moderncv PDF rendering, and iterative content/design review. Portable across Claude Code, Gemini CLI, Cursor, and Pi via the Agent Skills standard.", + "version": "0.2.0", "author": { "name": "Florian Hochstrasser", "url": "https://github.com/datarian" diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 311685e..597cb21 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,8 +1,8 @@ { "name": "swiss-tech-resume-builder", "displayName": "Swiss Tech Resume Builder", - "version": "0.1.0", - "description": "Create ATS-optimized resumes for Swiss technology positions. Orchestrates market analysis, strategy, content generation, LaTeX/moderncv PDF rendering, and iterative content/design review. Specialized for Swiss conventions (work permits, CEFR languages, salary norms) and ML/AI/Engineering roles.", + "version": "0.2.0", + "description": "Create ATS-optimized resumes for Swiss technology positions. Orchestrates market analysis, strategy, content generation, LaTeX/moderncv PDF rendering, and iterative content/design review. Specialized for Swiss conventions (work permits, CEFR languages, salary norms) and ML/AI/Engineering roles. Portable across Claude Code, Gemini CLI, Cursor, and Pi via the Agent Skills standard.", "author": { "name": "Florian Hochstrasser", "url": "https://github.com/datarian" @@ -19,10 +19,6 @@ "moderncv", "job-search" ], - "skills": "./.claude/skills/", - "agents": [ - "./.claude/agents/design-reviewer.md", - "./.claude/agents/swiss-tech-resume-reviewer.md" - ], + "skills": "./.agents/skills/", "commands": "./.claude/commands/" } diff --git a/.claude/agents/design-reviewer.md b/.claude/agents/design-reviewer.md deleted file mode 100644 index 23b79c4..0000000 --- a/.claude/agents/design-reviewer.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: design-reviewer -description: PROACTIVELY use this agent when a rendered resume (PDF or web) has changed in layout, fonts, colors, or visual structure, to provide unified design QA across both formats. Returns a numeric design rating and actionable feedback. -tools: Glob, Grep, Read, WebFetch, TodoWrite, WebSearch, BashOutput, KillBash, Bash -model: sonnet ---- - -You are dispatched in an isolated context to review the visual design of a rendered resume (PDF and/or web) with fresh eyes. - -Invoke the `resume-design-review` skill and follow it exactly. It defines the dual-format design criteria (typography, color, whitespace, Swiss-market fit; plus responsive/print/accessibility for web) and the required output contract. - -Return ONLY the skill's structured verdict — `rating`, `pass`, and a `feedback` list of specific, actionable design items — and nothing else. Do not edit any files; you are a reviewer. diff --git a/.claude/agents/swiss-tech-resume-reviewer.md b/.claude/agents/swiss-tech-resume-reviewer.md deleted file mode 100644 index f9e47cb..0000000 --- a/.claude/agents/swiss-tech-resume-reviewer.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -name: swiss-tech-resume-reviewer -description: PROACTIVELY use this agent to review resume content (resume_content.md or a rendered PDF's text) for the Swiss tech job market — ATS keyword match, content quality, Swiss conventions — returning a numeric rating and actionable feedback. Use as the content-review gate before rendering and to verify content after rendering. -tools: Glob, Grep, Read, WebFetch, TodoWrite, WebSearch, BashOutput, KillBash, Bash -model: opus -color: green ---- - -You are dispatched in an isolated context to review a resume with fresh eyes — content you did not write. - -Invoke the `resume-content-review` skill and follow it exactly. It defines the evaluation criteria (ATS keyword match, content quality, Swiss-market fit, and grounding/anti-fabrication) and the required output contract. Do not restate or reinterpret the criteria here — the skill is the single source of truth. - -One thing to be deliberate about, because you are often handed only a rendered PDF's extracted text: run the skill's **grounding pass** (criterion 8). If `docs/PERSONAL_PROFILE.md` is readable, verify every quantified claim and named technology/scope against it and apply the grounding override (a confirmed ungrounded claim is an automatic `pass: false`, `rating ≤ 4.0`); if the profile is not available, flag any implausibly precise or unverifiable claim as a High-priority weakness and recommend confirming it against the profile. - -Return ONLY the skill's structured verdict — `rating`, `ats_match`, `pass`, and a `feedback` list of specific, actionable items — and nothing else. Do not edit any files; you are a reviewer. diff --git a/.claude/commands/preview-web-resume.md b/.claude/commands/preview-web-resume.md index a79970d..d5d91b3 100644 --- a/.claude/commands/preview-web-resume.md +++ b/.claude/commands/preview-web-resume.md @@ -30,7 +30,7 @@ The `resume-render-web` skill (preview mode) will: ## Use Cases - Quick visual check during content development -- Review before requesting formal approval from swiss-tech-resume-reviewer +- Review before requesting formal approval from the `resume-content-review` skill - Test web builder changes or styling - Demonstrate locally to others without sharing private URL diff --git a/.claude/skills b/.claude/skills new file mode 120000 index 0000000..2b7a412 --- /dev/null +++ b/.claude/skills @@ -0,0 +1 @@ +../.agents/skills \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e26dd3b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,140 @@ +# AGENTS.md + +Project instructions for any AI coding agent working in this repository (Claude Code, +Gemini CLI, Cursor, Pi, and other tools that read `AGENTS.md`). `CLAUDE.md` and `GEMINI.md` +are symlinks to this file so every agent reads the same guidance. + +## Project Goal + +This repository builds polished, ATS-optimized CVs/resumes for the Swiss technology job +market, packaged as a **portable, multi-agent skill bundle** (Agent Skills standard). It +targets roles such as ML Engineer, MLOps Engineer, AI Software Architect, and Engineering +Manager. + +Work proceeds in two modes: a generic resume that fits the target roles and market, and +job-specific tailoring for individual postings. + +**Privacy:** the user's own career objectives, target roles, and salary expectations are +personal data and live only in their private `docs/PERSONAL_PROFILE.md` (gitignored) — never +in this file or any other tracked file. + +## Repository Overview + +This is a LaTeX-based CV/Resume system, with a portable skill pipeline, for producing +bilingual (English/German) resumes for the Swiss tech market. The skills follow the +[Agent Skills standard](https://agentskills.io/specification), so the same pipeline runs +across Claude Code, Gemini CLI, Cursor, and Pi. + +## File Structure + +- `.agents/skills/` - **Canonical home of the resume pipeline** (single source of truth): + the `swiss-tech-resume-builder` orchestrator plus `resume-*` sub-skills (profile coaching, + market analysis, strategy, content generation, PDF render, content/design review) and + `swiss-tech-resume-setup`. The two review skills (`resume-content-review`, + `resume-design-review`) declare `context: fork` so they review with fresh eyes. +- Per-agent skill directories (`.claude/skills/`, and later `.gemini/skills/`, + `.cursor/skills/`) are **symlinks** into `.agents/skills/`. Pi reads `.agents/skills/` + natively. Edit skills only in `.agents/skills/`. +- `.claude-plugin/` - Claude Code plugin + marketplace manifests (points `skills` at + `.agents/skills/`). +- `docs/PERSONAL_PROFILE.md` - **Primary data source** (private, gitignored). Built and + maintained via the `resume-profile-coach` skill. Template: `docs/PERSONAL_PROFILE.example.md`. +- `docs/MISSING_INFORMATION.md` - Durable profile-gap ledger (private, gitignored), owned by + the profile coach. Template: `docs/MISSING_INFORMATION.example.md`. +- `docs/knowledge/` - Swiss-market standards (ATS, tone, bullets, grounding, conventions). +- `docs/style-guide/` - Design specifications (`pdf/` and `web/`). +- `resumes/templates/CV_template.tex` - Universal moderncv template for all role types. +- `resumes/customized/{id}/` - Per-application working files (private, gitignored): + `resume_content.md`, the `.tex`, the compiled PDF, and `..._application_strategy.md`. +- `resumes/compiled/` - Final timestamped PDF outputs (private, gitignored). +- `resources/` - Portrait photos (private, gitignored). + +## Rendering + +PDF rendering is driven by the `resume-render-pdf` skill (invoked by the +`swiss-tech-resume-builder` orchestrator): it fills the template from the approved +`resume_content.md`, compiles with XeLaTeX, and cleans up. The skills are the single source +of truth — see "Resume Workflow" below. + +For manual work on a `.tex` directly: +```bash +cd resumes/customized/{id}/ +xelatex {id}.tex +rm -f *.aux *.log *.out *.fls *.fdb_latexmk *.gz *.toc *.bbl *.blg # clean build artifacts +``` + +Always compile with XeLaTeX (never pdflatex). Templates use the `moderncv` class. + +## LaTeX Dependencies + +The CV uses: +- `moderncv` document class with **`fancy` style (REQUIRED)** +- Custom fonts via `fontspec` (Roboto, Lato, Roboto Slab) +- `moderntimeline` package for timeline visualizations +- `fontawesome` for icons +- Multiple language support via `babel` + +### CRITICAL: ModernCV Style Requirement +**ALWAYS use `\moderncvstyle{fancy}` for all CVs in this repository.** + +- The `fancy` style is MANDATORY because it properly handles multi-page documents +- The `casual` style has a fundamental bug causing "Unbalanced output routine" errors on multi-page CVs +- NEVER use `casual`, `classic`, `banking`, or `oldstyle` styles +- All templates use the `fancy` style +- See `docs/style-guide/pdf/MODERNCV_REFERENCE.md` for detailed technical reference + +## Development Notes + +- The `.gitignore` excludes LaTeX build artifacts (`*.log`, `*.aux`, `*.out`, `*.gz`) and all personal data (profile, customized/compiled resumes, PDFs, portrait photos) +- Primary data source is `docs/PERSONAL_PROFILE.md` - the comprehensive profile all resumes draw from +- If information is missing, check `docs/MISSING_INFORMATION.md` (the profile coach's gap ledger), then ask the user +- All resume generation should reference `docs/PERSONAL_PROFILE.md` for consistency and completeness + +## Web Resources + +Statistical Salary Calculator: https://www.salarium.bfs.admin.ch/ + +### Job Search Portals +See comprehensive list in `docs/JOB_AGENT_RESEARCH.md` (maintained via the `resume-market-analysis` skill) + +## Resume Workflow + +Resume creation is driven by the `swiss-tech-resume-builder` skill and its `resume-*` +sub-skills (`.agents/skills/`). Those skills are the authoritative, single source of truth +for the pipeline, decision gates, and review loops — do not duplicate workflow steps here. +The two review steps run via the `resume-content-review` and `resume-design-review` skills, +which fork an isolated context (use your agent's isolation mechanism: a subagent, a +`context: fork` skill, or a clean `/skill:` turn). + +## File Management + +### LaTeX Build Artifacts +Always clean up after compilation: +```bash +rm -f *.aux *.log *.out *.fls *.fdb_latexmk *.gz *.toc *.bbl *.blg +``` + +### Generated & temporary files +- **Temporary files**: Remove scratch/working files once their content is integrated into `docs/`. Never delete the skills under `.agents/skills/`. +- **Research files**: Consolidate market research into `docs/JOB_AGENT_RESEARCH.md` (gitignored). +- **Analysis files**: Merge insights into existing documentation rather than creating new files. + +### Directory Organization +- **Keep clean**: Remove duplicate or outdated files promptly +- **Naming convention**: Use timestamps for compiled PDFs: `YYYY_MM_DD_HH_MM_role_CV_lang.pdf` +- **Version control**: Track significant template changes and customizations + + +## Key Constraints +- **ModernCV Style**: ALWAYS use `\moderncvstyle{fancy}` - this is MANDATORY for multi-page support +- **cventry Format**: All `\cventry` commands must have exactly 6 arguments: `\cventry{dates}{title}{company}{location}{}{description}` +- **Job titles**: Never change job titles of past or current employments +- **Compilation**: NEVER use pdflatex. Always compile with xelatex +- **Data source**: Always reference docs/PERSONAL_PROFILE.md as the single source of truth +- **Skills are the source of truth**: author and edit skills only in `.agents/skills/`; never edit through the per-agent symlinks +- **File organization**: template in `resumes/templates/`, per-application work in `resumes/customized/{id}/`, final timestamped PDFs in `resumes/compiled/` +- **Clean up**: Clean up any temporary files and experiments when you are done compiling a new version of the CV +- **Page count**: Do not feel you need to fit the whole CV on 1 page. 2-3 page CVs are preferred with room for comprehensive background +- **GitHub Repository Link**: ALWAYS include a link to the GitHub repository at the end of every generated resume with the text: "Curious how this resume was built? Explore the system at github.com/datarian/CV" +- **Privacy**: never put personal data (real profile, salary, career goals) in tracked files; it belongs only in the gitignored `docs/PERSONAL_PROFILE.md` +- **Preview availability**: Preview mode available during development without approval, no credentials required diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index a61ed85..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,113 +0,0 @@ -# Claude.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Goal - -This repository builds polished, ATS-optimized CVs/resumes for the Swiss technology job market, packaged as a Claude Code plugin. It targets roles such as ML Engineer, MLOps Engineer, AI Software Architect, and Engineering Manager. - -Work proceeds in two modes: a generic resume that fits the target roles and market, and job-specific tailoring for individual postings. - -**Privacy:** the user's own career objectives, target roles, and salary expectations are personal data and live only in their private `docs/PERSONAL_PROFILE.md` (gitignored) — never in this file or any other tracked file. - -## Repository Overview - -This is a LaTeX-based CV/Resume system, with a Claude Code skill pipeline, for producing bilingual (English/German) resumes for the Swiss tech market. - -## File Structure - -- `.claude/skills/` - The resume pipeline: the `swiss-tech-resume-builder` orchestrator plus `resume-*` sub-skills (profile coaching, market analysis, strategy, content generation, PDF render, content/design review) and `swiss-tech-resume-setup`. -- `.claude/agents/` - The two review agents: `swiss-tech-resume-reviewer` and `design-reviewer`. -- `.claude-plugin/` - Marketplace + plugin manifests (this repo is an installable Claude Code plugin). -- `docs/PERSONAL_PROFILE.md` - **Primary data source** (private, gitignored). Built and maintained via the `resume-profile-coach` skill. Template: `docs/PERSONAL_PROFILE.example.md`. -- `docs/MISSING_INFORMATION.md` - Durable profile-gap ledger (private, gitignored), owned by the profile coach. Template: `docs/MISSING_INFORMATION.example.md`. -- `docs/knowledge/` - Swiss-market standards (ATS, tone, bullets, grounding, conventions). -- `docs/style-guide/` - Design specifications (`pdf/` and `web/`). -- `resumes/templates/CV_template.tex` - Universal moderncv template for all role types. -- `resumes/customized/{id}/` - Per-application working files (private, gitignored): `resume_content.md`, the `.tex`, the compiled PDF, and `..._application_strategy.md`. -- `resumes/compiled/` - Final timestamped PDF outputs (private, gitignored). -- `resources/` - Portrait photos (private, gitignored). - -## Rendering - -PDF rendering is driven by the `resume-render-pdf` skill (invoked by the `swiss-tech-resume-builder` orchestrator): it fills the template from the approved `resume_content.md`, compiles with XeLaTeX, and cleans up. The skills are the single source of truth — see "Resume Workflow" below. - -For manual work on a `.tex` directly: -```bash -cd resumes/customized/{id}/ -xelatex {id}.tex -rm -f *.aux *.log *.out *.fls *.fdb_latexmk *.gz *.toc *.bbl *.blg # clean build artifacts -``` - -Always compile with XeLaTeX (never pdflatex). Templates use the `moderncv` class. - -## LaTeX Dependencies - -The CV uses: -- `moderncv` document class with **`fancy` style (REQUIRED)** -- Custom fonts via `fontspec` (Roboto, Lato, Roboto Slab) -- `moderntimeline` package for timeline visualizations -- `fontawesome` for icons -- Multiple language support via `babel` - -### CRITICAL: ModernCV Style Requirement -**ALWAYS use `\moderncvstyle{fancy}` for all CVs in this repository.** - -- The `fancy` style is MANDATORY because it properly handles multi-page documents -- The `casual` style has a fundamental bug causing "Unbalanced output routine" errors on multi-page CVs -- NEVER use `casual`, `classic`, `banking`, or `oldstyle` styles -- All templates use the `fancy` style -- See `docs/style-guide/pdf/MODERNCV_REFERENCE.md` for detailed technical reference - -## Development Notes - -- The `.gitignore` excludes LaTeX build artifacts (`*.log`, `*.aux`, `*.out`, `*.gz`) and all personal data (profile, customized/compiled resumes, PDFs, portrait photos) -- Primary data source is `docs/PERSONAL_PROFILE.md` - the comprehensive profile all resumes draw from -- If information is missing, check `docs/MISSING_INFORMATION.md` (the profile coach's gap ledger), then ask the user -- All resume generation should reference `docs/PERSONAL_PROFILE.md` for consistency and completeness - -## Web Resources - -Statistical Salary Calculator: https://www.salarium.bfs.admin.ch/ - -### Job Search Portals -See comprehensive list in `docs/JOB_AGENT_RESEARCH.md` (maintained via the `resume-market-analysis` skill) - -## Resume Workflow - -Resume creation is driven by the `swiss-tech-resume-builder` skill and its `resume-*` -sub-skills (`.claude/skills/`). Those skills are the authoritative, single source of truth -for the pipeline, decision gates, and review loops — do not duplicate workflow steps here. -The two review steps run via the `swiss-tech-resume-reviewer` and `design-reviewer` agents. - -## File Management - -### LaTeX Build Artifacts -Always clean up after compilation: -```bash -rm -f *.aux *.log *.out *.fls *.fdb_latexmk *.gz *.toc *.bbl *.blg -``` - -### Generated & temporary files -- **Temporary files**: Remove scratch/working files once their content is integrated into `docs/`. Never delete the skills or agents under `.claude/`. -- **Research files**: Consolidate market research into `docs/JOB_AGENT_RESEARCH.md` (gitignored). -- **Analysis files**: Merge insights into existing documentation rather than creating new files. - -### Directory Organization -- **Keep clean**: Remove duplicate or outdated files promptly -- **Naming convention**: Use timestamps for compiled PDFs: `YYYY_MM_DD_HH_MM_role_CV_lang.pdf` -- **Version control**: Track significant template changes and customizations - - -## Key Constraints -- **ModernCV Style**: ALWAYS use `\moderncvstyle{fancy}` - this is MANDATORY for multi-page support -- **cventry Format**: All `\cventry` commands must have exactly 6 arguments: `\cventry{dates}{title}{company}{location}{}{description}` -- **Job titles**: Never change job titles of past or current employments -- **Compilation**: NEVER use pdflatex. Always compile with xelatex -- **Data source**: Always reference docs/PERSONAL_PROFILE.md as the single source of truth -- **File organization**: template in `resumes/templates/`, per-application work in `resumes/customized/{id}/`, final timestamped PDFs in `resumes/compiled/` -- **Clean up**: Clean up any temporary files and experiments when you are done compiling a new version of the CV -- **Page count**: Do not feel you need to fit the whole CV on 1 page. 2-3 page CVs are preferred with room for comprehensive background -- **GitHub Repository Link**: ALWAYS include a link to the GitHub repository at the end of every generated resume with the text: "Curious how this resume was built? Explore the system at github.com/datarian/CV" -- **Privacy**: never put personal data (real profile, salary, career goals) in tracked files; it belongs only in the gitignored `docs/PERSONAL_PROFILE.md` -- **Preview availability**: Preview mode available during development without approval, no credentials required \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/README.md b/README.md index 5d175cc..e4b16ad 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@ # Swiss Tech Resume Builder -A Claude Code **plugin** that turns your experience into an ATS-optimized, Swiss-market resume. -You keep one profile of everything you've done; the plugin researches the target role, plans a -strategy, writes grounded content, renders a polished PDF, and reviews it against quality gates — -then hands you a tailored application strategy (cover letter, salary negotiation, interview prep). +A **portable Agent Skills bundle** that turns your experience into an ATS-optimized, Swiss-market +resume. You keep one profile of everything you've done; the system researches the target role, +plans a strategy, writes grounded content, renders a polished PDF, and reviews it against quality +gates — then hands you a tailored application strategy (cover letter, salary negotiation, interview +prep). -It runs entirely inside [Claude Code](https://docs.claude.com/claude-code) and installs in two -commands — no cloning or copying files. +The pipeline is authored once to the [Agent Skills standard](https://agentskills.io/specification) +and runs across **Claude Code, Gemini CLI, Cursor, and Pi** — see +[Use it with other agents](#use-it-with-other-agents). In Claude Code it installs as a plugin in two +commands; with the other agents you clone the repo and the skills are discovered automatically. ## Table of contents @@ -15,26 +18,30 @@ commands — no cloning or copying files. - [Requirements](#requirements) - [What it does](#what-it-does) - [Examples](#examples) +- [Use it with other agents](#use-it-with-other-agents) - [Your data stays private](#your-data-stays-private) - [Customize it for another market](#customize-it-for-another-market) - [Resources](#resources) ## Install -In Claude Code: +**Claude Code (easiest — installs as a plugin):** ```text /plugin marketplace add datarian/CV /plugin install swiss-tech-resume-builder@swiss-tech-resume ``` -That's it — the plugin brings everything it needs: the skills, the review agents, the LaTeX -template, the Swiss-market knowledge base, and the style guide. Update later with +That's it — the plugin brings everything it needs: the skills, the two forked review skills, the +LaTeX template, the Swiss-market knowledge base, and the style guide. Update later with `/plugin marketplace update swiss-tech-resume`. +**Gemini CLI, Cursor, or Pi:** clone the repo and run your agent inside it — the skills are +discovered automatically. See [Use it with other agents](#use-it-with-other-agents). + ## Quick start -After installing, just ask: +Once it's available (installed in Claude Code, or running your agent inside a clone), just ask: ```text > How do I use the Swiss tech resume builder? @@ -44,13 +51,13 @@ This runs the setup helper, which: 1. **Checks your prerequisites** (see [Requirements](#requirements)) and tells you what's missing. 2. **Creates your profile** — `docs/PERSONAL_PROFILE.md`, started from a template — in your own - project. This is your single source of truth: it holds *all* your experience, and the plugin + project. This is your single source of truth: it holds *all* your experience, and the system pulls the relevant parts for each application. 3. **Sets up your workspace** so generated resumes land in `resumes/` in your project. ### Build your profile by chatting — meet the profile coach -You don't write the profile by hand. The plugin includes a built-in **profile coach** that builds +You don't write the profile by hand. The system includes a built-in **profile coach** that builds it *with* you: hand it your source material and it extracts your experience, structures it onto the profile, and — the part that matters most — spots the gaps between where you want to go and what you've actually documented. @@ -90,7 +97,8 @@ You get back a compiled PDF and a paired application-strategy document. ## Requirements -The plugin runs in Claude Code; producing the PDF additionally needs, on your machine: +The pipeline runs in any supported agent (Claude Code, Gemini CLI, Cursor, Pi); producing the PDF +additionally needs, on your machine: - **XeLaTeX** — a TeX distribution with the `moderncv`, `moderntimeline`, and `fontawesome` packages. @@ -100,7 +108,7 @@ The plugin runs in Claude Code; producing the PDF additionally needs, on your ma - **Python 3** — for the helper that scaffolds each application. The setup helper checks all of these and points you at anything that's missing, so the easiest -path is to install the plugin and let it walk you through setup. +path is to install it (or open a clone in your agent) and let it walk you through setup. ## What it does @@ -113,10 +121,10 @@ You talk to the resume builder in plain language; behind the scenes it runs a re | **Market analysis** | Researches the target role: salary benchmarks, in-demand skills, ATS keywords | | **Strategy** | Decides positioning, section emphasis, and which keywords to feature | | **Content** | Writes the resume from your profile — every claim grounded in what you actually did | -| **Content review** | An expert reviewer scores the content and ATS match; it must pass before rendering | +| **Content review** | A forked review skill scores the content and ATS match with fresh eyes; it must pass before rendering | | **Your review** | You get to read and edit the content — still plain markdown — before anything is rendered | | **PDF render** | Produces a polished moderncv PDF | -| **Design review** | A design reviewer checks layout and typography against the style guide | +| **Design review** | A forked review skill checks layout and typography against the style guide | | **Strategy doc** | Generates a paired application strategy: cover-letter angle, salary negotiation, interview prep | Two things make the output trustworthy: @@ -129,7 +137,9 @@ Two things make the output trustworthy: you. Everything is generated from one source — `docs/PERSONAL_PROFILE.md` — so you maintain a single, -comprehensive profile and produce as many targeted resumes as you need. +comprehensive profile and produce as many targeted resumes as you need. And the pipeline itself is +authored from a single source: the skills live once in `.agents/skills/`, so the same reviewed +workflow behaves identically whichever agent you run it in. ## Examples @@ -153,19 +163,56 @@ You get, under resumes/customized/{date}_companyx_senior_ml_engineer/: • an application strategy: cover-letter angle, salary range, interview prep, fit assessment ``` -If you prefer to start an application from the command line, the plugin ships a small helper: +If you prefer to start an application from the command line, the system ships a small helper: ```bash -python3 "${CLAUDE_PLUGIN_ROOT}/.claude/skills/swiss-tech-resume-builder/scripts/init_application.py" \ +# From a clone of this repo (skills live under .agents/skills/): +python3 .agents/skills/swiss-tech-resume-builder/scripts/init_application.py \ + --company companyx --role ml_engineer +# In Claude Code as an installed plugin, prepend the install root: +python3 "${CLAUDE_PLUGIN_ROOT}/.agents/skills/swiss-tech-resume-builder/scripts/init_application.py" \ --company companyx --role ml_engineer ``` It scaffolds the application folder under `resumes/customized/` in your project and finds the bundled template automatically. +## Use it with other agents + +The whole pipeline is authored once in `.agents/skills/` to the +[Agent Skills standard](https://agentskills.io/specification). Each agent's expected skills +directory is a symlink into that one canonical tree, so there's a single source of truth — you +never maintain parallel copies. Project guidance lives in `AGENTS.md` (with `CLAUDE.md` and +`GEMINI.md` as symlinks to it). + +Clone the repo and run your agent from inside it: + +```bash +git clone https://github.com/datarian/CV +cd CV +``` + +| Agent | How skills load | +|-------|-----------------| +| **Claude Code** | Install as a plugin (above), or run in a clone — skills resolve via `.claude/skills/` (symlink) and the plugin manifest. | +| **Pi** | Run `pi` inside the clone — skills under `.agents/skills/` are auto-discovered (no config). Or install remotely: `pi install git:github.com/datarian/CV` (the root `package.json` declares `pi.skills`). | +| **Gemini CLI** | Symlink `.gemini/skills → ../.agents/skills` and point Gemini at `AGENTS.md` via `.gemini/settings.json`. *(adapter pending)* | +| **Cursor** | Symlink `.cursor/skills → ../.agents/skills`; `AGENTS.md` is read natively. *(adapter pending)* | + +Then ask the same things you would in Claude Code (e.g. *"Build me a Swiss-market resume for +Senior ML Engineer roles"*); invoke the orchestrator explicitly with `/skill:swiss-tech-resume-builder` +where your agent supports it. + +> **Notes.** The PDF pipeline needs only XeLaTeX + Python (see [Requirements](#requirements)) and no +> MCP, so it works the same everywhere. The optional **web preview** uses a Playwright MCP that is +> configured per-agent (`.claude/.mcp.json` for Claude Code; Pi/Gemini/Cursor MCP wiring is a +> documented follow-up). The mandatory render constraints (moderncv `fancy`, XeLaTeX-only, 6-arg +> `\cventry`, GitHub footer) live inside the render skill itself, so they hold on every agent even +> if it doesn't read `AGENTS.md`. + ## Your data stays private -Your resume content never leaves your machine, and nothing personal is part of the plugin. +Your resume content never leaves your machine, and nothing personal is part of the published system. - `docs/PERSONAL_PROFILE.md`, your generated resumes (`resumes/customized/`, `resumes/compiled/`), all PDFs, and any portrait photos are kept local and are excluded from version control by @@ -178,17 +225,23 @@ PDFs, or files under `resumes/customized/` are staged. ## Customize it for another market -The system is built to be adapted. Edit the knowledge base and template to target a different -country, industry, or role family, then publish your fork as its own marketplace by updating -`.claude-plugin/marketplace.json` and `.claude-plugin/plugin.json`. Others install your version -with the same two `/plugin` commands. +The system is built to be adapted. Edit the knowledge base and template (under `docs/` and +`resumes/templates/`) and the skills (under `.agents/skills/`) to target a different country, +industry, or role family. To redistribute your fork, update the manifests for whichever agents you +publish to: `.claude-plugin/marketplace.json` + `.claude-plugin/plugin.json` for the Claude Code +marketplace, and the root `package.json` (`pi.skills`) for Pi. Others install your Claude Code +version with the same two `/plugin` commands, or clone your fork for the other agents. ## Resources - Swiss official salary calculator: - moderncv documentation: +- Agent Skills standard: - Claude Code plugins: - Claude Code: +- Gemini CLI: +- Cursor: +- Pi coding agent: --- diff --git a/package.json b/package.json new file mode 100644 index 0000000..71fd718 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "swiss-tech-resume-builder", + "version": "0.2.0", + "description": "Portable Agent Skills bundle that builds ATS-optimized resumes for the Swiss tech job market (Claude Code, Gemini CLI, Cursor, Pi).", + "keywords": [ + "pi-package", + "agent-skills", + "resume", + "cv", + "ats", + "swiss" + ], + "license": "CC-BY-NC-SA-4.0", + "private": true, + "repository": { + "type": "git", + "url": "https://github.com/datarian/CV" + }, + "homepage": "https://github.com/datarian/CV", + "author": "Florian Hochstrasser (https://github.com/datarian)", + "pi": { + "skills": [ + ".agents/skills" + ] + } +}