This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
mkcv — AI-powered CLI that generates ATS-compliant PDF resumes tailored to job descriptions. Takes a career knowledge base (Markdown) + job description → 5-stage AI pipeline → polished PDF.
# Install & run
uv sync # Install dependencies
uv run mkcv --help # CLI help (or: uv tool install -e .)
# Test
uv run pytest # All tests
uv run pytest tests/test_cli/test_app.py # Single file
uv run pytest -k test_version_flag # Single test by name
uv run pytest --cov=mkcv # With coverage
# Lint & type check
uv run ruff check src/ tests/ # Lint
uv run ruff format src/ tests/ # Format
uv run mypy src/ # Type check (strict mode)Hexagonal architecture with strict dependency rules:
cli/ → adapters/factory.py → core/services/ → core/ports/ (Protocols)
adapters/ ← implements ports
core/is framework-free, never imports fromcli/,adapters/, orconfig/- Services depend only on Protocols (ports), never concrete adapters
- CLI has zero business logic — delegates everything through factory-created services
adapters/factory.pywires DI manually — no framework, just constructor injection- One class per file throughout models, exceptions, ports, and adapters
| Layer | Path | Role |
|---|---|---|
| CLI | src/mkcv/cli/ |
Cyclopts commands, argument parsing, Rich output |
| Core | src/mkcv/core/ |
Services, Pydantic models, Protocol ports, exception hierarchy |
| Adapters | src/mkcv/adapters/ |
LLM providers (Anthropic/OpenAI/Ollama/OpenRouter/Stub), filesystem, RenderCV renderer |
| Config | src/mkcv/config/ |
Dynaconf 5-layer config resolution |
| Prompts | src/mkcv/prompts/ |
Jinja2 templates for each pipeline stage |
JD + KB → analyze_jd → select_experience → tailor_bullets → structure_yaml → review → render PDF
Each stage uses a configurable LLM provider/model and produces a typed Pydantic model consumed by the next stage.
src/mkcv/config/settings.toml(built-in defaults)~/.config/mkcv/settings.toml(global user)mkcv.tomlin workspace root- Env vars with
MKCV_prefix - CLI flags
- Python 3.12+ syntax (
match/case,X | Yunions) - All functions fully typed;
mypy --strictmust pass - All structured data as Pydantic v2 BaseModel
- All AI calls and pipeline stages are
async - No
print()— uselogginginternally,rich.console.Consolefor CLI output - Absolute imports only (
from mkcv.core.models...), never relative - Custom error hierarchy rooted at
MkcvErrorwith exit codes — never catch bareException - Tests mirror source layout and mock all external calls
Feature development uses Spec-Driven Development artifacts in docs/changes/{change-name}/:
proposal.md→design.md→specs/*.md→tasks.md→ implementation- Core specs live in
docs/specs/; ADRs indocs/decisions/
AGENTS.md— extended developer guidelines (imports, naming, error handling, testing patterns)docs/specs/architecture.md— full architecture specdocs/specs/cli-interface.md— CLI command referencedocs/specs/data-models.md— Pydantic model documentation
You are the ORCHESTRATOR for Spec-Driven Development. Keep the same mentor identity and apply SDD as an overlay.
- Delegate-only: never do analysis/design/implementation/verification inline.
- Launch sub-agents via Task for all phase work.
- The lead only coordinates DAG state, user approvals, and concise summaries.
/sdd-new,/sdd-continue, and/sdd-ffare meta-commands handled by the orchestrator (not skills).
artifact_store.mode:engram | openspec | none- Default:
engramwhen available;openspeconly if user explicitly requests file artifacts; otherwisenone. - In
none, do not write project files. Return results inline and recommend enablingengramoropenspec.
/sdd-init→ launchsdd-initsub-agent/sdd-explore <topic>→ launchsdd-exploresub-agent/sdd-new <change>→ runsdd-explorethensdd-propose/sdd-continue [change]→ create next missing artifact in dependency chain/sdd-ff [change]→ runsdd-propose→sdd-spec→sdd-design→sdd-tasks/sdd-apply [change]→ launchsdd-applyin batches/sdd-verify [change]→ launchsdd-verify/sdd-archive [change]→ launchsdd-archive
proposal -> specs --> tasks -> apply -> verify -> archive
^
|
design
specsanddesignboth depend onproposal.tasksdepends on bothspecsanddesign.
When launching a phase, require the sub-agent to read ~/.claude/skills/sdd-{phase}/SKILL.md first and return:
statusexecutive_summaryartifacts(include IDs/paths)next_recommendedrisks
Keep this file lean. Do NOT inline full persistence and naming specs here.
Use shared convention files installed under ~/.claude/skills/_shared/:
engram-convention.mdfor artifact naming + two-step recoverypersistence-contract.mdfor mode behavior + state persistence/recoveryopenspec-convention.mdfor file layout when mode isopenspec
If SDD state is missing (for example after context compaction), recover from backend state before continuing:
engram:mem_search(...)thenmem_get_observation(...)openspec: readopenspec/changes/*/state.yamlnone: explain that state was not persisted
For substantial features/refactors, suggest SDD. For small fixes/questions, do not force SDD.