← Demos

PatraLekh

पत्र Patra (letter) + लेख Lekh (writing)

The pipeline

From job post to finished resume

PatraLekh tailors a resume to a job through a deterministic, six-stage pipeline

Every arrow below is drawn by code, not decided by a model at runtime. Click any stage to expand it.

LLM → JSONAnalyze JD

The only place unstructured human text enters the system. Output is immediately validated and schema-checked before anything downstream can use it.

Pure codeRoute

A switch on role_type picks the resume framing. Deliberately not an LLM call. Same input always yields the same route.

Optional gateFit Check

The model judges fit; code enforces the gate (<40 block, 40–69 ask, ≥70 proceed). Prevents wasted spend on a fundamentally mismatched role.

Bounded retryEvaluate → Write loop

The critic scores the draft; if it fails thresholds, the critique feeds back to the writer. The retry ceiling and pass threshold are owned by Go, so the loop always terminates.

Architectural philosophy

Not agentic, and that's the design achievement

The 2025 reflex is to reach for an agent: give a model a goal and a loop, and let it plan and execute. That's the right pattern when the path to the goal is unknown. Resume tailoring is the opposite kind of problem.

Property of the taskWhat it implies
The steps are known in advanceThe orchestrator can be hard-coded. There is nothing for a planner-agent to "discover."
Fixed order with clean data dependenciesA directed pipeline models it exactly; a re-planning loop adds cost and variance for no benefit.
Highest risk is fabricationControl must stay in code that enforces a knowledge base as ground truth. An agent free to "decide" what to include is a liability.
User wants predictable cost and latencyA bounded pipeline has a fixed number of LLM calls; an agent loop does not.
User wants to see, stop, and re-run individual stepsRequires discrete, observable stages: the native shape of a workflow, not an opaque agent turn.

“PatraLekh is not agentic, and that is a design achievement, not a limitation. An agent would introduce non-determinism into the control flow, the one place this problem cannot tolerate it. The model's creativity belongs inside a single stage (writing prose), never in the decision of what to do next.”

Execution model

Three tiers: determinism is the default

Every unit of work is assigned to the cheapest, most deterministic tier that can actually do it correctly. Work only moves up a tier when the tier below genuinely cannot do the job.

Tier 1
Go code
In-process · fully deterministic
  • Stage orchestration, start/stop/cancel, re-run
  • Routing (role_type → framing)
  • Pass/fail verdict, fit-score gate, retry ceiling
  • JSON repair, truncation detection, schema validation
  • Cost accounting, telemetry, file operations
Tier 2
External tools
Shelled out · still deterministic
  • Pandoc → .docx / .pdf (document typesetting)
  • osascript → native folder picker (macOS)
Tier 3
LLM APIs
Network · non-deterministic
  • Reading a messy JD into structured fields
  • Strategic judgement: narrative plan
  • Metric selection (grounded in knowledge base)
  • Prose writing: the actual resume
  • Critique and fit scoring
The through-line: Two things people often assume “the AI does” are deliberately notthe model's job: turning the draft into a Word/PDF file (that's Pandoc, tier 2) and guaranteeing the model's structured output is well-formed (that's Go's JSON layer, tier 1). Both are deterministic problems, handled by deterministic tiers, keeping the expensive non-deterministic tier as small as possible.
Features

What PatraLekh does

From JD to finished document

Paste a job description, get a tailored resume (and optional cover letter) in under a minute.

Role-tailored resume

The pipeline extracts the role, seniority, industry, and verbatim ATS keywords from the JD. Every element of the resume (narrative arc, roles featured, metrics chosen) is tuned to that specific posting.

Optional cover letter

Request a cover letter upfront or generate one from the finished draft in a single click. Produced as a separate document; can reference role themes the resume cannot.

Multiple output formats

Markdown is always produced. When Pandoc is available, .docx and .pdf are generated alongside it. A JD.txt and README.md are dropped into the output folder for provenance.

Flexible output location

Save to Desktop, Documents, or any path, including cloud-synced folders (OneDrive, iCloud Drive, Dropbox, Google Drive). A native OS folder picker lets you browse to any location.

Quality gates, under your control

The system produces a draft; a second model critiques it; you decide what ships.

Job-fit pre-check

An opt-in stage (off by default) scores the JD against your background before spending on generation. Below 40% it blocks the run; 40–69% it pauses and asks you; ≥70% it proceeds. Stops wasted spend on a fundamentally mismatched role.

Evaluator-optimizer loop

After the draft is written, a critic model scores it on content quality and ATS fit. If it falls below fixed thresholds, the critique feeds back to the writer, which revises, up to a bounded retry cap. The loop always terminates; Go owns the exit condition.

Stop and re-run from any stage

Stop a run before paying for later stages. Re-run from any stage to the end without restarting the whole pipeline. Optionally override the model for a single stage (e.g. re-run just the writer on a stronger model).

In-browser editor

The generated resume opens in a live Markdown editor (EasyMDE) so you can make any manual edit before finalizing. Edits persist across navigation. The system produces a draft, not an unquestioned artifact. A human is always in the loop.

Grounded in what's true

The model rephrases facts it is handed. It never invents them.

Knowledge base

All career facts come from a single user-owned Markdown file: companies, titles, dates, projects, metrics, skills. The model is a rephraser of this source, not a source itself. A second model (the evaluator) checks the result against the same facts.

Rules engine

Define absolute rules that override anything: "my IBM title is Delivery Project Executive, never Project Manager." Rules are injected into both the writer prompt (applied) and the evaluator prompt (violations flagged). Hot-reload, no restart needed.

Duplicate-run detection

Before starting, PatraLekh hashes the job description (SHA-256) and checks the last 90 days of history. If the same JD was already processed, it shows a notice and lets you either open the prior run or generate anyway. Stops accidental re-spend.

Separate metric calibration stage

Metric selection is a standalone stage (Calibrate), separated from writing so that the specific quantified achievements chosen are auditable on their own, and any projected or targeted figures are flagged so the writer hedges them appropriately.

Local. Private. One file.

Everything runs on your machine. No server to trust; no data retention to reason about.

Single static binary

The entire product is one file you double-click. No npm, no installer, no runtime to manage. Available for macOS (Apple Silicon + Intel), Windows, and Linux.

Bring-your-own API key

Supply keys for Anthropic, Google Gemini, OpenRouter, or xAI/Grok. Keys can be tested before saving, are stored with restrictive file permissions (0600), shown only as a masked fingerprint, and hot-reload on save.

Per-stage model selection

Each pipeline stage runs on an independently configurable model (provider:model string). One-click quick profiles: Fast / Balanced / Quality for Anthropic, plus Gemini and Grok presets. Cheap models for extraction; strongest models for writing and evaluation.

Self-upgrade

The app checks the public GitHub Releases API and, when a newer version exists, shows an update pill and an "Upgrade" button. One click downloads the new release, unpacks it, and replaces the running binary in place, then reconnects.

Technical robustness

Built for trust

The seam between non-deterministic model output and deterministic code is the most dangerous part of any LLM system. These are the mechanisms that harden it.

🛡️

JSON safety net

Stages that return structured data (Analyze, Fit, Evaluate) pass through a hardening layer: string-aware repair (strip fences, comments, trailing commas), truncation detection via API stop reason, schema validation, and retry-with-more-tokens. The model's output is never trusted blindly.

📊

Per-call telemetry

Every run is logged to an append-only JSONL file. For each LLM call: exact model, input/output tokens, cache-create/read tokens, computed USD cost, and wall-clock duration. A dashboard shows averages, per-stage breakdown, per-model breakdown, and period rollups.

👁️

Observable, stoppable runs

A generation runs in the background while the UI polls live per-stage state (pending / running / done / skipped / failed / stopped). Stop before paying for later stages. See the stop reason and any error inline on the stage that produced it.

🔒

No server, no accounts

Resumes and career data never leave your computer except for the direct API calls to the provider you chose with your own key. No multi-tenant blast radius; no data retention to reason about.

📄

One-click Pandoc install

The app can install a managed Pandoc binary into its own app-data folder, with no admin rights and no system-wide install. Document export works out of the box with a single click in Settings → System.

No tool-calling loop

There is no autonomous tool-use loop, and no function-calling the model discovers at runtime. The "tools" are fixed pipeline stages called in a known order by deterministic Go code. Predictable cost; no runaway loops.

Technology

Stack at a glance

Technology choices reinforce the same values as the architecture: determinism, auditability, a small trusted surface, and zero-friction distribution. Two direct third-party dependencies. No vendor SDKs. Every LLM call is a hand-rolled REST request.

LayerTechnology
Language / runtimeGo 1.22, single static binary, CGO_ENABLED=0
Web frameworkGin
LLM accessHand-rolled REST: Anthropic, Gemini, OpenRouter, xAI/Grok (no SDKs)
FrontendEmbedded HTML + Tailwind (CDN) + EasyMDE (CDN), no build step
Document exportPandoc (managed install) → .docx / .pdf
PersistenceLocal files: JSON, YAML, append-only JSONL, no database
PackagingCross-compiled 4 targets; macOS ad-hoc-signed .app; key/PII scan on release
DistributionLocal-first, bring-your-own-key, in-app self-upgrade

What was deliberately not built

Restraint is the design. Every one of these is a place where the fashionable choice was available and turned down because the task doesn't need it.

No autonomous planning agentNo tool-calling / function-calling loopNo multi-agent committeeNo RAG / vector storeNo server or accountsNo data retentionNo vendor SDKsNo build pipelineNo database

PatraLekh

Runs on your machine. Uses your own API key. Your data never leaves your computer.

Mac · Windows · Linux · Free to download

Download PatraLekh