Skip to main content

saneless

SANE scanner to paperless-ngx bridge. Web UI and CLI for triggering scans, assembling multi-page PDFs, and ingesting documents into paperless-ngx with metadata.

System Requirements

python-sane requires the SANE development headers to compile:

Distro Package
Debian / Ubuntu libsane-dev
Fedora / RHEL / Rocky sane-backends-devel
Arch sane
Alpine sane-dev

Install them before installing saneless:

# Debian/Ubuntu
sudo apt-get install libsane-dev

# Fedora/RHEL/Rocky
sudo dnf install sane-backends-devel

Install

saneless is not yet published on PyPI, so this installs the current default branch from GitHub, which needs git as well as the SANE package above:

pip install git+https://github.com/kdknigga/saneless

Docker

The Docker image includes libsane and handles python-sane compilation automatically.

First create a config directory and put your paperless-ngx details in config/saneless.toml:

mkdir config
[paperless]
url = "https://paperless.example.com"
token = "your-api-token-here"

Then start the container from the directory that holds config:

docker run -d --name saneless -p 8080:8080 \
  --stop-timeout 90 \
  -v "$(pwd)/config:/etc/saneless" \
  -v saneless-data:/var/lib/saneless \
  -e SANELESS_SCANNER__HOST=192.168.1.50 \
  ghcr.io/kdknigga/saneless:0.2
  • The container reads /etc/saneless/saneless.toml from the mounted config directory. Keep the directory writable by UID 1000, the user the container runs as, so saneless can save the profiles it generates there.
  • SANELESS_SCANNER__HOST names the machine running saned. A container always needs it, because it reaches scanners only over the network.
  • saneless-data is a named volume for the job database and any scans kept after a failed upload.
  • --stop-timeout 90 gives a stop during a scan time to keep the pages scanned so far, as stop_grace_period: 90s does in the shipped docker-compose.yml.
  • On a host with SELinux enforcing (Fedora, RHEL, Rocky), the container cannot read config until it is relabelled: write that mount as -v "$(pwd)/config:/etc/saneless:z". See Docker volumes.

Open http://localhost:8080 to scan. docker exec saneless saneless doctor checks the setup, and docker exec saneless saneless auto-profiles writes scan profiles into config/saneless.toml from what your scanner reports.

For a permanent setup, use Deploy with Docker Compose.

Usage

saneless devices                      # List available SANE scanners
saneless auto-profiles                # Write scan profiles from what the scanner reports
saneless doctor                       # Check that saneless is ready to scan
saneless scan --title "Some Document" # Scan a document with the default profile
saneless scan --profile adf-duplex --title "Invoice" # A profile auto-profiles writes for a duplex feeder
saneless serve                        # Start web UI
saneless jobs                         # View job history

Configuration

saneless reads its settings from saneless.toml; in the container that is /etc/saneless/saneless.toml. A minimal file:

[scanner]
host = "192.168.1.100"

[paperless]
url = "https://paperless.example.com"
token = "your-api-token-here"

Scan profiles come from saneless auto-profiles, which writes them into the same file from what your scanner reports. Where saneless looks for the file, and how SANELESS_<SECTION>__<FIELD> environment variables override it, is in Where saneless reads settings.

Documentation

Full documentation is available at kdknigga.github.io/saneless.

Metadata

Release files for saneless 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for saneless 0.2.0
File Size Uploaded
saneless-0.2.0.tar.gz 486.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for saneless 0.2.0
File Interpreter ABI Platform
saneless-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / saneless-0.2.0.tar.gz

Download URL saneless-0.2.0.tar.gz
Size 486.8 kB
Tags Source
SHA-256 checksum
How to use checksums
28bb83ab5bee09976991697b9fe6391662f6b674831b125724ab72f1bf0c1947
BLAKE2b-256 checksum
How to use checksums
ce5e917841daa1af89825b0ced82369c4a987ada30140e92bc3e99d4accf228b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / saneless-0.2.0-py3-none-any.whl

Download URL saneless-0.2.0-py3-none-any.whl
Size 534.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
86026d4ac6c3a923371a87560d2aec06fa9faff7f4a931cc1f984f37c9b58744
BLAKE2b-256 checksum
How to use checksums
084f05bc28e46b556a375dec2eb3f213848104892564692902bb1f04e6278d03
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page