Skip to content
imkrishsubPublic

About

A privacy-first document organization tool that uses local AI to automatically categorize, tag, and rename your PDF files. All processing happens on your machine with Ollama, keeping your documents completely private.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

FileFolio

FileFolio helps privacy-conscious professionals keep large PDF collections searchable and organized using local AI. No cloud, no telemetry, all on your machine.

Support me on Ko-fi

FileFolio Preview

Status: Actively maintained, used on my own 1,000+ PDF collection. Expect breaking changes before v1.0, but I'm responsive to issues and feedback.

Why FileFolio?

  • You have hundreds of PDF bills, reports, or research papers scattered in folders.
  • You care about privacy and do not want to upload them to cloud AI services.
  • You still want smart search, auto-tagging, and reasonable file names.

FileFolio watches a folder, uses a local LLM via Ollama to analyze each PDF, and keeps everything searchable in one interface.

FileFolio vs Paperless-ngx

Paperless-ngx is the most popular self-hosted alternative. Here's how they compare:

Feature FileFolio Paperless-ngx
AI tagging and naming 🟢 Local LLM via Ollama, zero config 🔴 ML classifier available, but requires manual training; no LLM-level understanding
Setup 🟢 Single Python process + SQLite 🔴 Docker Compose: web, worker, Redis, PostgreSQL
Resource footprint 🟢 Single process + Ollama 🔴 Multi-service, heavier
Multi-user 🔴 No 🟢 Yes
Feature scope 🔴 Focused: upload, search, tag, organize 🟢 Broader: email ingestion, custom fields, workflow automation
Best for 🟢 Personal libraries, privacy-first, low setup 🟢 Power users, teams, complex workflows

Features

  • Automatic organization – drop PDFs in a watched folder and Ollama names, tags, and categorizes them automatically
  • Privacy-first – every byte stays on your machine, no cloud calls, no telemetry
  • Fast retrieval – full-text search across content and metadata with thumbnail previews
  • Disaster-proof – back up and restore your entire library as a single ZIP

Prerequisites

  • Git
  • Python 3.10+
    • Ubuntu/Debian: apt-get install git python3-venv (Python there ships without venv and pip, so step 2 of the manual setup fails without it)
  • Ollama installed locally, with a model pulled:
    ollama pull llama3.2
    Without a model, FileFolio still files and searches your documents, but tagging and naming fall back to simple keyword rules. See Custom Ollama model to use a different one.
  • Poppler (for PDF processing)
    • macOS: brew install poppler
    • Ubuntu/Debian: apt-get install poppler-utils
    • Windows: download the latest Release-*.zip from poppler releases, extract it (e.g. to C:\poppler) and add its Library\bin folder to PATH
  • Tesseract (for OCR on scanned documents)
    • macOS: brew install tesseract
    • Ubuntu/Debian: apt-get install tesseract-ocr
    • Windows: run the installer from Tesseract releases, then add C:\Program Files\Tesseract-OCR to PATH
  • Windows only: Poppler, Tesseract and Ghostscript (see OCR dependencies) are not added to PATH for you. Open Start, search for "Edit environment variables for your account", select Path, click New for each folder, then open a new terminal.

How files are stored

Uploaded PDFs are filed by category and year:

uploads/
  Invoice/
    2026/
      20260731_101500_bill.pdf
  Receipt/
    2025/
      20251102_090000_lidl.pdf

Changing a document's category in the interface moves the file to the matching folder. An existing flat uploads/ directory is reorganised automatically the next time FileFolio starts.

Thumbnails stay flat in thumbnails/ — they are generated artifacts, not files you browse.

Quick start

Docker (recommended)

  1. Clone the repository
git clone https://github.com/imkrishsub/filefolio.git
cd filefolio
  1. Start Ollama and pull the model (if not already done)
ollama serve
ollama pull llama3.2
  1. Start FileFolio
docker compose up
  1. Open your browser Navigate to: http://localhost:8000

Ollama runs on your host machine; the container connects to it automatically via host.docker.internal. On Linux, set OLLAMA_HOST=http://172.17.0.1:11434 if host.docker.internal is not available.

Manual setup

  1. Clone the repository
git clone https://github.com/imkrishsub/filefolio.git
cd filefolio
  1. Create and activate virtual environment

macOS and Linux:

python3 -m venv venv
source venv/bin/activate

Windows (PowerShell or Command Prompt):

python -m venv venv
venv\Scripts\activate

If PowerShell refuses with "running scripts is disabled on this system", run Set-ExecutionPolicy -Scope CurrentUser RemoteSigned once, or use Command Prompt.

  1. Install dependencies
pip install -r requirements.txt
  1. Start Ollama and pull the model (in a separate terminal)
ollama serve
ollama pull llama3.2
  1. Run the application
python backend/main.py
  1. Open your browser Navigate to: http://127.0.0.1:8000

Configuration

Custom port

Set a custom port using the PORT environment variable:

PORT=8080 python backend/main.py
# or with Docker:
PORT=8080 docker compose up

Custom Ollama model

FileFolio uses llama3.2 by default. Point it at any model you have pulled:

OLLAMA_MODEL=qwen2.5 python backend/main.py
# or with Docker:
OLLAMA_MODEL=qwen2.5 docker compose up

If Ollama is unreachable or the configured model is not installed, FileFolio shows a banner in the interface and falls back to rule-based tagging rather than failing the upload.

Custom Ollama URL

OLLAMA_HOST=http://192.168.1.10:11434 docker compose up

Time zone (Docker)

The container runs in UTC unless told otherwise, so upload times and the date prefix of stored filenames would be off by your offset. Set TZ to your time zone name. The easiest way on every platform is a file named .env next to docker-compose.yml, which Docker Compose reads automatically. Put this line in it, then restart with docker compose up -d:

TZ=Europe/Berlin

A manual install uses your computer's time zone and needs no setting.

Testing

pytest

Full API and functionality coverage including unit tests, integration tests, and frontend tests.

Command line (optional)

Same operations as the web UI, against a running instance. Needs only the normal venv/ — no MCP SDK.

python backend/cli.py search rent --category Invoice
python backend/cli.py get 7
python backend/cli.py upload ~/Downloads/receipt.pdf
python backend/cli.py update 7 --tags finance,rent --category Tax
python backend/cli.py download 7 ~/Desktop/rent.pdf

Add --json to search, get, upload, or update to get the raw API response for scripting. Errors go to stderr and exit non-zero. Set FILEFOLIO_URL to reach a non-default instance:

FILEFOLIO_URL=http://127.0.0.1:8080 python backend/cli.py search rent

Installing the package (pip install -e .) gives you a bare filefolio command that does the same thing from any directory.

MCP server (optional)

Lets other Claude Code sessions search, read, add, and re-tag documents in a running FileFolio instance over the Model Context Protocol — without needing to be in this repo's directory.

The MCP server needs its own virtual environment: the mcp SDK requires newer anyio/starlette versions than FileFolio's pinned FastAPI supports, so it can't share venv/ with the backend.

  1. Create the MCP virtual environment and install its dependencies
python3 -m venv venv-mcp
venv-mcp/bin/pip install -r requirements-mcp.txt  # On Windows: venv-mcp\Scripts\pip install -r requirements-mcp.txt
  1. Register it with Claude Code, with FileFolio already running (python backend/main.py). Run this from the FileFolio repo root so the paths resolve to absolute paths — claude mcp add needs them, since the server may be invoked from any directory:

    macOS/Linux (bash/zsh):

claude mcp add filefolio -s user -- "$(pwd)/venv-mcp/bin/python" "$(pwd)/backend/mcp_server.py"

Windows (PowerShell):

claude mcp add filefolio -s user -- "$PWD\venv-mcp\Scripts\python.exe" "$PWD\backend\mcp_server.py"
  1. Optional: point it at a non-default FileFolio instance

    macOS/Linux (bash/zsh):

claude mcp add filefolio -s user -e FILEFOLIO_URL=http://127.0.0.1:8080 -- "$(pwd)/venv-mcp/bin/python" "$(pwd)/backend/mcp_server.py"

Windows (PowerShell):

claude mcp add filefolio -s user -e FILEFOLIO_URL=http://127.0.0.1:8080 -- "$PWD\venv-mcp\Scripts\python.exe" "$PWD\backend\mcp_server.py"

Available tools: filefolio_search, filefolio_get_document, filefolio_download, filefolio_upload, filefolio_update, filefolio_pdf_merge, filefolio_pdf_split, filefolio_pdf_extract, filefolio_pdf_delete_pages, filefolio_pdf_rotate, filefolio_pdf_ocr.

PDF tools

FileFolio can merge, split, rotate, OCR, and trim pages from stored PDFs. The same operations are reachable from the web UI, the command line, and the MCP server.

Web UI

Select two or more documents and a Merge button (a floating action button) files them into one new document. Each document also has a Tools menu with Rotate, Split, Extract pages, Delete pages, and Make searchable. The operations that produce a new document offer a "Download only, do not file" checkbox.

Command line

filefolio pdf merge 12 15 3
filefolio pdf split 12 "1-3,4-"
filefolio pdf extract 12 "2"
filefolio pdf delete-pages 12 "1"
filefolio pdf rotate 12 --degrees 90
filefolio pdf ocr 12

Page ranges accept comma-separated single pages and spans, with an open-ended upper bound ("1-3,5,8-"). Add --download OUT.pdf (merge, extract, delete-pages) or --download-dir DIR (split) to save the result instead of filing it, and --json to print the raw API payload.

MCP

  • filefolio_pdf_merge — merge documents into one new filed document.
  • filefolio_pdf_split — split a document by page ranges; files each part.
  • filefolio_pdf_extract — keep only the given pages as a new document.
  • filefolio_pdf_delete_pages — drop the given pages and file the rest.
  • filefolio_pdf_rotate — rotate pages 90, 180, or 270 degrees in place.
  • filefolio_pdf_ocr — add a searchable text layer in place.

Behavior

Merge, split, extract, and delete-pages create new documents that are filed through the same AI tagging pipeline as uploads (or, with the download option, just hand you the file). Rotate and Make searchable (OCR) edit the document in place, keeping its id, tags, category, and upload date.

Split files its parts one at a time. If a later part fails to file (for example because it duplicates an existing document), the earlier parts stay filed and the response is the error for the failing part.

OCR dependencies

Make searchable / filefolio pdf ocr uses ocrmypdf, which requirements.txt installs into the virtual environment. FileFolio runs it with its own Python interpreter, so the virtual environment does not have to be activated. It also needs Tesseract (see Prerequisites) and Ghostscript on PATH. The Docker image bundles them.

  • macOS: brew install ghostscript
  • Debian/Ubuntu: apt-get install ghostscript
  • Windows: install Ghostscript from ghostscript.com, then add its bin folder (C:\Program Files\gs\gs<version>\bin) to PATH

Project structure

filefolio/
├── backend/
│   ├── main.py          # FastAPI server
│   ├── client.py        # HTTP client shared by the CLI and MCP server
│   ├── cli.py           # Command line
│   ├── mcp_server.py    # MCP server (own venv, see below)
│   └── sync_service.py  # Folder sync service
├── frontend/
│   ├── static/
│   │   ├── app.js       # Frontend JavaScript
│   │   ├── style.css    # Styles
│   │   └── i18n.json    # Translations
│   └── templates/
│       └── index.html   # Main interface
├── tests/               # Test suite
├── uploads/             # PDF storage (created on first run)
├── thumbnails/          # Document thumbnails (created on first run)
├── data/                # Database (created on first run)
├── setup.cfg             # Linting and tool configuration
├── pytest.ini            # Test configuration
├── requirements.txt
└── requirements-mcp.txt  # MCP server dependencies (separate venv-mcp/)

How it works

  1. Upload - Drag and drop a PDF file into the web interface, or sync a local folder to automatically import new files
  2. Extract - Text is extracted from the PDF (with OCR fallback for scanned documents)
  3. Analyze - A local LLM analyzes the content to determine category, tags, and suggest a filename. Suggested names follow one pattern: issuer, document type, and the month the document was issued, e.g. stadtwerke-musterstadt-electricity-bill-september-2026.pdf. Invoice numbers, amounts and other identifiers are left out
  4. Organize - The document is saved with metadata in a local SQLite database. The file on disk keeps its original name; the suggested name is stored alongside it and is what you see in the interface, so nothing is lost if a suggestion is wrong. Every suggestion is editable
  5. Search - Find documents by content, category, tags, or filename

Tech stack

  • Backend: FastAPI (Python)
  • Frontend: Vanilla JavaScript
  • Database: SQLite
  • AI/LLM: Ollama
  • PDF Processing: PyPDF, pdf2image, pytesseract
  • Styling: Custom CSS

Contributing

Contributions are welcome! Please feel free to submit a pull request or open an issue.

License

MIT License - see LICENSE file for details.

About

A privacy-first document organization tool that uses local AI to automatically categorize, tag, and rename your PDF files. All processing happens on your machine with Ollama, keeping your documents completely private.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages