# Project pack: Paperless-ngx @ f25fd53

Facts about **Paperless-ngx** for an AI following the [BespokeAI handover guide](https://handoff.bespokeai.software/guide/v1.md). This pack is pinned to one version and never changes after publication.

> Paperless-ngx turns paper into a searchable archive. Scan or photograph a letter, drop in a PDF or forward an email, and it reads the text, files it and suggests who it is from and what kind of document it is. Find any bill, payslip, warranty or school letter by typing a word. It runs on your own computer or server, so your private documents stay at home.

## Version and source
- Repository: https://github.com/paperless-ngx/paperless-ngx
- Pinned commit: `f25fd5365fcc32d06c24306535c7b55e93fbb259`. Use exactly this version.
- Get it: `git clone https://github.com/paperless-ngx/paperless-ngx paperless-ngx && cd paperless-ngx && git checkout f25fd5365fcc32d06c24306535c7b55e93fbb259`
- Or download a zip: https://github.com/paperless-ngx/paperless-ngx/archive/f25fd5365fcc32d06c24306535c7b55e93fbb259.zip
- Official docs: https://docs.paperless-ngx.com
- Live demo: https://demo.paperless-ngx.com (username: demo / password: demo). Shared demo; content is reset often. Don't upload real documents.
- Licence: **GPL-3.0-only**. Free to use and change. If you share your changed version with other people (give them the code or app), you must share your source code under the same licence. Using it privately for yourself or your household has no extra obligations.

## Running it
- Easiest: bash -c "$(curl --location --silent --show-error https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)" # or: copy docker/compose/docker-compose.sqlite.yml and docker-compose.env, set PAPERLESS_SECRET_KEY, # run docker compose pull && docker compose up -d, then open http://localhost:8000 and create the admin user
- Needs: Docker with Docker Compose, For development, Python 3.11+ with uv, Node.js 24+ with pnpm, and Redis
- Develop: `cd src && uv run manage.py runserver & uv run manage.py document_consumer & uv run celery --app paperless worker   # then in src-ui/: pnpm install && pnpm ng serve`
- Test: `cd src && uv run pytest   # frontend: cd src-ui && pnpm ng test`
- Check/lint: `uv run prek run --all-files   # frontend: cd src-ui && pnpm ng lint`
- Stack: python, typescript, html, scss (Django, Django REST framework, Celery, Angular, Bootstrap). Difficulty for a non-developer with an AI: **moderate**. Tags, matching rules, workflows, mail rules and custom fields cover most household needs without code. Code changes mean a Django backend (src/) and an Angular frontend (src-ui/), plus Redis and a Celery worker for processing.

## Customisation points (settings → extend → code)
- **tags-and-matching** [settings]: Auto-file documents, e.g. anything containing "British Gas" goes to Energy bills. → `Tags, Correspondents, Document Types, Storage Paths pages (docs/advanced_usage.md#matching)`
- **workflows** [settings]: When a document arrives or changes, assign tags or owners, send an email or call a webhook, or run on a schedule. → `Workflows page (docs/usage.md#workflows; code in src/documents/workflows/)`
- **mail-rules** [settings]: Import attachments from an email inbox and tag them automatically. → `Mail → accounts and rules (docs/usage.md#incoming-mail)`
- **custom-fields-and-views** [settings]: Track things like amount, due date or warranty end, and show "bills due this month" on the dashboard. → `Custom Fields page; saved views on the dashboard (docs/usage.md#custom-fields)`
- **look-and-name** [settings]: Your own colour, name and logo. → `Settings → Appearance (theme colour, dark mode); PAPERLESS_APP_TITLE and PAPERLESS_APP_LOGO`
- **consume-scripts** [extend]: Run your own script before or after each document is processed, e.g. to notify your phone. → `PAPERLESS_PRE_CONSUME_SCRIPT / PAPERLESS_POST_CONSUME_SCRIPT (docs/advanced_usage.md#consume-hooks)`
- **rest-api** [extend]: Upload from other apps, build reports or connect a phone shortcut. → `REST API with a token (docs/api.md)`
- **frontend** [code]: New screens or widgets in the Angular interface. → `src-ui/src/app/components/** (e.g. dashboard/, document-detail/, document-list/), styles in src-ui/src/theme.scss`
- **backend** [code]: New data or API behaviour in Django. Database changes need a migration. → `src/documents/models.py, views.py, serialisers.py, src/documents/migrations/`

## Must keep working
- Original documents in the media folder. Never let code delete or rewrite originals.
- Permissions. Documents owned by one person must not appear for others unless shared.
- Database changes need a Django migration in the right app's migrations/ folder.
- The REST API is used by mobile apps and scripts. Don't change existing fields.

## Staying updatable
Matching rules, workflows, mail rules, custom fields, consume scripts and the REST API cover most needs without a fork. For bigger features, upstream asks you to start a GitHub discussion first.

## Data, costs and safety
- Personal data: **yes**. Stored in: Original and archived files in the media volume; database (SQLite by default, or PostgreSQL/MariaDB) in the data volume. Files dropped in ./consume are imported; ./export holds exports. Documents are stored unencrypted. Back up with the built-in exporter (document_exporter) and copy the export folder off the machine. Test a restore before upgrading or changing code.
- Service: Redis (message broker) (required, free (included in the compose files)): Queues documents for processing.
- Service: Email account (IMAP) (optional, free): Pull in bills and letters sent by email, using mail rules.
- Service: Apache Tika and Gotenberg (optional, free (optional containers)): Read Word, Excel, LibreOffice and email files, not just PDFs and images.
- Service: AI provider (Ollama locally, or an OpenAI-compatible API) (optional, free with local Ollama, pay-per-use for cloud providers): Smarter suggestions and a chat that answers questions about your documents.
- Setting `PAPERLESS_SECRET_KEY` (**secret**: the person enters it themselves, never in chat): Random secret used to sign logins. Generate a long random value. Never paste it into an AI chat.
- Setting `PAPERLESS_URL`: The address you open Paperless at, if you reach it from outside your home network.
- Setting `PAPERLESS_TIME_ZONE`: Your time zone (e.g. Europe/London).
- Setting `PAPERLESS_OCR_LANGUAGE`: The language most of your documents are written in (e.g. eng, deu, eng+fra).
- Setting `USERMAP_UID`: Your user ID on the host, so you can write to the consume folder (with USERMAP_GID).
- Setting `PAPERLESS_APP_TITLE`: Replace the name "Paperless-ngx" in the interface.
- Setting `PAPERLESS_FILENAME_FORMAT`: How stored files are named and foldered on disk, e.g. by year and correspondent.
- Setting `PAPERLESS_AI_ENABLED`: Turn on the optional AI features (off by default). Also needs PAPERLESS_AI_LLM_BACKEND and a model.
- Documents are stored without encryption. Upstream warns never to run it on an untrusted host; a home server with backups is safest.
- Don't expose it to the internet without HTTPS and a strong password; turn on two-factor authentication.
- AI features send document text to the chosen provider. Use Ollama to keep everything at home.

---

# Customising Paperless-ngx

Paperless-ngx is a Django backend with an Angular frontend. **Most household adaptations are settings**: matching rules, workflows, mail rules and custom fields. Exhaust levels 1 and 2 before touching code.

## Level 1: Settings (no code)
- **Auto-filing:** create Tags, Correspondents, Document Types and Storage Paths, each with a *matching* rule (any word, exact phrase, regular expression or "auto" learning). See `docs/advanced_usage.md#matching`.
- **Workflows** (Workflows page): triggers are *Consumption Started*, *Document Added*, *Document Updated* and *Scheduled*. Actions include assigning tags, owners and custom fields, removal, Email, Webhook and Move to Trash. A *Scheduled* trigger on a date custom field plus an Email action gives you "bill due soon" reminders. See `docs/usage.md#workflows`.
- **Email import:** Mail → add an IMAP account and mail rules to pull attachments and tag them. See `docs/usage.md#incoming-mail`.
- **Custom fields** (Manage → Custom Fields): amount, due date, warranty end, policy number and so on. Use them in saved views on the dashboard.
- **Look:** Settings → Appearance (theme colour, dark mode, display language). Rename the app with `PAPERLESS_APP_TITLE` and set a logo with `PAPERLESS_APP_LOGO`.
- **File names on disk:** `PAPERLESS_FILENAME_FORMAT` or Storage Paths, e.g. `{{ created_year }}/{{ correspondent }}/{{ title }}`. See `docs/advanced_usage.md#file-name-handling`.
- **OCR language:** `PAPERLESS_OCR_LANGUAGE` (and `PAPERLESS_OCR_LANGUAGES` to install more).
- **AI (optional, off by default):** `PAPERLESS_AI_ENABLED=true` plus `PAPERLESS_AI_LLM_BACKEND` (`ollama` or `openai-like`) and a model. See `docs/advanced_usage.md#ai-features`.

## Level 2: Extend (no fork)
- **Consume scripts:** `PAPERLESS_PRE_CONSUME_SCRIPT` and `PAPERLESS_POST_CONSUME_SCRIPT` run your own script for every document. See `docs/advanced_usage.md#consume-hooks`.
- **Workflow webhooks:** send document events to n8n, Home Assistant, ntfy or your own script.
- **REST API** with a token (`docs/api.md`): phone shortcuts, reports, imports from other apps.
- **Barcodes:** separator sheets and ASN stickers for batch scanning (`PAPERLESS_CONSUMER_ENABLE_BARCODES`). See `docs/advanced_usage.md#barcodes`.

## Level 3: Code
Read `docs/development.md` first.

| Change | Where |
|---|---|
| New screen or dashboard widget | `src-ui/src/app/components/**` (e.g. `dashboard/`, `document-list/`, `document-detail/`) |
| Colours and styles | `src-ui/src/theme.scss`, `src-ui/src/styles.scss` |
| Frontend text | Angular i18n; run `ng extract-i18n` to update `src-ui/messages.xlf` |
| New API endpoint | `src/documents/views.py` + `src/documents/serialisers.py` |
| New data | `src/documents/models.py` + `uv run manage.py makemigrations` (files in `src/documents/migrations/`) |
| Workflow behaviour | `src/documents/workflows/`, `src/documents/signals/handlers.py` |
| Email import | `src/paperless_mail/` |
| AI features | `src/paperless_ai/` |

## Running locally
- **Just use it:**
  1. Run the install script from the README, or copy `docker/compose/docker-compose.sqlite.yml` (as `docker-compose.yml`) and `docker/compose/docker-compose.env`.
  2. Set `PAPERLESS_SECRET_KEY` to a long random value.
  3. Run `docker compose pull`, then `docker compose up -d`.
  4. Open http://localhost:8000 and create the first (superuser) account.
- **Develop:**
  1. Copy `paperless.conf.example` to `paperless.conf` and set `PAPERLESS_DEBUG=true`. Run `mkdir -p consume media`.
  2. Run `uv sync --group dev` and `uv run prek install`.
  3. Start a broker: `docker run -d -p 6379:6379 docker.io/valkey/valkey:9-alpine` (or `scripts/start_services.sh`).
  4. In `src/`, run `uv run manage.py migrate` and `uv run manage.py createsuperuser`.
  5. Run `uv run manage.py runserver`, `uv run manage.py document_consumer` and `uv run celery --app paperless worker`.
  6. In `src-ui/`, run `pnpm install` and `pnpm ng serve`, then open http://localhost:4200.
- **Check:** `pytest` in `src/`; `pnpm ng test` and `pnpm ng lint` in `src-ui/`.

## Pitfalls
- Back up with `document_exporter` before upgrades or code changes. These are your important documents.
- Files are stored unencrypted. Keep it on a home server, not an untrusted host.
- Set `USERMAP_UID`/`USERMAP_GID` if files dropped in `consume/` are not picked up.
- Changing matching rules does not refile old documents by itself. Use bulk edit or a workflow.
- Permissions are per object. Code that lists documents must respect the owner and shared permissions.

---
Machine-readable: [bespoke.yaml](https://handoff.bespokeai.software/p/paperless-ngx/f25fd53/bespoke.yaml) · Agent skill: [SKILL.md](https://handoff.bespokeai.software/p/paperless-ngx/f25fd53/SKILL.md)
