Self-hosted picture library with AI tagging, semantic search, and a clean web UI
Reason this release was yanked:
Takes presedence over the newer 1.0.0b-releases
Project description
PixlStash
PixlStash is a local picture library server for organizing, filtering, and reviewing large image collections.
It provides:
- A browser-based interface
- Fast metadata and tag filtering
- Smart score sorting
- Character and set organization
- Local storage of your library data
- Simple keyboard shortcuts for scoring, selection, deletion and navigation.
PixlStash runs on your machine and serves the UI at a local web address.
Install PixlStash
Choose one installation method.
Option 1: Windows installer
Use this if you want the easiest setup on Windows.
- Go to the GitHub Releases page for this repository.
- Download the latest Windows installer
.exe. - Run the installer.
- Start PixlStash Server from the Start Menu shortcut.
- Open your browser to
http://localhost:9537.
Windows SmartScreen warning: Because the installer is not yet signed with a paid code-signing certificate, Windows SmartScreen may show a red "Windows protected your PC" dialog when you run it. This is expected. Click More info and then Run anyway to proceed with the installation.
![]()
Option 2: Install from PyPI
Use this if you already have Python and want a pip install.
NOTE: You really, really should do this in a virtual environment:
python -m venv venv
. venv/bin/activate
Requirements:
- Python 3.10 or newer
Install:
pip install pixlstash
Run:
pixlstash-server
Then open:
http://localhost:9537
Option 3: Clone and run manually
Use this if you want to run from source.
Requirements:
- Python 3.10 or newer
- Node.js 20 or newer
- npm
Steps:
git clone https://github.com/pikselkroken/pixlstash.git
cd pixlstash
python -m venv .venv
# Windows:
.venv\Scripts\activate
# macOS/Linux:
# source .venv/bin/activate
pip install --upgrade pip
pip install -e .
cd frontend
npm ci
npm run build
cd ..
pixlstash-server
Then open:
http://localhost:9537
Option 4: Docker (GPU — Linux / WSL2 on Windows)
Use this if you want a fully self-contained container with CUDA support. A pre-built image is published to the GitHub Container Registry on every release — no clone required.
Prerequisites
On Linux (native Docker)
- Install Docker Engine.
- Install the NVIDIA Container Toolkit:
distribution=$(. /etc/os-release; echo $ID$VERSION_ID)
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
| sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -sL "https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list" \
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
- Verify GPU access:
docker run --rm --gpus all nvidia/cuda:12.8.1-base-ubuntu24.04 nvidia-smi
On Windows (WSL2)
- Install WSL2 with Ubuntu 24.04.
- Install an NVIDIA Windows driver ≥ 525 from nvidia.com/drivers — do not install a driver inside WSL2 itself; the Windows driver is shared automatically.
- Install Docker Desktop with the WSL2 backend enabled, or install Docker Engine directly inside WSL2 as per the Linux steps above.
- Install the NVIDIA Container Toolkit inside your WSL2 distro (same commands as the Linux section above).
- Verify GPU access from WSL2:
docker run --rm --gpus all nvidia/cuda:12.8.1-base-ubuntu24.04 nvidia-smi
Run (pre-built image — recommended)
Pull and start the container:
docker run -d \
--runtime nvidia \
-e NVIDIA_VISIBLE_DEVICES=all \
-e NVIDIA_DRIVER_CAPABILITIES=compute,utility \
-e PIXLSTASH_HOST=0.0.0.0 \
-p 9537:9537 \
-v pixlstash-home:/home/pixlstash \
--name pixlstash \
ghcr.io/pikselkroken/pixlstash:latest
Open http://localhost:9537 in your browser.
All data (images, database, config, downloaded models) is stored in the pixlstash-home named volume and persists across restarts.
To update to the latest release:
docker pull ghcr.io/pikselkroken/pixlstash:latest
docker rm -f pixlstash
# re-run the docker run command above
To pin to a specific release, replace latest with a version tag, e.g. ghcr.io/pikselkroken/pixlstash:0.9.1.
Optional: docker-compose.yml
If you prefer Compose for easier management:
services:
pixlstash:
image: ghcr.io/pikselkroken/pixlstash:latest
runtime: nvidia
ports:
- "9537:9537"
volumes:
- pixlstash-home:/home/pixlstash
environment:
PIXLSTASH_HOST: "0.0.0.0"
PIXLSTASH_PORT: "9537"
NVIDIA_VISIBLE_DEVICES: all
NVIDIA_DRIVER_CAPABILITIES: compute,utility
restart: unless-stopped
volumes:
pixlstash-home:
docker compose up -d
# To update:
docker compose pull && docker compose up -d
Run (build from source)
Use this if you need a custom build or want to run unreleased changes.
git clone https://github.com/pikselkroken/pixlstash.git
cd pixlstash
docker compose up --build
Then open http://localhost:9537.
First run and data location
On first run, PixlStash creates a user config directory and stores:
- Server config
- Database
- Imported media files
Model downloads: On first startup, PixlStash automatically downloads the AI models required for tagging, captioning, and quality scoring. This includes several hundred MB of model weights. Downloads happen in the background and are stored in the platform user data directory:
OS Path Linux ~/.local/share/pixlstash/downloaded_models/macOS ~/Library/Application Support/pixlstash/downloaded_models/Windows %LOCALAPPDATA%\pixlstash\downloaded_models\An internet connection is required the first time the server starts. Subsequent starts use the cached models.
If you need to use a custom config path:
python -m pixlstash.app --server-config "C:\path\to\server-config.json"
Server configuration
On first run, PixlStash generates a server-config.json file in the user config directory:
- Linux / macOS:
~/.config/pixlstash/server-config.json - Windows:
%LOCALAPPDATA%\pixlstash\server-config.json
You can also supply a custom path with --server-config <path>.
Edit the file and restart the server to apply changes.
Network and port
| Key | Default | Description |
|---|---|---|
host |
"localhost" |
Address the server binds to. Change to "0.0.0.0" to expose the server on the local network. |
port |
9537 |
TCP port the server listens on. |
cors_origins |
[] |
Extra origins allowed to make credentialed cross-origin requests. localhost, 127.0.0.1, and the server's own LAN IP are always permitted on any port. |
At startup the server detects its own LAN IP and automatically allows it on any port. This means the Vite dev server works over LAN (http://192.168.1.5:5173 → http://192.168.1.5:9537) without any extra configuration, as long as network access is enabled via host.
Use cors_origins only if you need to allow origins on a different machine entirely.
SSL / HTTPS
| Key | Default | Description |
|---|---|---|
require_ssl |
false |
Enable HTTPS. When true, the server will use the key and certificate below. |
ssl_keyfile |
<config_dir>/ssl/key.pem |
Path to the SSL private key file. |
ssl_certfile |
<config_dir>/ssl/cert.pem |
Path to the SSL certificate file. |
cookie_samesite |
"Lax" |
SameSite attribute for session cookies ("Lax", "Strict", or "None"). |
cookie_secure |
false |
Set the Secure flag on session cookies. Enable when serving over HTTPS. |
Storage
| Key | Default | Description |
|---|---|---|
image_root |
<config_dir>/images |
Directory where imported media files are stored. |
watch_folders |
[] |
List of folder entries to watch for new images and automatically import them. Each entry is an object with the fields below. |
Each entry in watch_folders has the following fields:
| Field | Type | Default | Description |
|---|---|---|---|
folder |
string | — | Absolute path to the directory to monitor (recursively). |
delete_after_import |
boolean | false |
When true, source files are deleted from the watch folder after a successful import. |
Example:
"watch_folders": [
{ "folder": "/home/user/downloads/photos", "delete_after_import": false },
{ "folder": "/mnt/camera", "delete_after_import": true }
]
Processing
| Key | Default | Description |
|---|---|---|
default_device |
"cpu" |
Device used for AI processing ("cpu" or "cuda"). |
generate_thumbnails_on_startup |
true |
Generate missing thumbnails when the server starts. |
Logging
| Key | Default | Description |
|---|---|---|
log_level |
"info" |
Log verbosity ("debug", "info", "warning", "error"). |
log_file |
<config_dir>/server.log |
Path to the log file. |
Example config
{
"host": "localhost",
"port": 9537,
"log_level": "info",
"require_ssl": false,
"image_root": "/home/user/.config/pixlstash/images",
"watch_folders": [
{ "folder": "/path/to/photos", "delete_after_import": false }
],
"default_device": "cpu",
"generate_thumbnails_on_startup": true
}
Installing CUDA 12.8 for GPU Acceleration (Windows & Linux)
PixlStash can run fully on CPU, but GPU acceleration requires CUDA 12.8 plus the corresponding CUDA-enabled PyTorch and ONNX Runtime packages.
-
Install or update your NVIDIA driver (must support CUDA 12.x).
-
Install the CUDA Toolkit for your distribution from NVIDIA’s CUDA downloads page. 1
-
Verify installation:
nvcc --version nvidia-smi -
Install PyTorch with CUDA 12.8 (from the pixlstash install folder):
venv\Scripts\Activate pip install torch torchvision --force-reinstall --index-url https://download.pytorch.org/whl/cu128
-
Install ONNX Runtime GPU:
pip uninstall -y onnxruntime pip install onnxruntime-gpu
Verify GPU availability
Linux
python - <<EOF
import torch
print("CUDA available:", torch.cuda.is_available())
EOF
Windows
py -c "import torch; print('CUDA available:', torch.cuda.is_available()); \
print('GPU:', torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'N/A')"
Updating PixlStash
PyPI install
pip install --upgrade pixlstash
Source install
Pull latest changes, rebuild frontend, and reinstall:
git pull
cd frontend
npm ci
npm run build
cd ..
pip install -e .
Troubleshooting
- If the page does not load, confirm the server process is running.
- If port
9537is in use, set a different port in your server config file. - If frontend assets are missing, rebuild frontend with
npm run buildand restart the server.
GPU startup fails (CUDAExecutionProvider unavailable)
If startup reports that ONNX CUDAExecutionProvider is unavailable, you likely have CPU-only ONNX Runtime installed.
Fix your environment:
pip uninstall -y onnxruntime
pip install onnxruntime-gpu
Verify providers:
python -c "import onnxruntime as ort; print(ort.get_available_providers())"
Expected output should include CUDAExecutionProvider.
If you prefer CPU mode, set "default_device": "cpu" in server-config.json.
Installing plugins
PixlStash supports built-in plugins and user-created plugins.
User plugin directory
Place your .py plugin files in the platform-specific user data directory. PixlStash logs the exact path on startup.
| OS | Path |
|---|---|
| Linux | ~/.local/share/pixlstash/image-plugins/user/ |
| macOS | ~/Library/Application Support/pixlstash/image-plugins/user/ |
| Windows | %LOCALAPPDATA%\pixlstash\image-plugins\user\ |
Writing a plugin
Use the template from pixlstash/image_plugins/built-in/plugin_template.py in the source repository as a starting point:
- Create a new
.pyfile in your user plugin directory. - Subclass
ImagePlugin, set a uniquenameandplugin_id, and implementrun(). - Restart PixlStash Server — plugins are loaded at startup.
plugin_template.py is ignored by plugin discovery and will not be loaded as a plugin.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pixlstash-0.9.5.tar.gz.
File metadata
- Download URL: pixlstash-0.9.5.tar.gz
- Upload date:
- Size: 6.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
80802886493a7b6db5e4f018707d41944de8c2dda6c52ba4dfe8c34a0a923d69
|
|
| MD5 |
d43af51381e1aa9068137f2c4df20998
|
|
| BLAKE2b-256 |
e42f75eec473bfc85c4224fd89cf65d2f038b72472537b36f1b689eb4b284df4
|
Provenance
The following attestation bundles were made for pixlstash-0.9.5.tar.gz:
Publisher:
publish-pypi.yml on Pikselkroken/pixlstash
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pixlstash-0.9.5.tar.gz -
Subject digest:
80802886493a7b6db5e4f018707d41944de8c2dda6c52ba4dfe8c34a0a923d69 - Sigstore transparency entry: 1084550925
- Sigstore integration time:
-
Permalink:
Pikselkroken/pixlstash@aa62ab502f4962e5ff7973d0a4e3c8c780aec4a0 -
Branch / Tag:
refs/tags/v0.9.5 - Owner: https://github.com/Pikselkroken
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@aa62ab502f4962e5ff7973d0a4e3c8c780aec4a0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pixlstash-0.9.5-py3-none-any.whl.
File metadata
- Download URL: pixlstash-0.9.5-py3-none-any.whl
- Upload date:
- Size: 6.5 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c7f2d8c98ed577d1c43bb3bc16a9588843d93703d3f4078f6bd445a9e13affa
|
|
| MD5 |
fa985fbb4a15f60afa6a8d9051eb451f
|
|
| BLAKE2b-256 |
b13d43e81c7f15ac45d594a171f882fcebd4552bd239697b598115dd02e9b2dd
|
Provenance
The following attestation bundles were made for pixlstash-0.9.5-py3-none-any.whl:
Publisher:
publish-pypi.yml on Pikselkroken/pixlstash
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pixlstash-0.9.5-py3-none-any.whl -
Subject digest:
7c7f2d8c98ed577d1c43bb3bc16a9588843d93703d3f4078f6bd445a9e13affa - Sigstore transparency entry: 1084550982
- Sigstore integration time:
-
Permalink:
Pikselkroken/pixlstash@aa62ab502f4962e5ff7973d0a4e3c8c780aec4a0 -
Branch / Tag:
refs/tags/v0.9.5 - Owner: https://github.com/Pikselkroken
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@aa62ab502f4962e5ff7973d0a4e3c8c780aec4a0 -
Trigger Event:
push
-
Statement type: