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.tomlfrom the mountedconfigdirectory. Keep the directory writable by UID 1000, the user the container runs as, so saneless can save the profiles it generates there. SANELESS_SCANNER__HOSTnames the machine runningsaned. A container always needs it, because it reaches scanners only over the network.saneless-datais a named volume for the job database and any scans kept after a failed upload.--stop-timeout 90gives a stop during a scan time to keep the pages scanned so far, asstop_grace_period: 90sdoes in the shippeddocker-compose.yml.- On a host with SELinux enforcing (Fedora, RHEL, Rocky), the container cannot read
configuntil 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.
- Your First CLI Scan -- step-by-step tutorial
- How-To Guides -- installation, Docker, profiles, duplex, CLI
- Configuration Reference -- all TOML options and defaults
- CLI Reference -- commands, flags, exit codes
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)
| File | Size | Uploaded | |
|---|---|---|---|
| saneless-0.2.0.tar.gz | 486.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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