Applire
Health Uyari
- License — License: AGPL-3.0
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Basarisiz
- rm -rf — Recursive force deletion command in .github/workflows/test.yml
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Open-source AI-powered CV tailoring platform for the DACH job market

Applire
The open-source, agent-ready job application tool for Europe — DACH-native first
Transform hours of CV tailoring into seconds. Upload your CVs, paste a job description, and let AI guide you through an intelligent interview to create perfectly matched application documents.
🌐 applire.de • 🚀 Quick Start • 📖 Documentation • 💬 Community • 🐛 Report Bug
🌐 English · Deutsch
📸 See it in action
From a CV and a job ad to a complete application package — in minutes.
1. Upload your CVs & paste the job ad

Drop in one or more CVs and add the job posting as text or URL. Applire merges them into a Master Profile, scores your fit for the role, and groups what's missing into a handful of themes.
2. A short, targeted AI interview closes the gaps

A job-specific interview fills the gaps and sharpens your story — with editable answer starters, progress tracking, and a live role-requirements checklist on the side.
3. Pick a template — get a tailored CV & matching cover letter

Generate a DACH-ready Lebenslauf in seven templates (Classic German, Modern Swiss, Executive, Tech, Academic, and more) and colour variants — plus, on request, a matching cover letter (Anschreiben) in the same design, with recipient and subject auto-extracted from the job ad.
Screenshots use synthetic demo data (example profile "Milan Novak"). Applire ships in German and English — see the German README for German-UI screenshots. Output documents follow the job ad's language, so an English source CV becomes a German Lebenslauf for a German posting.
💡 What is Applire?
Applire is the open-source, agent-ready job application tool for Europe. It turns your entire career history into truthful, perfectly tailored application documents — DACH conventions built in, further countries planned as community-contributable packs.
Built for all job seekers — from career changers consolidating years of CV versions to international professionals adapting to German application conventions. Runs on your own hardware; your AI agent can drive it — and if you don't have one, the built-in assistant has you covered.
Unlike generic CV builders, Applire:
- 🧠 Learns from you: Builds a persistent Master Profile that gets smarter with every CV you upload — every claim traceable to where it came from
- 💬 Interviews you intelligently: Asks targeted questions to fill gaps between your experience and job requirements
- ✨ Tailors with precision: Generates culturally appropriate CVs optimized for DACH recruiters and ATS systems
- ✅ Keeps you truthful: Every job-ad keyword is classified as backed, claimable, or an honest gap — the system never claims what your profile can't back. Every generated document also ships a per-claim truthfulness report grading each statement against your profile
- 🤖 Agent-ready: Your AI assistant can run the whole loop via the Model Context Protocol (MCP)
- 🔒 Privacy by design: GDPR-compliant, self-hosted, full data sovereignty
In 3 simple steps:
- 📄 Upload 2-4 versions of your CV
- 🔗 Paste the job description
- 💬 Answer a few intelligent questions → ✨ Get a perfectly tailored CV
👥 Who is Applire for?
Applire is built around two everyday problems job seekers actually have — plus a third, agent-ready way to solve them.
📚 "I have five versions of my CV and I'm afraid of copy-paste mistakes"
Most professionals keep several CVs — some in English, some in their native language — and every new application means copy-pasting fragments between them, rebuilding the layout, and hoping nothing important slipped through. Applire stores every fact about your career in one place, retrieves exactly the parts that fit a specific job, and interviews you to close the remaining gaps as well as possible — so each CV is complete, consistent, and tailored without the manual shuffle.
🌍 "I want to apply in the DACH region, but my CV is from somewhere else"
You have your existing CV — say, an Indian one — but how do you turn it into something a German, Austrian, or Swiss recruiter expects? Applire converts your profile into a CV fine-tuned for DACH conventions (Lebenslauf structure, expected sections, cultural signals), so you compete on equal footing.
🤖 "Let my AI agent handle it"
Applire is agent-ready. Connect your AI agent — Claude, ChatGPT, or any MCP-capable assistant — and have it run the whole loop for you interactively over the Model Context Protocol: import your CVs, analyse the job ad, fill gaps, and generate the finished CV. No UI required. And if your agent writes better than our built-in generator, good — Applire's job is to enable it: your agent stays the strategist, Applire provides the career vault, the gap evidence, the DACH norms, and the rendering.
✨ Key Features
🧠 Intelligent Master Profile
- Multi-CV Consolidation: Upload multiple CVs and automatically merge them into a rich, conflict-aware Master Profile
- Additive Enrichment: Every CV upload, interview session, and edit enriches your profile — it never overwrites, only accumulates
- Source Tracking: Full audit trail of where every piece of information came from
- Conflict Resolution: Smart detection of factual contradictions (dates, degrees) with user-controlled resolution
🎯 Job-First Analysis & Gap Detection
- Deep JD Analysis: Extracts requirements, skills, cultural signals, and industry context from job descriptions
- Transparent Gap Scoring: 0-100% match score with detailed explanations of what's missing
- Categorized Gaps:
- Category A (Hard blockers): Must-have requirements you don't meet
- Category B (Confirmation needed): You likely have this, but it's not stated clearly
- Category C (Exploratory): Soft requirements worth discussing
💬 Conversational Interview Orchestrator
- Three Modes:
- Targeted (for experienced users): Focuses on filling specific gaps identified in your profile
- Guided (for new users): Systematically builds your profile section by section
- Profile enrichment (no job ad needed): Improves your Master Profile on its own, outside any application
- Stateful Backend: Pause and resume anytime — your progress is saved server-side
- Smart Completion: Automatically detects when you're done or when all gaps are resolved
- Profile Updates: Every answer enriches your Master Profile in real-time
📄 CV Generation & Fine-Tuning
- ATS-Optimized PDFs: Generated via Playwright/Chromium with CSS-based themes
- Live Browser Preview: See exactly what your CV will look like before downloading
- Section-Level Editing: Fine-tune individual sections (introduction, positions, skills) with live re-rendering
- Dual Save Path: Save edits to your Master Profile (permanent) or just to this CV (one-time)
- AI-Assisted Editing: Optional "Let Kaile help" for targeted gap completion within the editor
- Cover Letter Generation: AI-powered cover letter creation based on JD and Master Profile
- Cultural Adaptation: Automatic detection and formatting for German, Austrian, and Swiss CV conventions
🗺️ DACH Cultural Intelligence
- Market-Specific Formatting: Lebenslauf vs. international CV formats
- Cultural Signal Detection: Identifies when a CV needs adaptation (e.g., Indian-format CV → German Lebenslauf conventions)
- Multilingual Support: German and English UI (English by default, switchable in Settings). Interview questions follow your UI language, while the generated CV and cover letter follow the language the job ad is written in — detected from the ad itself, so an English source CV becomes a German Lebenslauf for a German posting. French and Spanish planned.
🔒 Privacy & GDPR Compliance
- Privacy by Design (GDPR Art. 25): Data minimisation throughout — the LLM provider you choose is the only third party your data reaches, and Applire sends it the least it can
- Automated Retention: A daily worker enforces TTLs, all configurable via environment variables:
- Uploaded files: 7 days (
UPLOAD_TTL_DAYS) - Interview sessions: 30 days (
INTERVIEW_SESSION_TTL_DAYS) - Generated CVs and cover letters: 90 days (
GENERATED_DOCUMENTS_TTL_DAYS) - Cancelled applications: 7 days (
CANCELLED_APPLICATION_TTL_DAYS) - Master Profile after inactivity: 730 days (
PROFILE_INACTIVITY_TTL_DAYS)
- Uploaded files: 7 days (
- Right to Erasure (GDPR Art. 17): One-click full data deletion
- Self-Hosted: Your data never leaves your infrastructure
- Encryption at rest is yours to provide. Applire adds no plaintext store of its own beyond PostgreSQL, and it does not encrypt the database for you — run it on an encrypted volume or a full-disk-encrypted host if your context requires it
🤖 Built for the AI Agent Era
Applire is the first CV tool built for AI agents as first-class users — under a simple doctrine: bring your own intelligence. Your agent is the strategist and, if it's strong, the writer; Applire supplies what an agent structurally cannot give itself:
- State that can't silently drift — the Master Profile is a reconciled vault where every change is recorded with its source, not a lossy notes file
- Checks it can't fake — deterministic keyword-coverage and ATS checks, plus
audit_document: a per-claim document-vs-profile truthfulness audit (grounded / inflated / misattributed / unbacked / unverifiable / not applicable, with profile evidence) that also accepts documents your agent wrote itself. Limit stated openly: it verifies document ↔ profile consistency; it cannot prove the profile itself - A renderer it doesn't have to fight —
render_document: your agent's structured content (public versioned schemas, served as MCP resources) through Applire's templates and DACH norms checks — PDF plus ATS and truthfulness reports out, and Applire never rewrites your content - Rules it only half-remembers — DACH application norms enforced as tested, reviewable data, not vague model recall
- A campaign, not one document — applications, versions, staleness, and follow-ups tracked across the whole search
- Compounding memory — facts surfaced in interviews land in the profile with receipts and benefit every future application. If your agent runs the interview itself,
submit_claimsrecords the elicited facts with agent-interview provenance — your agent asks, Applire notarises: only what the candidate actually said can land, ambiguities go to the profile Health hub instead of being silently applied
The weaker your agent's model, the more of Applire's built-in pipeline you can lean on — the generation tools remain available end-to-end.
Model Context Protocol (MCP)
- Seamless Integration: First-class support for Claude Desktop, ChatGPT, Cursor, and custom AI agents
- Agent-supplied documents: Agents can ingest CVs (base64-encoded PDF, with a plain-text fallback) and job descriptions (raw text or a URL scraped server-side) directly over stdio — no UI required
- Stateful Sessions: Agents can pause, resume, and recover from interruptions via a stable
flow_id - Flow Orchestrator: Guides agents through the correct sequence (JD analysis → CV import → gap analysis → interview → generation)
- Data-minimal by default: Write and ingest tools return summaries and receipts, not the profile —
import_cvreports what it extracted rather than echoing the vault back. The full profile is available when an agent actually needs it, deliberately and by name:get_profile()and theprofile://currentresource - Async Generation: Non-blocking CV generation with polling-based status checks
REST API
- Full HTTP API: Programmatic access for remote integrations
- OpenAPI Documentation: Interactive Swagger UI at
/docs
Agent Workflow Example
# Start MCP server (stdio transport)
python -m applire.mcp
# A typical agent session:
1. start_flow() → flow_id (stable recovery handle)
2. import_cv(file_base64="<base64 PDF>") → profile summary
3. analyze_jd(url="https://.../job-posting") → job_id
4. analyze_gaps(job_id) → gap_report
5. run_interview(job_id) → session_id + first question
6. send_message(session_id, "I have 5 yrs…") → next question / {complete: true}
7. generate_cv(job_id) → cv_id (async)
8. get_cv_status(cv_id) → {status: "ready", pdf_url: "…"}
9. create_application(job_id) → application logged to pipeline
🏗️ Architecture & Tech Stack
Backend
- Python 3.12+: Modern async Python with type hints
- FastAPI: High-performance async web framework
- PostgreSQL 16: JSONB for flexible Master Profile schema
- Pydantic: Type-safe data validation and serialization
- SQLAlchemy 2.0: Async ORM with full type support
- Alembic: Database migrations
Frontend
- Next.js 15: React framework with App Router
- TypeScript: Type-safe JavaScript
- ShadCN/UI: Accessible component library
- Tailwind CSS v4: Utility-first styling
AI/ML
- Bring your own key: You choose the LLM provider and supply the API key — your data goes only where you point it
- LLM Provider Abstraction: Pluggable backends — Mistral (EU-hosted), Requesty (EU-hosted gateway), OpenRouter, Anthropic (Claude, BYO-API-key), OpenAI (or any OpenAI-compatible endpoint), and Ollama (fully offline, self-hosted)
- Custom State Machine: Async interview orchestrator (no LangGraph dependency)
- Playwright: Headless Chromium for PDF generation
Infrastructure
- Docker & Docker Compose: Containerized deployment
- PostgreSQL 16: Primary database with JSONB support
- Retention Worker: Daily cron for GDPR TTL enforcement
- GitHub Actions: CI/CD pipeline with pytest and Playwright E2E tests
Agent Integration
- Model Context Protocol (MCP): stdio transport for local AI agents
- REST API: Full HTTP API for remote integrations
- Flow Orchestrator: State machine for multi-step agent workflows
- Session Recovery: Agents can resume interrupted sessions via
flow_id
🚀 Installation
Prerequisites
- Docker & Docker Compose
- An LLM provider of your choice (bring your own key): Mistral, Requesty, OpenRouter, Anthropic, OpenAI (or any OpenAI-compatible endpoint), or Ollama (local/free, no key needed)
Self-hosting (no clone required)
Which version does this install? These commands always fetch the newest published
release — the same one Docker's:latestresolves to, so the compose file, the env
template and the images are one matching set, with no version number for you to look
up. This page describes the development version; for documentation that matches what
you just installed, open the
latest release.
# 1. Download the two files you need, straight from the newest release
curl -LO https://github.com/Applire/Applire/releases/latest/download/docker-compose.yml
curl -L -o .env.example https://github.com/Applire/Applire/releases/latest/download/env.example
# 2. Configure your environment
cp .env.example .env
# Edit .env: set LLM_PROVIDER and the matching API key (see Configuration below)
# 3. Fetch the images, then start all services.
# The explicit `pull` matters: `up -d` on its own reuses an older `:latest`
# that is already cached locally. Database migrations run automatically on
# backend startup — there is no separate migration step.
docker compose pull && docker compose up -d
Every service — including the reverse proxy, whose config is baked into the applire-nginx image — is a pre-built image, so docker compose pull fetches a complete, working stack with no config files to place on the host.
Access the application at http://localhost — the bundled nginx reverse proxy serves the frontend and routes /api/* to the backend. Port 80 is the only one you need to publish; the backend and frontend containers stay internal. For the full entry-point and port topology, see docs/ARCHITECTURE.md.
Custom domain or TLS? The image ships a sensible default proxy config. To override it, bind-mount your own file over the baked one — add to the
nginxservice indocker-compose.yml:volumes: - ./my-nginx.conf:/etc/nginx/conf.d/default.conf:ro
To update to the latest release:
docker compose pull && docker compose up -d
Updating from a release older than
v0.37.0-beta? Step throughv0.37.2-betafirst. Profiles imported before the reconciliation engine
(E035) can hold flat duplicate employers and orphaned projects, and the
one-timescripts/migrate_flat_duplicates.pypass that folds them into the
typed model shipped only inv0.37.0-beta…v0.37.2-beta. It is data
hygiene, not schema — Alembic migrations still run automatically on startup,
so a direct jump upgrades cleanly, it just leaves those duplicates in place.
Self-hosting from source
Prefer to build what you run (or can't reach GHCR)? Clone the repo and build the same
three images locally, then start the same production topology:
git clone https://github.com/Applire/Applire.git && cd Applire
cp .env.example .env # set LLM_PROVIDER and the matching API key
docker build -t ghcr.io/applire/applire-backend:latest ./backend
docker build --target runner -t ghcr.io/applire/applire-frontend:latest ./frontend
docker build -t ghcr.io/applire/applire-nginx:latest ./nginx
docker compose -f docker-compose.yml up -d
Note the explicit
-f docker-compose.yml. Inside a clone, a plaindocker compose up -dalso appliesdocker-compose.override.yml— the
development stack (hot-reload servers, source bind mounts, extra published
ports including the database). Great for hacking on Applire, not for serving
real users.
Contributing? See CONTRIBUTING.md for the build-from-source developer setup.
⚙️ Configuration
Environment Variables
Applire is bring-your-own-key: pick any supported provider and supply its key — your data goes only to the provider you choose. Copy .env.example to .env and configure:
# Database
DATABASE_URL=postgresql+asyncpg://applire:applire@postgres:5432/applire
# LLM Provider — choose one: mistral | requesty | openrouter | anthropic | openai | ollama
LLM_PROVIDER=mistral
# Mistral AI — EU-hosted, strong German proficiency
MISTRAL_API_KEY=your-mistral-api-key-here
MISTRAL_MODEL=mistral-medium-latest
# Requesty — EU-hosted gateway (Frankfurt); also an EU-resident path to Claude/GPT/Gemini
REQUESTY_API_KEY=your-requesty-api-key-here
REQUESTY_MODEL=mistralai/mistral-large-latest # EU-region model for full residency
# OpenRouter — multi-model gateway: one key for Mistral, Claude, and more (not EU-hosted)
# Get a key at https://openrouter.ai/keys
OPENROUTER_API_KEY=your-openrouter-api-key-here
OPENROUTER_MODEL=mistralai/mistral-medium-3
# Anthropic (Claude) — native API, BYO-API-key only (a Claude subscription cannot be used)
# Model names move fast: take a current id from Anthropic's model list rather than
# copying one from a README. See docs/llm-models.md for how to choose.
ANTHROPIC_API_KEY=your-anthropic-api-key-here
#ANTHROPIC_MODEL=<current-claude-model-id>
# OpenAI or any OpenAI-compatible server (e.g. LM Studio)
OPENAI_API_KEY=your-openai-api-key-here
#OPENAI_MODEL=gpt-4o
#OPENAI_BASE_URL=http://host.docker.internal:1234/v1
# Ollama — fully offline (docker compose --profile ollama up)
OLLAMA_BASE_URL=http://ollama:11434
OLLAMA_MODEL=llama3.2
# LLM timeout in seconds (raise for reasoning models)
LLM_TIMEOUT=180
# Auth (none for Community Edition single-user mode)
AUTH_PROVIDER=none
# CORS — comma-separated list of allowed origins
# Default "*" (allow all) is fine for single-user self-hosting with AUTH_PROVIDER=none
#CORS_ORIGINS=*
# nginx proxy timeout — must be greater than LLM_TIMEOUT
#NGINX_PROXY_TIMEOUT=300
# Frontend API URL
# docker compose: leave empty — nginx at :80 routes /api/* to the backend
# standalone dev: set to http://localhost:8001
#NEXT_PUBLIC_API_URL=http://localhost:8001
LLM Provider Options
Applire is bring-your-own-key — no provider is privileged. Pick whichever fits your needs and supply the matching key via a pluggable abstraction layer:
| Provider | Configuration | Use Case |
|---|---|---|
| Mistral AI | LLM_PROVIDER=mistralMISTRAL_API_KEY=... |
EU-hosted, strong German proficiency |
| Requesty | LLM_PROVIDER=requestyREQUESTY_API_KEY=... |
EU-hosted gateway (Frankfurt, zero-retention); an EU-resident path to Claude/GPT/Gemini via EU-region deployments |
| OpenRouter | LLM_PROVIDER=openrouterOPENROUTER_API_KEY=... |
Multi-model gateway; access Mistral, Claude, and others with one key (not EU-hosted) |
| Anthropic (Claude) | LLM_PROVIDER=anthropicANTHROPIC_API_KEY=... |
Claude via a Console API key (BYO-key) — a Claude Pro/Max subscription cannot be used. US-hosted |
| OpenAI | LLM_PROVIDER=openaiOPENAI_API_KEY=... |
High quality, widely available; also supports LM Studio via OPENAI_BASE_URL |
| Ollama (local) | LLM_PROVIDER=ollamaOLLAMA_BASE_URL=http://localhost:11434 |
Fully offline, no API costs, no key required |
📖 API Documentation
REST API
In the Docker stack the REST API is reached through nginx at http://localhost/api/*; the interactive Swagger UI is available when running the backend standalone in development. See docs/ARCHITECTURE.md for the entry-point and port topology.
Core Endpoints
# Job Description Analysis
POST /api/job/analyze
{
"text": "Senior Software Engineer role...",
"url": "https://example.com/job" # Optional
}
# CV Upload & Profile Enrichment (async job — poll until done)
POST /api/profile/import-jobs
Content-Type: multipart/form-data
files: [cv1.pdf, cv2.pdf]
GET /api/profile/import-jobs/{job_id}
# Gap Analysis (session-scoped)
POST /api/session/{session_id}/analyze-gaps
# Start Interview Session
POST /api/session
{ "job_id": "uuid", "mode": "targeted" }
# Send Interview Message
POST /api/session/{session_id}/message
{ "message": "I have 5 years of experience with Python..." }
# Generate CV
POST /api/cv/generate
{ "job_id": "uuid", "template": "classic_german", "target_pages": 2 }
# template and target_pages are optional; target_pages falls back to your
# settings, then the region standard
# Check CV Generation Status
GET /api/cv/{cv_id}/status
# Returns: { "status": "pending" | "ready" | "failed" }
# Download CV
GET /api/cv/{cv_id}/pdf
Model Context Protocol (MCP)
# Start MCP server (stdio transport)
python -m applire.mcp
Set APPLIRE_BASE_URL to the externally-reachable scheme://host:port of your
reverse proxy for any deployment other than local/unproxied dev — it's whatgenerate_cv/get_cv_status/generate_cover_letter use to build html_url/pdf_url. It defaults to http://localhost:8001, which is wrong behind
nginx/Caddy; the server logs a startup warning when it's unset. See.env.example.
First call: after connecting, have your agent call
get_guide— it returns
the agent-usage guide and Applire's honesty contract (tool flow, à-la-carte
paths, grounding rules). The canonical file isbackend/applire/mcp/AGENT_GUIDE.md.
MCP Tools
Guidance
| Tool | Description |
|---|---|
get_guide() |
Returns the agent-usage guide + honesty contract — call before your first application run |
Ingestion & profile
| Tool | Description |
|---|---|
import_cv(file_base64?, filename?, text?) |
Seed or extend the Master Profile from a CV. Primary: base64-encoded PDF (≤10 MB); fallback: pre-extracted text. Returns an extraction summary (never the raw profile) |
analyze_jd(text?, url?) |
Analyze a job description. Provide exactly one of text (JD body) or url (scraped server-side); reposts of jobs already in the pipeline carry a duplicate_of hint |
get_profile() |
Return the current Master Profile |
update_profile(section, data) |
Patch one section (personal_info, professional_summary, work_experience, education, certifications, skills, languages, publications, volunteer_activities, signature_stories) |
add_role(title, company, start_date, location?, industry?, close_role_ids?) |
Add a new ongoing role (post-hire update); close_role_ids closes prior open roles |
Flow & interview
| Tool | Description |
|---|---|
start_flow(job_id?) |
Create or resume a flow session (idempotent per user+job); returns flow_id + state |
advance_flow(flow_id, step, artifact_id?) |
Advance to the next step; artifact-producing steps require artifact_id |
get_flow_state(flow_id) |
Get current flow state and available actions |
analyze_gaps(job_id) |
Detect gaps between profile and JD |
run_interview(job_id) |
Start a gap-fill interview; returns session_id + first question |
send_message(session_id, message) |
Send a message in an active interview; returns next question or {complete: true} |
resolve_gap(job_id, gap_id, answer) |
Resolve ONE gap cluster in a single call — the agent-channel form of the UI's targeted gap fill. Stateless: for agents that would rather ask their own questions than run a full interview session. gap_id comes from analyze_gaps' gap_clusters |
Built-in generation
| Tool | Description |
|---|---|
generate_cv(job_id, target_pages?) |
Initiate async CV generation; optional target_pages pins the page count for this run; returns cv_id, html_url, pdf_url |
get_cv_status(cv_id) |
Poll CV generation status (pending / generating / ready / failed) |
get_cv_ats_report(cv_id) |
Persisted ATS audit report for a generated CV — named pass/fail checks + present/missing keywords, no aggregate score |
generate_cover_letter(job_id) |
Generate a cover letter (requires an existing flow session for the job); returns cover_letter_id, html_url, pdf_url |
get_cover_letter_status(cover_letter_id) |
Poll cover-letter generation status (pending / generating / ready / failed) |
get_cover_letter_ats_report(cover_letter_id) |
Persisted ATS audit report for a generated cover letter |
Bring your own intelligence (ADR-054) — à la carte, no prior generate_* call needed
| Tool | Description |
|---|---|
submit_claims(claims, job_id?) |
Submit facts your agent elicited from the candidate as itemized claims; Applire reconciles them into the profile with agent-interview provenance (agent = interviewer, Applire = notary). Contract: schema://claims |
submit_testimony(text) |
Reconcile ONE whole free-text testimony document into the profile with receipts — the unstructured counterpart to submit_claims. Contract: schema://testimony |
audit_document(document_id?, document_text?) |
Truthfulness Oracle: per-claim truthfulness report — for a generated document by id, or raw text of a document your agent wrote itself |
render_document(document_kind, content, job_id, template?, target_pages?) |
Render your agent-authored structured content (contracts: schema://cv / schema://cover-letter) into a norms-checked, templated PDF with ATS + truthfulness reports — never rewritten |
Applications
| Tool | Description |
|---|---|
create_application(job_id, start_workflow?, company_name?, role_title?, deadline?, source_url?) |
Log an application to the pipeline; start_workflow=true atomically creates the flow session |
list_applications(status_filter?) |
List the application pipeline (tracking, applied, rejected, offer) |
get_application(application_id) |
Get details for a specific application (incl. a stale_cv re-tailor hint) |
update_application(application_id, ...) |
Update user-managed fields (status, notes, deadline, source URL), pin the submitted CV/letter, or dismiss the stale-CV hint |
MCP Resources
profile://current— Current Master Profile (JSON)job://{job_id}— Job analysiscv://{cv_id}— Generated CV metadataflow://{flow_id}— Flow session stateschema://cv— Versioned tailored-CV content contract forrender_document({schema_version, json_schema})schema://cover-letter— Versioned cover-letter content contract forrender_documentschema://claims— Versioned itemized-claims contract forsubmit_claimsschema://testimony— Versioned free-text testimony contract forsubmit_testimonyguide://usage— The agent-usage guide + honesty contract (same content asget_guide)
🧪 Testing
Backend Tests
# Run all tests
pytest
# Run with coverage (enforces ≥75% threshold)
pytest --cov=applire --cov-fail-under=75
# Generate HTML coverage report
pytest --cov=applire --cov-report=html
Frontend Tests
# Run unit tests
npm test
# Run E2E tests (Playwright)
npm run test:e2e
# Run E2E tests in UI mode
npm run test:e2e:ui
CI/CD Pipeline
GitHub Actions runs, against a mocked LLM provider throughout:
- ATS round-trip render guarantee (Playwright)
- Backend unit tests (pytest, ≥75% coverage)
- Backend integration tests (Docker stack)
- MCP stdio tests (the agent channel)
- Playwright IQ, OQ (desktop + mobile), and PQ suites — Chromium
- Frontend unit tests (Vitest), lint (ESLint + i18n parity), and a production build
- A module-system check
All tiers must pass before merge.
📁 Project Structure
Applire/
├── backend/
│ ├── applire/
│ │ ├── main.py # FastAPI application entry point
│ │ ├── models/ # SQLAlchemy ORM models
│ │ ├── schemas/ # Pydantic request/response schemas
│ │ ├── routers/ # FastAPI route handlers
│ │ ├── services/ # Business logic layer
│ │ │ ├── interview/ # Interview Orchestrator (state machine)
│ │ │ ├── flow/ # Flow Orchestrator
│ │ │ ├── profile/ # Master Profile merge logic
│ │ │ ├── cv/ # CV generation & section editing
│ │ │ └── gap/ # Gap analysis
│ │ ├── providers/ # LLM, Auth, Storage abstractions
│ │ ├── mcp/ # Model Context Protocol server
│ │ ├── retention/ # GDPR retention worker
│ │ └── templates/ # Jinja2 CV templates
│ ├── alembic/ # Database migrations
│ ├── tests/ # Pytest test suite
│ └── requirements.txt
├── frontend/
│ ├── app/ # Next.js App Router pages
│ ├── components/ # React components
│ ├── lib/ # Utilities and API clients
│ └── public/
├── docs/
│ ├── TESTING.md # Testing strategy and commands
│ └── CI_CD_GUIDE.md # CI/CD pipeline documentation
├── tests/ # Integration and E2E tests
├── docker-compose.yml
├── .env.example
└── README.md
🗺️ Roadmap
✅ Current Release (v0.40.0-beta)
- The document language is your decision, not a detection: a per-application DE/EN control governs every generated document, each document pins its own language, and switching later never repaints an existing one
- Structured profile editors for work experience, education, skills, languages, certifications and projects — the JSON text field is gone, and an edit made on stale data can be refused instead of silently overwriting
- Fact pins: mark a fact as required for one application and it keeps its place in the document's budget, with attribution in the review report
- One vault write path: every writer — interview, import, section editor, conflict resolution, role lifecycle — commits through
commit_opswith per-entry receipts; no ad-hoc profile writes remain - Terminal document review closes over the CV and cover letter as composed, with bounded re-entry and ship-and-report semantics
- Letter review treats presence as a fact it is told, not a question it asks — false demands and false-presence findings driven to near zero
- CV prose custody: the writer emits prose only; facts join deterministically, and the deterministic tail can never silently delete evidence
- Honestly bounded partials (assisted-not-independent, in-progress) are deliverable data instead of dropped claims
- Outcome critic: a persisted advisory report for every generated CV and cover letter, including dropped-citation accounting
- Truthfulness stance guard: an interview answer that denies experience can never become a CV claim — the reconciler's own denial verdicts deterministically outrank its edits
- Document-language enforcement covers project bullets — nothing prose-shaped enters a generated CV after the language pass
- Claimable keyword coverage self-heals inside the generation pipeline — the deterministic check that grades the document also gates every writer, including the output-language pass
- Truthful keyword ledger: every job-ad keyword classified present / claimable / honest gap — one consistent source for match score, ATS panel, generators, and interview
- Profile Reconciliation Engine: typed, deterministic merge of CV imports and interview answers with conflict resolution and enrichment history
- Master Profile Health hub with snapshots/undo and no-JD interviews
- ATS parseability checks on every generated document (panel + REST + MCP)
- Unified CV + cover-letter document workspace per application
- Async import/gap/letter jobs — long LLM steps survive refresh and proxies
- Cap-safe segmented CV generation (no truncated documents on verbose models)
- Multi-CV upload and parsing (PDF, DOCX, images via OCR)
- Master Profile consolidation with conflict resolution
- Job description analysis (text + URL scraping)
- Gap detection and match scoring
- Conversational interview flow (Targeted + Guided modes)
- CV generation (PDF via Playwright, multiple templates)
- CV Section Editor (Finetuner) with live preview and AI-assisted editing
- Cover letter generation
- Photo management (upload, crop, remove)
- Cultural adaptation detection (DACH-specific)
- MCP Server (stdio transport for AI agents)
- Flow Orchestrator (state machine for user journey)
- GDPR Retention Worker (automated TTL enforcement)
- Multilingual UI (de/en via next-intl)
⏳ Next Up
Applire ships in dessert-named releases, each tracked as a public milestone — follow along on the blog:
- Spaghettieis — shipped with v0.38.0-beta (milestone closed, 27 issues). Parallel applications became first-class: an application dashboard with status tracking, one-click re-tailoring across multiple jobs, refreshed job-ad analysis, and better progress feedback on long-running steps
- Tiramisu — shipped with v0.39.0-beta. Truthfulness Oracle: every generated document ships with a deterministic truthfulness report — is each claim grounded in your profile, is every number backed, did a "targets 70%" quietly become "achieved 70%"? In the UI and as the
audit_documentMCP tool, which also audits documents your agent wrote itself; likewiserender_document(your agent's own content through Applire's norms-checked renderer, never rewritten),submit_claims/submit_testimony(agent-run interviews landing in the profile with receipts) andresolve_gap. The flavour closed on evidence selection: one write path into the profile, and a review loop whose verdict covers the document as composed - Stracciatella — Felix takes the controls: choose the leading document language per application (detection becomes a default, not a law), structured Master-Profile editors replacing the raw-JSON view, and pinning must-appear facts to a document — plus hardening of the delivered documents (the v0.39 ship-gate findings and the prompt-injection defence)
- Strawberry — Multi-user capability: user roles, sign-in UI, an admin panel for user management, and operator controls
Beyond that, without dates: country packs beyond DACH as a community contribution surface. The hosted demo and Applire Cloud (SaaS) are paused while we focus on the open-source core and the agent channel — the waitlist hears first when that changes.
🔭 Future Vision
- Mock Interview Preparation: AI-powered practice sessions with role-specific questions
- Career Path Advisory: Skill gap analysis and training recommendations
- Job Search & Recommendation: Curated job suggestions based on Master Profile
- MCP Marketplace Listings: Distribution via agent marketplaces
🤝 Contributing
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'feat: add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
Development Guidelines
- Follow PEP 8 for Python code (enforced by
black) - Use TypeScript for all frontend code (strict mode, no
any) - Write tests for new features (≥75% backend coverage)
- Keep commits atomic and use Conventional Commits
- All schema changes go through Alembic migrations — never raw DDL
Code Style
# Backend: Format with Black
black .
# Frontend: Lint with ESLint
npm run lint
Contributor License Agreement
By submitting a pull request you agree to the Applire CLA. This allows us to maintain the open-core model while keeping the Community Edition fully open-source. See CONTRIBUTING.md for details.
💛 Support the project
Applire is built part-time by a solo founder and stays fully open source (AGPL-3.0, no feature held back). Every feature and every release is checked against real LLM providers before it ships — adversarial passes, blind hiring-panel reviews, agent-channel journeys — and Applire is built in public together with AI coding agents. Sponsorship pays for exactly that: the API credits, the AI coding tools, and the infrastructure behind applire.de and the release images.
If Applire saves you an evening of CV tailoring, consider sponsoring the project on GitHub. Sponsors are named in the release notes and here in the README, and every release post states what sponsorship paid for in that cycle.
💬 Community & Support
Get Help
- 🌐 applire.de — Website, blog (English and German), and beta waitlist
- 📖 Documentation — Testing, CI/CD, and architecture guides
- 🐛 GitHub Issues — Report bugs and request features
- 💬 GitHub Discussions — Ask questions and share ideas
📄 License
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) — see the LICENSE file for details.
Why AGPL?
We chose AGPL to ensure that:
- ✅ The software remains free and open source — Always accessible to everyone
- ✅ Modifications must be shared — Even when used as a service (SaaS)
- ✅ The community benefits — All improvements flow back to the project
- ✅ Your privacy is protected — Full transparency in how your data is processed
- ✅ No vendor lock-in — You control your data and infrastructure
Commercial Licensing
For organizations that cannot comply with AGPL requirements (e.g., proprietary SaaS offerings), commercial licenses are available. Contact [email protected] for details.
🙏 Acknowledgments
- Mistral AI for EU-hosted LLM infrastructure
- FastAPI and Next.js communities
- All contributors and early adopters
- DACH industry professionals who provided domain expertise
- The open-source community for inspiration and tools
📬 Contact
- Website: applire.de — blog and beta waitlist
- Email: [email protected]
- Issues: GitHub Issues
- Security: [email protected] (see SECURITY.md)
Built with ❤️ for job seekers in the DACH market
Open source. Privacy-first. Agent-ready. Truthful by design.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi