A self-hosted, privacy-preserving document management system built on Paperless-ngx, extended with an AI classification, extraction, and retrieval layer.
Drop a PDF into the consume folder and aktenraum classifies it, summarises it in German, propagates the metadata onto Paperless's native fields once you approve it, and indexes the full body so you can later ask questions over your corpus in plain German.
Status: feature-complete v1 — SPA, AI find + ask, inbox review, library, upload, RAG Phase 1 all live. Distribution work (Tauri desktop app) is in progress; see docs/plans/desktop-app.md.
| Feature | UI | API |
|---|---|---|
| Auto-classification (20 German doc types, 11 AI custom fields) | — | auto-tagger service |
| Confidence-based auto-approve (≥ 90 %, any type, with "Auto-genehmigt" badge) | — | auto-tagger service |
| Per-correspondent history hint + few-shot exemplars from your propagated corpus | — | auto-tagger service |
| Inbox review queue (PDF preview + editable AI fields, keyboard shortcuts) | /inbox | /api/inbox/* |
| Library / archive (filters, tag facet, URL-state, two-pane detail) | /library | /api/library/* |
| Find docs (closed-enum SearchFilter, editable chips, German LLM extraction) | /find | /api/ai/find |
Ask AI (German prose answer with [Quelle: <id>] citations, SSE-streamed) | /ask | /api/ai/answer/stream |
| RAG retrieval (Qdrant + bge-m3 + bge-reranker-v2-m3 over OCR'd document bodies) | feeds /ask | — |
| Upload (drag-and-drop, per-file progress, isolated failures) | /upload | /api/documents/upload |
| Reprocess (clear lifecycle tags + ping auto-tagger webhook) | preview modal | /api/documents/{id}/reprocess |
| Delete (two-step confirm, invalidates all caches) | preview modal + library detail | DELETE /api/documents/{id} |
| Processing visibility (Nav badge, per-row pill, upload-page polling) | everywhere | /api/documents/in-flight, /{id}/status, /task/{uuid} |
RAG eval harness (recall@K + MRR over evals/golden-questions.yaml) | — | python -m aktenraum-api eval.runner |
| Daily restic backup (data + media + Postgres dump, 7/4/12 retention) | — | backup container |
LLM backends: Ollama (local, default — gemma4 and friends) or Anthropic (claude-sonnet-4-6).
Ten services, one Docker Compose file:
paperless DMS core, OCR, consumer, admin UI (127.0.0.1:8000)
postgres Hosts paperless + aktenraum databases
redis Paperless task queue
gotenberg, tika PDF / document parsing for Paperless
qdrant RAG vector store (chunks + payload)
auto-tagger AI extraction worker + RAG indexer (webhook + poller)
aktenraum-api FastAPI HTTP API: auth, AI features, RAG retrieval, document proxy
nginx Edge: serves SPA static + reverse-proxies /api/* (127.0.0.1:8080)
backup Daily restic backup via crond
Detailed walkthroughs:
docs/architecture.md — services, data flow, lifecycle, RAG pipelinedocs/architecture-diagram.md — the same stack as diagrams (Mermaid, D2, ASCII, C4) with a shared legenddocs/development.md — start/build/test/debug + common tasksdocs/document-types.md — the 26 German doc types + disambiguation + per-type fieldsdocs/configuration.md — every env var, organised by filedocs/api-reference.md — endpoint catalog with auth + shapesCLAUDE.md — canonical Claude working guide (dense reference)apps/web/ React 19 + Vite + TanStack Router/Query + Tailwind v4 SPA
packages/aktenraum-core/ Shared Python lib (models, LLM backends, paperless client, RAG)
services/
auto-tagger/ Extraction worker + propagator + webhook + indexer
aktenraum-api/ FastAPI HTTP API, Alembic migrations, eval harness
docker/ docker-compose.yml + per-service env templates + nginx config
scripts/ bootstrap, backup, RAG backfill, migrations
evals/ RAG golden questions for the eval harness
docs/
adr/ Architecture Decision Records (001 tooling, 002 desktop-app)
plans/ Multi-phase roadmaps (custom-frontend, desktop-app, rag-phase-1)
runbooks/ Operational guides (first-time setup, restore, key rotation)
sessions/ Daily session summaries (what shipped + next steps)
openspec/ OpenSpec change proposals
See the First-time setup runbook for the full step-by-step.
Quick version (using the task runner — brew install go-task):
git clone <this-repo>
cd aktenraum
task setup # host dirs + secrets + stack up + next-step hints
Or without task:
bash scripts/setup.sh # create ~/aktenraum/ host dirs
bash scripts/bootstrap-secrets.sh # generate runtime secrets in docker/*.env
cd docker && docker compose up -d
task --list enumerates every shortcut: task start, task web:dev,
task build:be, task test, task logs SVC=auto-tagger, etc.
After the first boot, mint a Paperless API token and run bash scripts/bootstrap-paperless.sh to create the AI custom fields and lifecycle tags. The SPA is at http://localhost:8080 (override the port via AKTENRAUM_WEB_PORT in docker/.env).
For an existing corpus, run bash scripts/backfill-rag-index.sh to index everything into Qdrant so /ask can answer body-text questions.
Backups run daily at 02:00 inside the backup container (cron-based, not systemd). Retention: 7 daily, 4 weekly, 12 monthly. Restic repo at ~/aktenraum/backup/restic-repo/. See the restore runbook for recovery; manual snapshot:
MSYS_NO_PATHCONV=1 docker compose exec backup //usr/local/bin/entrypoint.sh
pnpm install # install Python deps for both workspace members
pnpm -r test # 419 tests, ~50s
pnpm -r lint
pnpm install
pnpm --filter @aktenraum/web lint
pnpm --filter @aktenraum/web build
GitHub Actions runs the Python and web jobs on every push and PR (.github/workflows/ci.yml).
Multi-phase initiatives:
docs/plans/custom-frontend.md — SPA rollout (largely complete)docs/plans/rag-phase-1.md — local RAG architecture + eval harnessdocs/plans/desktop-app.md — phased path to a shippable Tauri app127.0.0.1-bound by design)restic check) on a scheduleSee LICENSE if present; otherwise treat as all-rights-reserved until the project ships publicly.
137 commits
56 commits
TypeScript
52.1%
HTML
41.8%
Shell
4.6%
A self-hosted, privacy-preserving document management system built on Paperless-ngx, extended with an AI classification, extraction, and retrieval layer.
Drop a PDF into the consume folder and aktenraum classifies it, summarises it in German, propagates the metadata onto Paperless's native fields once you approve it, and indexes the full body so you can later ask questions over your corpus in plain German.
Status: feature-complete v1 — SPA, AI find + ask, inbox review, library, upload, RAG Phase 1 all live. Distribution work (Tauri desktop app) is in progress; see docs/plans/desktop-app.md.
| Feature | UI | API |
|---|---|---|
| Auto-classification (20 German doc types, 11 AI custom fields) | — | auto-tagger service |
| Confidence-based auto-approve (≥ 90 %, any type, with "Auto-genehmigt" badge) | — | auto-tagger service |
| Per-correspondent history hint + few-shot exemplars from your propagated corpus | — | auto-tagger service |
| Inbox review queue (PDF preview + editable AI fields, keyboard shortcuts) | /inbox | /api/inbox/* |
| Library / archive (filters, tag facet, URL-state, two-pane detail) | /library | /api/library/* |
| Find docs (closed-enum SearchFilter, editable chips, German LLM extraction) | /find | /api/ai/find |
Ask AI (German prose answer with [Quelle: <id>] citations, SSE-streamed) | /ask | /api/ai/answer/stream |
| RAG retrieval (Qdrant + bge-m3 + bge-reranker-v2-m3 over OCR'd document bodies) | feeds /ask | — |
| Upload (drag-and-drop, per-file progress, isolated failures) | /upload | /api/documents/upload |
| Reprocess (clear lifecycle tags + ping auto-tagger webhook) | preview modal | /api/documents/{id}/reprocess |
| Delete (two-step confirm, invalidates all caches) | preview modal + library detail | DELETE /api/documents/{id} |
| Processing visibility (Nav badge, per-row pill, upload-page polling) | everywhere | /api/documents/in-flight, /{id}/status, /task/{uuid} |
RAG eval harness (recall@K + MRR over evals/golden-questions.yaml) | — | python -m aktenraum-api eval.runner |
| Daily restic backup (data + media + Postgres dump, 7/4/12 retention) | — | backup container |
LLM backends: Ollama (local, default — gemma4 and friends) or Anthropic (claude-sonnet-4-6).
Ten services, one Docker Compose file:
paperless DMS core, OCR, consumer, admin UI (127.0.0.1:8000)
postgres Hosts paperless + aktenraum databases
redis Paperless task queue
gotenberg, tika PDF / document parsing for Paperless
qdrant RAG vector store (chunks + payload)
auto-tagger AI extraction worker + RAG indexer (webhook + poller)
aktenraum-api FastAPI HTTP API: auth, AI features, RAG retrieval, document proxy
nginx Edge: serves SPA static + reverse-proxies /api/* (127.0.0.1:8080)
backup Daily restic backup via crond
Detailed walkthroughs:
docs/architecture.md — services, data flow, lifecycle, RAG pipelinedocs/architecture-diagram.md — the same stack as diagrams (Mermaid, D2, ASCII, C4) with a shared legenddocs/development.md — start/build/test/debug + common tasksdocs/document-types.md — the 26 German doc types + disambiguation + per-type fieldsdocs/configuration.md — every env var, organised by filedocs/api-reference.md — endpoint catalog with auth + shapesCLAUDE.md — canonical Claude working guide (dense reference)apps/web/ React 19 + Vite + TanStack Router/Query + Tailwind v4 SPA
packages/aktenraum-core/ Shared Python lib (models, LLM backends, paperless client, RAG)
services/
auto-tagger/ Extraction worker + propagator + webhook + indexer
aktenraum-api/ FastAPI HTTP API, Alembic migrations, eval harness
docker/ docker-compose.yml + per-service env templates + nginx config
scripts/ bootstrap, backup, RAG backfill, migrations
evals/ RAG golden questions for the eval harness
docs/
adr/ Architecture Decision Records (001 tooling, 002 desktop-app)
plans/ Multi-phase roadmaps (custom-frontend, desktop-app, rag-phase-1)
runbooks/ Operational guides (first-time setup, restore, key rotation)
sessions/ Daily session summaries (what shipped + next steps)
openspec/ OpenSpec change proposals
See the First-time setup runbook for the full step-by-step.
Quick version (using the task runner — brew install go-task):
git clone <this-repo>
cd aktenraum
task setup # host dirs + secrets + stack up + next-step hints
Or without task:
bash scripts/setup.sh # create ~/aktenraum/ host dirs
bash scripts/bootstrap-secrets.sh # generate runtime secrets in docker/*.env
cd docker && docker compose up -d
task --list enumerates every shortcut: task start, task web:dev,
task build:be, task test, task logs SVC=auto-tagger, etc.
After the first boot, mint a Paperless API token and run bash scripts/bootstrap-paperless.sh to create the AI custom fields and lifecycle tags. The SPA is at http://localhost:8080 (override the port via AKTENRAUM_WEB_PORT in docker/.env).
For an existing corpus, run bash scripts/backfill-rag-index.sh to index everything into Qdrant so /ask can answer body-text questions.
Backups run daily at 02:00 inside the backup container (cron-based, not systemd). Retention: 7 daily, 4 weekly, 12 monthly. Restic repo at ~/aktenraum/backup/restic-repo/. See the restore runbook for recovery; manual snapshot:
MSYS_NO_PATHCONV=1 docker compose exec backup //usr/local/bin/entrypoint.sh
pnpm install # install Python deps for both workspace members
pnpm -r test # 419 tests, ~50s
pnpm -r lint
pnpm install
pnpm --filter @aktenraum/web lint
pnpm --filter @aktenraum/web build
GitHub Actions runs the Python and web jobs on every push and PR (.github/workflows/ci.yml).
Multi-phase initiatives:
docs/plans/custom-frontend.md — SPA rollout (largely complete)docs/plans/rag-phase-1.md — local RAG architecture + eval harnessdocs/plans/desktop-app.md — phased path to a shippable Tauri app127.0.0.1-bound by design)restic check) on a scheduleSee LICENSE if present; otherwise treat as all-rights-reserved until the project ships publicly.
137 commits
56 commits
TypeScript
52.1%
HTML
41.8%
Shell
4.6%