scottgal/lucidRESUME

lucidRESUME is a free, open-source desktop editor for evidence-backed resumes. You write and own the human prose. The app keeps a separate, higher-resolution JobML representation for ATS and AI systems, with every machine-facing claim linked to the evidence that supports it.

C#

7

221 commits

updated Sep 30, 2026

See the code

README

lucidRESUME

NOTE: lucidRESUME is a research project and not intended as a product for general use.

lucidRESUME release lucidRESUME total downloads Mostlylucid.Avalonia.UITesting on NuGet NuGet downloads

Human prose for people. Evidence-linked JobML for machines.

lucidRESUME is a free, open-source desktop editor for evidence-backed resumes. You write and own the human prose. The app keeps a separate, higher-resolution JobML representation for ATS and AI systems, with every machine-facing claim linked to the evidence that supports it.

It builds a structured ledger from your resumes, LinkedIn data, repositories, and other sources, then uses that ledger to:

  • Project role-specific resumes from a persistent evidence ledger
  • Match you to relevant roles with per-skill similarity scoring
  • Show what you're missing (and what you're not)
  • Plan your next move based on your actual skill graph

The ledger and deterministic extraction pipeline run locally on your machine. No account is required. Data leaves your machine only when you explicitly configure a cloud AI provider, import a remote source, or use an online job-search service.

OpenAI is the primary full-strength provider for assisted ingestion and optional drafting. Anthropic and Ollama are also supported. grug 9B through LLamaSharp is an experimental offline path. These providers can offer an explicitly labelled prose draft or sample. A draft is not accepted prose, evidence, or a published claim. The person remains the author and decides what to edit, accept, and publish.

Projection itself is deterministic. It selects reviewed resume, LinkedIn, and GitHub ledger records and starts with the accepted human prose. An optional, bounded editing stage may tighten those selected passages with local grug 9B or OpenAI. The deterministic planner first fits complete source sentences to a compact per-section budget. Model edits are then accepted section by section; any edit that changes claim or evidence identity, invents a number, borrows an unsupported vacancy term, or exceeds its budget falls back to the valid human selection. Detailed experience remains selective. Accepted roles omitted from the detailed projection are preserved in a compact end-of-experience chronology when they lasted more than three months; shorter engagements are left in the complete career record. Chronology lines are deterministic ledger projections and never go through a prose-editing model. The result exports as one evidence-linked artifact in Markdown, Word, or PDF. Published documents use inline numbered citations and a compact cJobML References section. A citation can open the exact role or project in the published full career transcript. Full JobML retains the passage selectors, drift hashes, review state, and semantic metadata omitted from the compact document. Transcript links expose the fuller candidate-maintained account; repositories, articles, releases, qualifications, and similar artefacts remain distinguishable as stronger external evidence. See the design article. See resume output and template design for the full flow, template rationale, and configuration.

Built with .NET 10 + Avalonia. Runs on Windows, macOS, and Linux.


Core Idea

Every skill is backed by evidence.

lucidRESUME doesn't just list what you say you know - it builds a skill ledger where each skill is tied to:

  • Where it appeared (job, project, repo)
  • When you used it (date ranges, calculated years)
  • How often it shows up across roles
  • How strong the evidence is (recency, frequency, confidence)

No invented skills. No output-time guessing. Extraction is recorded once with its method, confidence, source, and review state.

An optional local Ollama Nimble decision layer can resolve bounded ingestion ambiguities after local rules and NER have proposed candidates. It can classify an unknown section or prose-linked skill, or select an already-extracted person or employer span. It cannot generate a new name, company, claim, or evidence value. Every decision is probability-gated, source-hashed, and recorded for review. Nimble is disabled by default. See the local setup and decision guide. Cloud API keys entered in Profile are held by the operating system credential store, never in the JSON settings file.

This is the foundation everything else builds on - matching, projection, gap analysis, and career direction.

The two representations have different jobs:

  • Human prose is written for human readers. It should sound like its author.
  • JobML is written for machines. It can be more explicit and more detailed, but it must remain traceable to reviewed prose or external evidence.
  • AI may suggest draft prose. It cannot silently publish that prose, create accepted evidence, or turn an inference into fact.

lucidRESUME is not an automated job application service and it is not intended to disguise machine-written text as human writing. Its purpose is to let human writing remain human while giving ATS and AI systems a precise, verifiable view.

The experimental JobML 0.1 editor places authoritative human Markdown on the left, editable JobML on the right, and live evidence links between them. Selecting a link highlights both the supporting prose and machine reference. As prose changes, claims are marked valid, changed, missing, or ambiguous; inferred claims never become evidence without explicit acceptance. Markdown may be shorter for a particular role while JobML retains higher-resolution external evidence. Its default Document tab is a debounced live DOCX projection through the selected output template, rendered by Morph beside those evidence links. It does not re-extract or reinterpret the ledger. See the JobML specification, cJobML publication specification, implementation profile, and GitHub repository extension.

DOCX PreviewMy Data Dashboard

Why lucidRESUME?

Every major job site wants your email, your browsing history, and permission to sell your profile. AI resume tools send your CV to some SaaS vendor's cloud. Paid tools charge monthly for table-stakes features.

lucidRESUME does things differently:

  • Evidence-first AI - full-strength OpenAI is the primary assisted path; grug 9B Q4_K_M through LLamaSharp remains an experimental offline option. Neither path runs during deterministic projection.
  • No account required - data stored in a local SQLite database. You own it.
  • Evidence-led projection - Project only renders claims already present in the ledger.
  • Career direction (based on your actual skill graph) - not just "match this job" but "what to do next to reach your target cluster".
  • Free forever - Unlicense. Public domain.

What It Does

Resume Import

Resume import with DOCX preview

  • Drag and drop any file onto the app to import — resumes, LinkedIn exports, anything
  • Import PDF or DOCX resumes
  • DOCX preview powered by Morph — cross-platform document-to-image rendering in pure C#, no LibreOffice needed
  • LinkedIn data export — drop your LinkedIn ZIP archive and it auto-detects and imports your full profile: positions, skills (with endorsement counts), education, projects, contact info
  • GitHub evidence - imports Linguist language totals, topics, README-derived candidates, project dates, and repository provenance. A bounded deep audit records original/fork status, repository age, activity span, tests, CI, release automation, package manifests, documentation, and browser-extension structure. Archived and small repositories remain visible as historical or experimental observations. Forks and repositories below the evidence threshold do not nominate personal skills by default. Observed technologies remain separate from reviewed personal claims.
  • NuGet package families - audits a public publisher profile and official V3 metadata, then groups package IDs by source product. Package count, public downloads, tags, and source repositories become searchable ledger evidence, not automatic résumé prose or claims of proficiency.
  • All imports merge into a single unified candidate document using embedding cosine similarity — no duplicates, full source tracking
  • Handles two-column, LaTeX, complex formatting
  • Template learning: learns your resume's structure on first parse, deterministic on subsequent imports
  • Multilingual: German, French, Spanish, Portuguese, Chinese, Dutch, Japanese, Korean

Skill Ledger

My Data — skills dashboard with pie chart, Gantt timeline, and skill communities

  • Provenance chain: skill -> which job -> which date range -> which bullet point
  • Calculated years: sum of non-overlapping date ranges where the skill appears
  • Evidence strength: combining years, role count, recency, confidence
  • Consistency checking: flags skills listed but never demonstrated, claimed vs calculated years
  • Presentation gap vs true gap: "you have adjacent skills" vs "you don't have this at all"

Smart Matching

Jobs page with Looking/Hiring toggle

  • Multi-vector cosine similarity between resume and JD skill ledgers
  • 3-layer matching: substring -> embedding similarity -> achievement-text keyword search
  • Per-skill match detail with similarity scores, evidence strength, calculated years

Career Direction

  • Skill graph with co-occurrence edges and Leiden community detection
  • Career planner: 4 gap types (PresentationGap, WeakEvidence, AdjacentSkill, TrueGap)
  • Effort/impact ranking: Low (rewording), Medium (side project), High (new learning)
  • Search query generator: suggests job searches from your strongest skill communities

Evidence Projection

  • Treats the complete human career transcript and its canonical ledger as source data
  • Exports that source as a portable JobML career_record, including sources and optional semantic artefacts
  • Detects role requirements, then deterministically plans sections and selects evidence
  • Semantic compression: 13 roles -> 6 relevant -> filtered to evidence-backed bullets
  • Optionally runs bounded tightening and human-voice passes over selected source prose
  • Renders Markdown and JobML together without output-time evidence re-inference
  • Links compressed statements to the exact source role or project in the complete transcript
  • Distinguishes candidate-maintained transcript provenance from external supporting artefacts
  • Preserves human-owned prose while JobML carries explicit machine detail

Embeddable web compiler

lucidRESUME.Web is an ASP.NET Core control for the narrow publish-and-compile workflow. It does not ingest LinkedIn exports, repositories, or old CVs. That happens upstream in the desktop application. The control accepts the already exported Markdown + JobML career_record, publishes an immutable revision, accepts a job description, and returns a shorter evidence-bounded projection with Markdown, Word, and PDF downloads. Each published application receives an opaque URL whose browser view shows the résumé, its selected claims, and links into the complete transcript. The same publication exposes full JobML and cJobML to machine clients. The application career ledger remains the canonical source; the published JobML document is its portable projection. OpenAI is the default interactive editor. The local LLamaSharp path batches the projection in ordered groups of three and can recover complete section objects from a truncated response without accepting an incomplete edit. The compiler keeps the reviewed summary outside model editing, orders experience in reverse chronology, and deterministically adds the detected target title, canonical evidence-backed skills, role-relevant projects, and reviewed education.

JobML web compiler rendering an evidence-linked projection

builder.Services.AddLucidResumeCompiler(builder.Configuration);

var app = builder.Build();
app.UseAntiforgery();
app.MapLucidResumeCompiler();
app.Run();

Run the included host with:

dotnet run --project samples/lucidRESUME.Web.Sample

The control is mounted at /resume by default. The current career-record projection is served at /resume/api/jobml; immutable source revisions and application-specific publication URLs carry ETags and cache headers. API keys remain server-side. See the web compiler guide.

For the adjacent Mostlylucid site checkout, run scripts/run-local-resume-integration.sh to serve the compiler at http://127.0.0.1:8080/resume/. Publish the reviewed Markdown and JobML career record locally, paste a job description, then use the resulting evidence link to inspect the full transcript, ordered source chunks, cJobML, Word, and PDF. The sample's App_Data publications are ignored by Git; keep private career records out of commits. Local Ollama setup and gateway configuration are in the web compiler guide.

Personal ATS (Pipeline)

Pipeline tracking

  • Stage pipeline: Saved -> Applied -> Screening -> Interview -> Offer -> Accepted/Rejected/Withdrawn/Ghosted
  • Timeline per application, funnel visualization, stale detection
  • Email integration (IMAP via MailKit): auto-detects confirmations, interviews, rejections, offers

Seven job board adapters searched in parallel (Adzuna, Reed, Findwork, Arbeitnow, JoinRise, Jobicy, Remotive). Near-duplicate detection via embedding similarity. Hoover role flagging.

Export

JSON Resume (standard schema), Markdown, DOCX (Word via OpenXml), and tagged PDF/UA (QuestPDF). DOCX uses real Word lists and named headings; both office formats keep identity in the document body and avoid tables, sidebars, text boxes and repeated résumé headers.

Documentation

CLI

lucidresume parse          --file cv.docx [--output result.json]
lucidresume evidence       --resume cv.docx [--output ledger.json]
lucidresume match          --resume cv.docx --job "JD text"
lucidresume compound-match --resume cv.docx --jobs-dir jds/
lucidresume explain        --resume cv.docx --job "JD text"
lucidresume tailor         --resume cv.docx --job "JD text" [--full-jobml https://example.net/career.jobml] [--output projected.md]
lucidresume drift          --resume1 old.docx --resume2 new.docx
lucidresume export         --file cv.docx --format pdf|docx|markdown|json
lucidresume validate       --resume cv.docx
lucidresume fix            --resume cv.docx [--output fixed.md]
lucidresume generate       --resume cv.docx --prompt "draft a 2 page cloud resume" [--full-jobml https://example.net/career.jobml]
lucidresume anonymize      --resume cv.docx [--output anon.json]
lucidresume rank           --dir resumes/ --job "JD text"
lucidresume search         --prompt "senior .NET developer remote"
lucidresume extract-jd     --job "JD text" [--output jd.json]
lucidresume github-import  --username scottgal --output repositories.json
lucidresume package-audit  --publisher mostlylucid --output packages.json
lucidresume batch-test     --dir resumes/
lucidresume jobml validate  --file resume.jobml.md
lucidresume jobml reconcile --file resume.jobml.md
lucidresume jobml coverage  --file resume.jobml.md
lucidresume jobml cold-parser-probe --file resume.jobml.md
lucidresume jobml career-record --resume-dir /path/to/resumes --github scottgal --nuget-publisher mostlylucid --output career.jobml.md
lucidresume jobml compact --file resume.jobml.md --full-jobml https://example.net/career.jobml --output resume.md
lucidresume jobml link-post --file resume.jobml.md --claim claim-id --url https://example.net/article --output linked.jobml.md

Role projections include compact cJobML citations in Markdown, Word, and PDF by default. Pass --cjobml false to tailor, generate, or render for a human-only copy. --full-jobml gives transcript references an exact deep link. Compact references can cite transcript sections and public evidence without copying full passages, selectors, or drift hashes out of the full JobML career record.

Career anchors

Relevance and recency should not erase a defining older role. Mark a role as Always include on the My Data page, or place an invisible directive directly below its Markdown heading:

### Program Manager II | Microsoft Corp
<!-- lucidresume:career-anchor -->

The full JobML career_record publishes this as projection: { include: always }. Compilers reserve anchor sections before ranking ordinary roles. The preference does not strengthen the role's claims or bypass evidence validation.

CLI and server configurations may anchor every role for selected companies:

{
  "Tailoring": {
    "CareerAnchorCompanies": ["Microsoft", "Dell"]
  }
}

Company anchoring is explicitly configured by the author. lucidRESUME does not maintain an inferred employer-prestige score.


Getting Started

Download & Install

  1. Go to the latest release
  2. Download the archive for your platform:
PlatformDownload
WindowslucidRESUME-...-win-x64.zip or win-arm64.zip
macOSlucidRESUME-...-osx-arm64.tar.gz (Apple Silicon) or osx-x64.tar.gz (Intel)
LinuxlucidRESUME-...-linux-x64.tar.gz or linux-arm64.tar.gz
  1. Extract the archive. On macOS, open lucidRESUME.app. On Windows or Linux, run lucidRESUME.exe or lucidRESUME respectively.

The desktop app downloads its local ONNX models (about 600 MB) on first launch. They are cached in the user data directory, outside the signed application bundle. No account or setup wizard is required.

macOS users: the bundle is ad-hoc signed but not notarized. If Gatekeeper blocks it, Control-click the extracted app and choose Open. If needed, run xattr -dr com.apple.quarantine ./lucidRESUME.app on that app only.

AI-assisted ingestion and drafts (Optional)

AI assistance is optional. It can recover structured candidates from difficult source documents or offer a clearly labelled authoring draft. Every inferred record is stored with provenance and requires review. Draft prose remains unaccepted until a person edits and approves it. Resume projection and export work without a language model.

Option 1: OpenAI (primary full-strength provider)

  1. Open Profile → AI Provider
  2. Enter your OpenAI API key and select openai
  3. Select the model and save. The key is stored in the operating system credential store.

Option 2: Local AI with LLamaSharp (experimental)

  1. Open Profile → AI Provider
  2. Select llamasharp and click Download local model
  3. Restart the app after the 5.63 GB Q4_K_M download completes

The model is loaded lazily and uses its embedded chat template. Apple Silicon uses the Metal support included in the LLamaSharp CPU backend; other platforms have a portable CPU fallback. Set LlamaSharp:ModelPath, ContextSize, or GpuLayerCount in lucidresume.json to override the defaults. Relative model paths resolve under the user data directory, outside the signed application bundle.

Option 3: Local AI with Ollama

  1. Install Ollama and run ollama pull qwen3.5:4b
  2. Select ollama under Profile → AI Provider

Option 4: Anthropic

  1. Open the Profile page in the app
  2. Enter your Anthropic API key and select anthropic

Build from Source

For developers who want to build from source:

git clone https://github.com/scottgal/lucidRESUME
cd lucidRESUME
dotnet run --project src/lucidRESUME/lucidRESUME.csproj

Requires .NET 10 SDK. The default solution is desktop-only, so dotnet build lucidRESUME.sln and dotnet test lucidRESUME.sln do not require mobile workloads. See docs/release.md for the release workflow.


How It Works (Technical)

Extraction

5-layer RRF fusion for both resume and JD extraction: structural patterns + ONNX NER (2 models) + skill taxonomy centroids (19,983 skills from 1.3M LinkedIn jobs) + optional LLM candidate extraction + entity lookup (11K companies, 7K locations). All signals run during ingestion and are fused by reciprocal rank fusion with multi-source confidence boosting. The resulting evidence records are persisted with provenance and review state.

Export is deliberately less clever. It is a projection of accepted ledger records. It does not rerun NER or an LLM, and it refuses stale evidence. This keeps the human prose and the JobML evidence graph reversible: each rendered claim points back to the exact ingested evidence and source revision that justified it.

Skill taxonomy: 19,983 preprocessed entries from the documented Kaggle/LinkedIn datasets ship with the application, together with priority data and compact leadership profiles for Lead Developer, Head of Engineering, CTO and VP Engineering. These source terms are the reproducible seeds for exact matching and locally materialised role centroids. No personal résumé, ledger or user database is part of the preload. Used by both resume and JD parsers to find skills embedded in prose.

The exact clean-install boundary, dataset provenance and release audit are documented in Product data and clean-install contract.

ONNX embeddings (all-MiniLM-L6-v2, 384-dim) power semantic matching throughout. DocLayNet YOLO model detects document structure from rendered page images — titles, section headers, tables, lists — producing a structural hash for template identification. Docling (Docker) adds ML-based PDF layout detection for complex documents; PdfPig with column detection as local fallback.

Architecture

lucidRESUME (Avalonia UI: My CV, JobML Editor, My Data, Career, Jobs, Add Job, Project, Pipeline, Profile, Help)
    ├── Ingestion        Resume parsing, DocLayNet layout detection, Morph preview, LinkedIn import
    ├── Extraction       ONNX NER (2 models) + Microsoft.Recognizers pipeline
    ├── Parsing          DOCX/PDF/TXT extraction, ATS pattern detection, template learning
    ├── JobSpec          JD parsing (5-layer RRF: Structural + NER + Taxonomy + LLM + Entity), URL scraping
    ├── JobSearch        7 job board adapters + orchestrator + deduplicator
    ├── Matching         Skill ledger, skill graph, career planner, taxonomy centroids, entity lookup
    ├── AI               LLamaSharp/Ollama/Anthropic/OpenAI ingestion and draft-authoring providers
    ├── Compiler         Complete JobML master -> deterministic role-specific projection
    ├── Web              Embeddable ASP.NET Core publish, preview, and export control
    ├── EmailTracker     IMAP scanning, email classification, application matching
    ├── Export           JSON Resume + Markdown + DOCX + PDF exporters
    ├── Collabora        Installed-editor discovery and LibreOffice fallback
    ├── Avalonia.UITesting  UI automation framework (REPL, MCP, script runner)
    └── Core             Domain models, interfaces, persistence (SQLite + sqlite-vec)

Dependency rule: everything depends inward on Core. Core depends only on Microsoft.Data.Sqlite and sqlite-vec.

Key Design Patterns

PatternWhereWhy
5-Layer RRF FusionResume + JD extractionStructural + NER + Taxonomy + LLM + Entity Lookup vote, best candidate wins
Skill TaxonomyMatching module19,983 skills from 1.3M LinkedIn jobs — cross-industry, not just tech
Entity LookupJD parser11K companies + 7K locations from LinkedIn/Adzuna validate NER candidates
Skill LedgerMatching moduleEvery skill backed by evidence with provenance
Skill Graph + CommunitiesCareer plannerLeiden community detection with UMAP visualisation
Template LearningDOCX parserFirst parse learns structure, subsequent parses are deterministic
ATS Pattern DetectionPDF parserYAML rulesets identify resume templates/ATS systems

Tests

dotnet test lucidRESUME.sln    # 479 tests across 12 projects
ProjectTestsCoverage
Core.Tests101Persistence, models, reviewed transcript overlays, multi-resume, export, linked posts
Extraction.Tests25NER, recognizers, RRF fusion pipeline
AI.Tests46Providers, embeddings, bounded decisions, deterministic projection, gated live OpenAI checks
Matching.Tests64Skill scoring, filters, voting, job-search resilience, projection quality
JobSpec.Tests16JD parsing, deterministic flattened-title extraction, salary extraction
EmailTracker.Tests25Classifier, matcher
GitHub.Tests44Language map, repository assessment, package families, LinkedIn parsing, reviewed document merge
JobML.Tests29Parsing, validation, drift, reversible links, cJobML projection
Compiler.Tests24Deterministic evidence selection, compact chronology and projection orchestration
Web.Tests5ASP.NET Core endpoint and projection control
App.Tests2Native operating-system credential storage
Avalonia.UITesting.Tests98Input, scripts, locators, screenshots, REPL

The Chrome evidence filler has a separate TypeScript suite:

cd extensions/lucidresume-chrome
npm ci && npm run check && npm test && npm run build

UX Testing

Mostlylucid.Avalonia.UITesting on NuGet NuGet downloads

The UI automation layer is published as a standalone NuGet package — Mostlylucid.Avalonia.UITesting — so any Avalonia desktop app can use it. Real pointer/touch/wheel/gesture input via Avalonia's IInputManager, region/control snipping for manuals, YAML scripts, GIF video, REPL, and an MCP server. Source lives in src/Mostlylucid.Avalonia.UITesting/.

# Run a YAML test script
dotnet run --project src/lucidRESUME/lucidRESUME.csproj -- \
  --ux-test --script ux-scripts/e2e-full-flow.yaml --output ux-screenshots

# Interactive REPL
dotnet run --project src/lucidRESUME/lucidRESUME.csproj -- --ux-repl

# MCP server (for LLM-driven UI control)
dotnet run --project src/lucidRESUME/lucidRESUME.csproj -- --ux-mcp

Roadmap

  • Optional resume authoring drafts and suggestions, always subject to human review
  • Automated job polling from skill community search queries
  • Resume extraction RRF fusion (multi-source confidence boost, same pattern as JD)
  • Career planner UI page with gap analysis visualization
  • Leiden community detection (refinement phase over Louvain greedy moves)
  • Temporal skill drift across resume variants (compare ledgers, detect added/dropped/changed skills)
  • DOCX export of projected resumes (pure C# via OpenXml, cross-platform)
  • PDF export of projected resumes (QuestPDF, professional formatting)
  • LinkedIn data export import (ZIP archive with full profile)
  • GitHub repo skills import (languages, topics, README analysis via lucidRAG)
  • DocLayNet ONNX model for document layout detection (YOLOv10m, 58MB, structural hashing)
  • RRF fusion name extraction (NER + positional + heading + email + LLM backstop — 92% accuracy)
  • Full CLI toolkit (17 commands: parse, evidence, match, explain, tailor, rank, fix, generate, etc.)
  • Batch testing and quality evaluation across 26 multilingual resumes
  • Skill taxonomy centroids (19,983 skills from 1.3M LinkedIn jobs + Kaggle role archetypes)
  • Entity lookup (11K companies, 7K locations, 144 industries from LinkedIn/Adzuna via DuckDB)
  • 5-layer JD parser (Structural + NER + Taxonomy + LLM + Entity — 0→60+ skills from plain text)

Contributing

PRs welcome. Run the tests before submitting:

dotnet test

The codebase follows a strict inward dependency rule - keep domain logic in Core and wire everything in the app shell.


License

This is free and unencumbered software released into the public domain. See LICENSE or unlicense.org for details.

No strings attached. No attribution required. Use it however you like.

Significant stargazers

iG

0 followers · starred Aug 2026

scottgal/lucidRESUME

lucidRESUME is a free, open-source desktop editor for evidence-backed resumes. You write and own the human prose. The app keeps a separate, higher-resolution JobML representation for ATS and AI systems, with every machine-facing claim linked to the evidence that supports it.

C#

7

221 commits

updated Sep 30, 2026

See the code

README

lucidRESUME

NOTE: lucidRESUME is a research project and not intended as a product for general use.

lucidRESUME release lucidRESUME total downloads Mostlylucid.Avalonia.UITesting on NuGet NuGet downloads

Human prose for people. Evidence-linked JobML for machines.

lucidRESUME is a free, open-source desktop editor for evidence-backed resumes. You write and own the human prose. The app keeps a separate, higher-resolution JobML representation for ATS and AI systems, with every machine-facing claim linked to the evidence that supports it.

It builds a structured ledger from your resumes, LinkedIn data, repositories, and other sources, then uses that ledger to:

  • Project role-specific resumes from a persistent evidence ledger
  • Match you to relevant roles with per-skill similarity scoring
  • Show what you're missing (and what you're not)
  • Plan your next move based on your actual skill graph

The ledger and deterministic extraction pipeline run locally on your machine. No account is required. Data leaves your machine only when you explicitly configure a cloud AI provider, import a remote source, or use an online job-search service.

OpenAI is the primary full-strength provider for assisted ingestion and optional drafting. Anthropic and Ollama are also supported. grug 9B through LLamaSharp is an experimental offline path. These providers can offer an explicitly labelled prose draft or sample. A draft is not accepted prose, evidence, or a published claim. The person remains the author and decides what to edit, accept, and publish.

Projection itself is deterministic. It selects reviewed resume, LinkedIn, and GitHub ledger records and starts with the accepted human prose. An optional, bounded editing stage may tighten those selected passages with local grug 9B or OpenAI. The deterministic planner first fits complete source sentences to a compact per-section budget. Model edits are then accepted section by section; any edit that changes claim or evidence identity, invents a number, borrows an unsupported vacancy term, or exceeds its budget falls back to the valid human selection. Detailed experience remains selective. Accepted roles omitted from the detailed projection are preserved in a compact end-of-experience chronology when they lasted more than three months; shorter engagements are left in the complete career record. Chronology lines are deterministic ledger projections and never go through a prose-editing model. The result exports as one evidence-linked artifact in Markdown, Word, or PDF. Published documents use inline numbered citations and a compact cJobML References section. A citation can open the exact role or project in the published full career transcript. Full JobML retains the passage selectors, drift hashes, review state, and semantic metadata omitted from the compact document. Transcript links expose the fuller candidate-maintained account; repositories, articles, releases, qualifications, and similar artefacts remain distinguishable as stronger external evidence. See the design article. See resume output and template design for the full flow, template rationale, and configuration.

Built with .NET 10 + Avalonia. Runs on Windows, macOS, and Linux.


Core Idea

Every skill is backed by evidence.

lucidRESUME doesn't just list what you say you know - it builds a skill ledger where each skill is tied to:

  • Where it appeared (job, project, repo)
  • When you used it (date ranges, calculated years)
  • How often it shows up across roles
  • How strong the evidence is (recency, frequency, confidence)

No invented skills. No output-time guessing. Extraction is recorded once with its method, confidence, source, and review state.

An optional local Ollama Nimble decision layer can resolve bounded ingestion ambiguities after local rules and NER have proposed candidates. It can classify an unknown section or prose-linked skill, or select an already-extracted person or employer span. It cannot generate a new name, company, claim, or evidence value. Every decision is probability-gated, source-hashed, and recorded for review. Nimble is disabled by default. See the local setup and decision guide. Cloud API keys entered in Profile are held by the operating system credential store, never in the JSON settings file.

This is the foundation everything else builds on - matching, projection, gap analysis, and career direction.

The two representations have different jobs:

  • Human prose is written for human readers. It should sound like its author.
  • JobML is written for machines. It can be more explicit and more detailed, but it must remain traceable to reviewed prose or external evidence.
  • AI may suggest draft prose. It cannot silently publish that prose, create accepted evidence, or turn an inference into fact.

lucidRESUME is not an automated job application service and it is not intended to disguise machine-written text as human writing. Its purpose is to let human writing remain human while giving ATS and AI systems a precise, verifiable view.

The experimental JobML 0.1 editor places authoritative human Markdown on the left, editable JobML on the right, and live evidence links between them. Selecting a link highlights both the supporting prose and machine reference. As prose changes, claims are marked valid, changed, missing, or ambiguous; inferred claims never become evidence without explicit acceptance. Markdown may be shorter for a particular role while JobML retains higher-resolution external evidence. Its default Document tab is a debounced live DOCX projection through the selected output template, rendered by Morph beside those evidence links. It does not re-extract or reinterpret the ledger. See the JobML specification, cJobML publication specification, implementation profile, and GitHub repository extension.

DOCX PreviewMy Data Dashboard

Why lucidRESUME?

Every major job site wants your email, your browsing history, and permission to sell your profile. AI resume tools send your CV to some SaaS vendor's cloud. Paid tools charge monthly for table-stakes features.

lucidRESUME does things differently:

  • Evidence-first AI - full-strength OpenAI is the primary assisted path; grug 9B Q4_K_M through LLamaSharp remains an experimental offline option. Neither path runs during deterministic projection.
  • No account required - data stored in a local SQLite database. You own it.
  • Evidence-led projection - Project only renders claims already present in the ledger.
  • Career direction (based on your actual skill graph) - not just "match this job" but "what to do next to reach your target cluster".
  • Free forever - Unlicense. Public domain.

What It Does

Resume Import

Resume import with DOCX preview

  • Drag and drop any file onto the app to import — resumes, LinkedIn exports, anything
  • Import PDF or DOCX resumes
  • DOCX preview powered by Morph — cross-platform document-to-image rendering in pure C#, no LibreOffice needed
  • LinkedIn data export — drop your LinkedIn ZIP archive and it auto-detects and imports your full profile: positions, skills (with endorsement counts), education, projects, contact info
  • GitHub evidence - imports Linguist language totals, topics, README-derived candidates, project dates, and repository provenance. A bounded deep audit records original/fork status, repository age, activity span, tests, CI, release automation, package manifests, documentation, and browser-extension structure. Archived and small repositories remain visible as historical or experimental observations. Forks and repositories below the evidence threshold do not nominate personal skills by default. Observed technologies remain separate from reviewed personal claims.
  • NuGet package families - audits a public publisher profile and official V3 metadata, then groups package IDs by source product. Package count, public downloads, tags, and source repositories become searchable ledger evidence, not automatic résumé prose or claims of proficiency.
  • All imports merge into a single unified candidate document using embedding cosine similarity — no duplicates, full source tracking
  • Handles two-column, LaTeX, complex formatting
  • Template learning: learns your resume's structure on first parse, deterministic on subsequent imports
  • Multilingual: German, French, Spanish, Portuguese, Chinese, Dutch, Japanese, Korean

Skill Ledger

My Data — skills dashboard with pie chart, Gantt timeline, and skill communities

  • Provenance chain: skill -> which job -> which date range -> which bullet point
  • Calculated years: sum of non-overlapping date ranges where the skill appears
  • Evidence strength: combining years, role count, recency, confidence
  • Consistency checking: flags skills listed but never demonstrated, claimed vs calculated years
  • Presentation gap vs true gap: "you have adjacent skills" vs "you don't have this at all"

Smart Matching

Jobs page with Looking/Hiring toggle

  • Multi-vector cosine similarity between resume and JD skill ledgers
  • 3-layer matching: substring -> embedding similarity -> achievement-text keyword search
  • Per-skill match detail with similarity scores, evidence strength, calculated years

Career Direction

  • Skill graph with co-occurrence edges and Leiden community detection
  • Career planner: 4 gap types (PresentationGap, WeakEvidence, AdjacentSkill, TrueGap)
  • Effort/impact ranking: Low (rewording), Medium (side project), High (new learning)
  • Search query generator: suggests job searches from your strongest skill communities

Evidence Projection

  • Treats the complete human career transcript and its canonical ledger as source data
  • Exports that source as a portable JobML career_record, including sources and optional semantic artefacts
  • Detects role requirements, then deterministically plans sections and selects evidence
  • Semantic compression: 13 roles -> 6 relevant -> filtered to evidence-backed bullets
  • Optionally runs bounded tightening and human-voice passes over selected source prose
  • Renders Markdown and JobML together without output-time evidence re-inference
  • Links compressed statements to the exact source role or project in the complete transcript
  • Distinguishes candidate-maintained transcript provenance from external supporting artefacts
  • Preserves human-owned prose while JobML carries explicit machine detail

Embeddable web compiler

lucidRESUME.Web is an ASP.NET Core control for the narrow publish-and-compile workflow. It does not ingest LinkedIn exports, repositories, or old CVs. That happens upstream in the desktop application. The control accepts the already exported Markdown + JobML career_record, publishes an immutable revision, accepts a job description, and returns a shorter evidence-bounded projection with Markdown, Word, and PDF downloads. Each published application receives an opaque URL whose browser view shows the résumé, its selected claims, and links into the complete transcript. The same publication exposes full JobML and cJobML to machine clients. The application career ledger remains the canonical source; the published JobML document is its portable projection. OpenAI is the default interactive editor. The local LLamaSharp path batches the projection in ordered groups of three and can recover complete section objects from a truncated response without accepting an incomplete edit. The compiler keeps the reviewed summary outside model editing, orders experience in reverse chronology, and deterministically adds the detected target title, canonical evidence-backed skills, role-relevant projects, and reviewed education.

JobML web compiler rendering an evidence-linked projection

builder.Services.AddLucidResumeCompiler(builder.Configuration);

var app = builder.Build();
app.UseAntiforgery();
app.MapLucidResumeCompiler();
app.Run();

Run the included host with:

dotnet run --project samples/lucidRESUME.Web.Sample

The control is mounted at /resume by default. The current career-record projection is served at /resume/api/jobml; immutable source revisions and application-specific publication URLs carry ETags and cache headers. API keys remain server-side. See the web compiler guide.

For the adjacent Mostlylucid site checkout, run scripts/run-local-resume-integration.sh to serve the compiler at http://127.0.0.1:8080/resume/. Publish the reviewed Markdown and JobML career record locally, paste a job description, then use the resulting evidence link to inspect the full transcript, ordered source chunks, cJobML, Word, and PDF. The sample's App_Data publications are ignored by Git; keep private career records out of commits. Local Ollama setup and gateway configuration are in the web compiler guide.

Personal ATS (Pipeline)

Pipeline tracking

  • Stage pipeline: Saved -> Applied -> Screening -> Interview -> Offer -> Accepted/Rejected/Withdrawn/Ghosted
  • Timeline per application, funnel visualization, stale detection
  • Email integration (IMAP via MailKit): auto-detects confirmations, interviews, rejections, offers

Seven job board adapters searched in parallel (Adzuna, Reed, Findwork, Arbeitnow, JoinRise, Jobicy, Remotive). Near-duplicate detection via embedding similarity. Hoover role flagging.

Export

JSON Resume (standard schema), Markdown, DOCX (Word via OpenXml), and tagged PDF/UA (QuestPDF). DOCX uses real Word lists and named headings; both office formats keep identity in the document body and avoid tables, sidebars, text boxes and repeated résumé headers.

Documentation

CLI

lucidresume parse          --file cv.docx [--output result.json]
lucidresume evidence       --resume cv.docx [--output ledger.json]
lucidresume match          --resume cv.docx --job "JD text"
lucidresume compound-match --resume cv.docx --jobs-dir jds/
lucidresume explain        --resume cv.docx --job "JD text"
lucidresume tailor         --resume cv.docx --job "JD text" [--full-jobml https://example.net/career.jobml] [--output projected.md]
lucidresume drift          --resume1 old.docx --resume2 new.docx
lucidresume export         --file cv.docx --format pdf|docx|markdown|json
lucidresume validate       --resume cv.docx
lucidresume fix            --resume cv.docx [--output fixed.md]
lucidresume generate       --resume cv.docx --prompt "draft a 2 page cloud resume" [--full-jobml https://example.net/career.jobml]
lucidresume anonymize      --resume cv.docx [--output anon.json]
lucidresume rank           --dir resumes/ --job "JD text"
lucidresume search         --prompt "senior .NET developer remote"
lucidresume extract-jd     --job "JD text" [--output jd.json]
lucidresume github-import  --username scottgal --output repositories.json
lucidresume package-audit  --publisher mostlylucid --output packages.json
lucidresume batch-test     --dir resumes/
lucidresume jobml validate  --file resume.jobml.md
lucidresume jobml reconcile --file resume.jobml.md
lucidresume jobml coverage  --file resume.jobml.md
lucidresume jobml cold-parser-probe --file resume.jobml.md
lucidresume jobml career-record --resume-dir /path/to/resumes --github scottgal --nuget-publisher mostlylucid --output career.jobml.md
lucidresume jobml compact --file resume.jobml.md --full-jobml https://example.net/career.jobml --output resume.md
lucidresume jobml link-post --file resume.jobml.md --claim claim-id --url https://example.net/article --output linked.jobml.md

Role projections include compact cJobML citations in Markdown, Word, and PDF by default. Pass --cjobml false to tailor, generate, or render for a human-only copy. --full-jobml gives transcript references an exact deep link. Compact references can cite transcript sections and public evidence without copying full passages, selectors, or drift hashes out of the full JobML career record.

Career anchors

Relevance and recency should not erase a defining older role. Mark a role as Always include on the My Data page, or place an invisible directive directly below its Markdown heading:

### Program Manager II | Microsoft Corp
<!-- lucidresume:career-anchor -->

The full JobML career_record publishes this as projection: { include: always }. Compilers reserve anchor sections before ranking ordinary roles. The preference does not strengthen the role's claims or bypass evidence validation.

CLI and server configurations may anchor every role for selected companies:

{
  "Tailoring": {
    "CareerAnchorCompanies": ["Microsoft", "Dell"]
  }
}

Company anchoring is explicitly configured by the author. lucidRESUME does not maintain an inferred employer-prestige score.


Getting Started

Download & Install

  1. Go to the latest release
  2. Download the archive for your platform:
PlatformDownload
WindowslucidRESUME-...-win-x64.zip or win-arm64.zip
macOSlucidRESUME-...-osx-arm64.tar.gz (Apple Silicon) or osx-x64.tar.gz (Intel)
LinuxlucidRESUME-...-linux-x64.tar.gz or linux-arm64.tar.gz
  1. Extract the archive. On macOS, open lucidRESUME.app. On Windows or Linux, run lucidRESUME.exe or lucidRESUME respectively.

The desktop app downloads its local ONNX models (about 600 MB) on first launch. They are cached in the user data directory, outside the signed application bundle. No account or setup wizard is required.

macOS users: the bundle is ad-hoc signed but not notarized. If Gatekeeper blocks it, Control-click the extracted app and choose Open. If needed, run xattr -dr com.apple.quarantine ./lucidRESUME.app on that app only.

AI-assisted ingestion and drafts (Optional)

AI assistance is optional. It can recover structured candidates from difficult source documents or offer a clearly labelled authoring draft. Every inferred record is stored with provenance and requires review. Draft prose remains unaccepted until a person edits and approves it. Resume projection and export work without a language model.

Option 1: OpenAI (primary full-strength provider)

  1. Open Profile → AI Provider
  2. Enter your OpenAI API key and select openai
  3. Select the model and save. The key is stored in the operating system credential store.

Option 2: Local AI with LLamaSharp (experimental)

  1. Open Profile → AI Provider
  2. Select llamasharp and click Download local model
  3. Restart the app after the 5.63 GB Q4_K_M download completes

The model is loaded lazily and uses its embedded chat template. Apple Silicon uses the Metal support included in the LLamaSharp CPU backend; other platforms have a portable CPU fallback. Set LlamaSharp:ModelPath, ContextSize, or GpuLayerCount in lucidresume.json to override the defaults. Relative model paths resolve under the user data directory, outside the signed application bundle.

Option 3: Local AI with Ollama

  1. Install Ollama and run ollama pull qwen3.5:4b
  2. Select ollama under Profile → AI Provider

Option 4: Anthropic

  1. Open the Profile page in the app
  2. Enter your Anthropic API key and select anthropic

Build from Source

For developers who want to build from source:

git clone https://github.com/scottgal/lucidRESUME
cd lucidRESUME
dotnet run --project src/lucidRESUME/lucidRESUME.csproj

Requires .NET 10 SDK. The default solution is desktop-only, so dotnet build lucidRESUME.sln and dotnet test lucidRESUME.sln do not require mobile workloads. See docs/release.md for the release workflow.


How It Works (Technical)

Extraction

5-layer RRF fusion for both resume and JD extraction: structural patterns + ONNX NER (2 models) + skill taxonomy centroids (19,983 skills from 1.3M LinkedIn jobs) + optional LLM candidate extraction + entity lookup (11K companies, 7K locations). All signals run during ingestion and are fused by reciprocal rank fusion with multi-source confidence boosting. The resulting evidence records are persisted with provenance and review state.

Export is deliberately less clever. It is a projection of accepted ledger records. It does not rerun NER or an LLM, and it refuses stale evidence. This keeps the human prose and the JobML evidence graph reversible: each rendered claim points back to the exact ingested evidence and source revision that justified it.

Skill taxonomy: 19,983 preprocessed entries from the documented Kaggle/LinkedIn datasets ship with the application, together with priority data and compact leadership profiles for Lead Developer, Head of Engineering, CTO and VP Engineering. These source terms are the reproducible seeds for exact matching and locally materialised role centroids. No personal résumé, ledger or user database is part of the preload. Used by both resume and JD parsers to find skills embedded in prose.

The exact clean-install boundary, dataset provenance and release audit are documented in Product data and clean-install contract.

ONNX embeddings (all-MiniLM-L6-v2, 384-dim) power semantic matching throughout. DocLayNet YOLO model detects document structure from rendered page images — titles, section headers, tables, lists — producing a structural hash for template identification. Docling (Docker) adds ML-based PDF layout detection for complex documents; PdfPig with column detection as local fallback.

Architecture

lucidRESUME (Avalonia UI: My CV, JobML Editor, My Data, Career, Jobs, Add Job, Project, Pipeline, Profile, Help)
    ├── Ingestion        Resume parsing, DocLayNet layout detection, Morph preview, LinkedIn import
    ├── Extraction       ONNX NER (2 models) + Microsoft.Recognizers pipeline
    ├── Parsing          DOCX/PDF/TXT extraction, ATS pattern detection, template learning
    ├── JobSpec          JD parsing (5-layer RRF: Structural + NER + Taxonomy + LLM + Entity), URL scraping
    ├── JobSearch        7 job board adapters + orchestrator + deduplicator
    ├── Matching         Skill ledger, skill graph, career planner, taxonomy centroids, entity lookup
    ├── AI               LLamaSharp/Ollama/Anthropic/OpenAI ingestion and draft-authoring providers
    ├── Compiler         Complete JobML master -> deterministic role-specific projection
    ├── Web              Embeddable ASP.NET Core publish, preview, and export control
    ├── EmailTracker     IMAP scanning, email classification, application matching
    ├── Export           JSON Resume + Markdown + DOCX + PDF exporters
    ├── Collabora        Installed-editor discovery and LibreOffice fallback
    ├── Avalonia.UITesting  UI automation framework (REPL, MCP, script runner)
    └── Core             Domain models, interfaces, persistence (SQLite + sqlite-vec)

Dependency rule: everything depends inward on Core. Core depends only on Microsoft.Data.Sqlite and sqlite-vec.

Key Design Patterns

PatternWhereWhy
5-Layer RRF FusionResume + JD extractionStructural + NER + Taxonomy + LLM + Entity Lookup vote, best candidate wins
Skill TaxonomyMatching module19,983 skills from 1.3M LinkedIn jobs — cross-industry, not just tech
Entity LookupJD parser11K companies + 7K locations from LinkedIn/Adzuna validate NER candidates
Skill LedgerMatching moduleEvery skill backed by evidence with provenance
Skill Graph + CommunitiesCareer plannerLeiden community detection with UMAP visualisation
Template LearningDOCX parserFirst parse learns structure, subsequent parses are deterministic
ATS Pattern DetectionPDF parserYAML rulesets identify resume templates/ATS systems

Tests

dotnet test lucidRESUME.sln    # 479 tests across 12 projects
ProjectTestsCoverage
Core.Tests101Persistence, models, reviewed transcript overlays, multi-resume, export, linked posts
Extraction.Tests25NER, recognizers, RRF fusion pipeline
AI.Tests46Providers, embeddings, bounded decisions, deterministic projection, gated live OpenAI checks
Matching.Tests64Skill scoring, filters, voting, job-search resilience, projection quality
JobSpec.Tests16JD parsing, deterministic flattened-title extraction, salary extraction
EmailTracker.Tests25Classifier, matcher
GitHub.Tests44Language map, repository assessment, package families, LinkedIn parsing, reviewed document merge
JobML.Tests29Parsing, validation, drift, reversible links, cJobML projection
Compiler.Tests24Deterministic evidence selection, compact chronology and projection orchestration
Web.Tests5ASP.NET Core endpoint and projection control
App.Tests2Native operating-system credential storage
Avalonia.UITesting.Tests98Input, scripts, locators, screenshots, REPL

The Chrome evidence filler has a separate TypeScript suite:

cd extensions/lucidresume-chrome
npm ci && npm run check && npm test && npm run build

UX Testing

Mostlylucid.Avalonia.UITesting on NuGet NuGet downloads

The UI automation layer is published as a standalone NuGet package — Mostlylucid.Avalonia.UITesting — so any Avalonia desktop app can use it. Real pointer/touch/wheel/gesture input via Avalonia's IInputManager, region/control snipping for manuals, YAML scripts, GIF video, REPL, and an MCP server. Source lives in src/Mostlylucid.Avalonia.UITesting/.

# Run a YAML test script
dotnet run --project src/lucidRESUME/lucidRESUME.csproj -- \
  --ux-test --script ux-scripts/e2e-full-flow.yaml --output ux-screenshots

# Interactive REPL
dotnet run --project src/lucidRESUME/lucidRESUME.csproj -- --ux-repl

# MCP server (for LLM-driven UI control)
dotnet run --project src/lucidRESUME/lucidRESUME.csproj -- --ux-mcp

Roadmap

  • Optional resume authoring drafts and suggestions, always subject to human review
  • Automated job polling from skill community search queries
  • Resume extraction RRF fusion (multi-source confidence boost, same pattern as JD)
  • Career planner UI page with gap analysis visualization
  • Leiden community detection (refinement phase over Louvain greedy moves)
  • Temporal skill drift across resume variants (compare ledgers, detect added/dropped/changed skills)
  • DOCX export of projected resumes (pure C# via OpenXml, cross-platform)
  • PDF export of projected resumes (QuestPDF, professional formatting)
  • LinkedIn data export import (ZIP archive with full profile)
  • GitHub repo skills import (languages, topics, README analysis via lucidRAG)
  • DocLayNet ONNX model for document layout detection (YOLOv10m, 58MB, structural hashing)
  • RRF fusion name extraction (NER + positional + heading + email + LLM backstop — 92% accuracy)
  • Full CLI toolkit (17 commands: parse, evidence, match, explain, tailor, rank, fix, generate, etc.)
  • Batch testing and quality evaluation across 26 multilingual resumes
  • Skill taxonomy centroids (19,983 skills from 1.3M LinkedIn jobs + Kaggle role archetypes)
  • Entity lookup (11K companies, 7K locations, 144 industries from LinkedIn/Adzuna via DuckDB)
  • 5-layer JD parser (Structural + NER + Taxonomy + LLM + Entity — 0→60+ skills from plain text)

Contributing

PRs welcome. Run the tests before submitting:

dotnet test

The codebase follows a strict inward dependency rule - keep domain logic in Core and wire everything in the app shell.


License

This is free and unencumbered software released into the public domain. See LICENSE or unlicense.org for details.

No strings attached. No attribution required. Use it however you like.

Significant stargazers

iG

0 followers · starred Aug 2026

Languages

C#

96.4%

TypeScript

2.4%