Documentation
Siegu docs
Guides, sync & sharing, configuration, and security — straight from the open-source project, updated with every release.
Getting started
About Siegu
Siegu (pronounced see-goo) is a privacy-first, local-only media manager for your photo and video library. It scans the folders you choose, builds a searchable library entirely on your machine, and never uploads your media anywhere. Every AI feature runs on-device via ONNX Runtime — no cloud, no accounts, no telemetry.
What Siegu can do
- Organize — Automatic scanning, EXIF metadata extraction, thumbnails, video indexing, and a map view with heatmaps.
- Semantic search — Describe a photo in your own words ("sunset at the beach") and CLIP finds it. Text search also matches file names, recognized text, object tags, captions, and locations.
- Discover — The search dropdown shows rails at a glance: Best shots, Favorites, Recent, People, Locations, Tags, Papers & screenshots, Cameras, and Months, plus one-tap filters (Favorites, Videos, Faces, Papers, NSFW, Surprise me).
- People — Automatic face detection and grouping. Name people, merge duplicates, and jump to every photo of a person.
- Analyze — On-device models enrich each photo with captions (BLIP), objects (YOLO), recognized text (OCR), aesthetics scores, depth maps (MiDaS), and audio transcription for videos (Whisper).
- Sync — Encrypted peer-to-peer sync between your own devices over the network (WebRTC), with mesh networking via LAN discovery or 6-word mnemonic phrases.
Privacy model
Everything happens on your computer. There are no accounts, no analytics, no cloud uploads. AI models are downloaded once from public sources (e.g. HuggingFace) and then run locally forever after. See docs/security.md for details.
Device Support
Siegu is verified against the platforms below. Which device you use also decides how the on-device AI models are accelerated (via ONNX Runtime):
| Platform | Devices | AI acceleration |
|---|---|---|
| Windows | Any x64 Windows 10/11 PC or laptop | DirectML (NVIDIA/AMD/Intel GPU) |
| Windows on ARM | Snapdragon X / Arm64 laptops | CPU |
| macOS | Apple Silicon Macs (M1–M4: MacBook Air/Pro, iMac, Mac mini, Mac Studio, Mac Pro) | CoreML (GPU + Neural Engine) |
| Linux | x86_64 desktops/laptops (Ubuntu, Debian, Fedora, Arch, …) | CPU |
| Linux ARM64 | Raspberry Pi 4/5, ARM single-board computers | CPU |
| Android | arm64 (arm64-v8a) phones and tablets, ~2017 and newer | CPU |
| iOS / iPadOS | iPhone and iPad (arm64, iOS 12+) | CPU (CoreML is used on macOS) |
Not supported: Intel Macs, 32-bit platforms, and Alpine Linux (musl). Android x86_64 (arm64 emulator images also work) and the iOS Simulator are supported for development; production Android builds target arm64-v8a.
Sync works between any two of the supported devices — e.g. an Android phone and a Windows PC — over your own network.
Mesh synchronization
Siegu syncs your media library between devices over encrypted peer-to-peer connections — no cloud, no accounts.
How it works
┌─────────────┐ WebRTC DTLS ┌─────────────┐
│ Device A │ ◄──────────────────► │ Device B │
│ (Host) │ encrypted P2P │ (Joiner) │
└──────┬───────┘ └──────┬───────┘
│ │
└────────── Signaling ────────────────┘
(WebSocket)
- Host starts a signaling server + mDNS broadcast
- Joiner discovers the host (mDNS, QR code, or mnemonic phrase)
- Devices exchange WebRTC SDP/ICE via the signaling channel
- A direct DTLS-encrypted data channel is established
- Devices exchange manifests (lists of photo IDs) and transfer only missing files
Connectivity Methods
LAN (Local Network)
Both devices on the same local network:
- Host: Open the Connect panel → tap Host. A QR code and 4-word mnemonic are displayed.
- Joiner: Open the Connect panel → tap Join. Devices appear automatically via mDNS. Alternatively, scan the QR code or type the mnemonic.
Remote (WAN)
For devices on different networks:
- Deploy the Go signaling server (see below)
- Host enters the signaling server URL
- Joiner connects using the same room ID
Signaling Server
LAN mode runs a built-in signaling server (embedded in the app). For remote connections, a standalone signaling server (siegu-signal, written in Rust) is available.
Self-hosting
docker compose up -d
The server runs on port 8080 with these env vars:
| Variable | Default | Description |
|---|---|---|
PORT | 8080 | Listen address |
SIEGU_SIGNAL_TOKEN | (unset) | If set, every join/room request must include this token |
Pre-built image
ghcr.io/denzyldick/siegu-signal:latest
Sync Protocol
Once connected, the sync protocol transfers only what's missing:
- Manifest exchange: Both sides share lists of photo IDs and their
sync_neededflags - File transfer: Missing files are chunked into 64KB blocks over the WebRTC data channel
- Metadata sync: AI results (captions, scores) are propagated as lightweight metadata updates
- Storage quota: Configurable via
max_storage_mbconfig key (default: unlimited)
Delta sync
Only photos with sync_needed = 1 are transferred. After a full sync, subsequent connections only transfer new/changed files.
Tips
- Both devices must have the AI models downloaded to sync AI metadata
- Storage quota is enforced per-device — configure on each device separately
- For best performance, keep devices on the same LAN
- The signaling server never sees your files — only encrypted handshake data
Collection sharing
Siegu allows you to share individual collections (albums) with others in a read-only, view-only mode.
How It Works
You (Host) Friend (Guest)
│ │
│ 1. Open a collection │
│ → tap "Share" in menu │
│ → see sharing info │
│ │
│ 2. Share via signalling server │
│ → connection coordinated │
│ → WebRTC data channel opens │
│ │
│ 3. Friend views in browser │
│ → opens share link │
│ → sees ONLY your collection │
│ → photos stream, not downloaded│
│ │
│ 4. Session ends │
│ → all data cleared │
Sharing Requirements
Collection sharing requires a signalling server to coordinate the secure WebRTC connection between your device and the viewer's browser.
Hosted Service
The easiest option: siegu.io/connect
- No setup required
- Works across networks (not just LAN)
- Secure, encrypted connections
Self-Hosted
Run your own signalling server. See SIGNALLING.md for setup instructions.
Over the internet / mobile data
Sharing across networks (including guests on cellular data) depends on the two devices finding a path to each other. When the networks block a direct connection (symmetric NAT, carrier-grade NAT on mobile data), a TURN relay carries the encrypted stream. You have two ways to provide one:
- Free, DIY: run a TURN relay on a machine you own and port-forward UDP/3478 — see NAT Traversal & TURN.
- Pro: the hosted
siegu.iorelay includes TURN, so sharing works from any network with zero router configuration.
Desktop App (local, for now)
The desktop app's Share Collection action (… → Share Collection) starts a local signalling + web server and generates a browser share link (http://127.0.0.1:PORT/#CODE.TOKEN.ALBUM). Opening it loads the view-only web client and shows only that collection; granting/copying/stopping happens right in the dialog. For now the link works on the same computer — cross-network sharing goes through a signalling server (see Remote & hosted and the single base-domain switch in src/services/appConfig.ts).
What the Viewer Can See
- Only the shared collection — the viewer cannot access other photos or collections
- Read-only — no editing, deleting, or modifying capabilities
- Streaming only — photos are not downloaded to the viewer's device
What the Viewer Cannot See
- Other collections or the full library
- File system paths or device information
- AI analysis results (unless included in the stream)
- Any metadata beyond what's in the shared photos
Privacy & Security
Data Flow
- Photos stream directly from your device to the viewer via WebRTC
- No photos are stored anywhere in between
- The signalling server only coordinates the connection (relays encrypted SDP/ICE data)
- If no direct path exists, a TURN relay forwards the encrypted stream between the devices — it never stores or reads the content
Session Security
- Sessions auto-expire after 30 minutes
- All data is cleared from the viewer's browser when the session ends
- Blob URLs are revoked to prevent cached access
- The URL hash is cleared to prevent re-loading
Anti-Crawling
robots.txtblocks all search engines- Meta tags prevent indexing of shared content
- No server-side caching of shared photos
Mobile Photo Viewer
When viewing shared photos on mobile:
- Swipe left/right — navigate between photos
- Swipe up — jump to previous time period
- Swipe down — jump to next time period
- Double-tap — toggle favorite (if connected to your library)
Troubleshooting
"Session ended" immediately
- The signalling server may not be running
- Check that the URL is correct (includes CODE.TOKEN in the hash)
Photos not loading
- Ensure both devices can reach the signalling server
- Check firewall settings for WebRTC (STUN/TURN ports)
- Try a different network if on restrictive WiFi
- On mobile data, a TURN relay is usually required — see NAT Traversal & TURN
Viewer sees "Access denied"
- The collection may not exist or the link may be expired
- Ask the host to generate a new share link
Architecture
Host Device (Tauri)
│
├── Embedded web server (serves webclient/dist/)
├── Embedded signalling server (LAN mode)
│
└── WebRTC data channel
│
└── Guest Browser
├── webclient/index.html
├── WebRTC peer connection
└── Gallery + Preview UI
Web client (view-only)
The web client is a standalone, zero-dependency browser app that lets someone view photos shared from a Siegu host — without installing anything.
How It Works
Host (Tauri app) Guest (Browser)
│ │
│ 1. Host runs `siegu-cli web` │
│ → starts signalling server │
│ → starts embedded web server │
│ → prints share URL │
│ │
│ 2. Guest opens URL ───────────────│
│ → WebSocket to /ws │
│ → WebRTC offer/answer │
│ → Data channel established │
│ │
│ 3. Guest browses gallery │
│ ← thumbnails stream via DC │
│ ← full-res on demand │
│ │
│ 4. Session ends │
│ → all blob URLs revoked │
│ → all data cleared from memory │
│ → URL hash wiped │
Running Locally
Prerequisites
- Node.js 18+
- A running Siegu host (Tauri app with
siegu-cli webactive)
Development Server
cd webclient
npm install
npm run dev
# → http://localhost:5173
The dev server proxies WebSocket connections to the host's signalling server. Open the share URL printed by siegu-cli web in your browser.
Build for Production
cd webclient
npm run build
# → dist/
The dist/ folder is served by the host's embedded web server when running siegu-cli web.
Docker (Quick Test)
Test everything with one command:
docker compose up
# → http://localhost:8080
This starts both the signalling server and web client on port 8080. Nginx serves the web client and proxies WebSocket connections to the internal signalling server.
URL Format
The share URL contains all connection info in the hash fragment:
http://HOST:PORT/#CODE.TOKEN
http://HOST:PORT/#CODE.TOKEN.ALBUM_ID
- CODE: Room code for the signalling server
- TOKEN: Authentication token
- ALBUM_ID (optional): If present, the viewer enters album-scoped mode (can only see photos in that album)
Security Features
No Persistence
- Photos stream via WebRTC data channel — nothing is downloaded to disk
- Blob URLs are revoked when the preview dialog closes
- All blob URLs are revoked when the session ends
Session Timeout
- Sessions auto-expire after 30 minutes
- A countdown timer is displayed in the header
- When expired, all data is wiped and the page shows "Session ended"
Tab Visibility
- If the browser tab is hidden for 5 minutes, the session is destroyed
- Prevents abandoned sessions from staying active
Anti-Crawling
robots.txtblocks all crawlers:User-agent: * Disallow: /- Meta tags:
noindex, nofollow, noarchive, nosnippet, noimageindex Referrer-Policy: no-referrer
Destructor
On session end (disconnect, timeout, page close), the web client:
- Revokes all blob URLs (
URL.revokeObjectURL) - Clears all in-memory caches
- Closes WebRTC peer connection and data channel
- Wipes the gallery DOM
- Replaces the URL hash (prevents re-loading the session link)
Mobile Gestures
The web client is designed for mobile browsers:
- Tap a thumbnail to open the full-res preview
- Swipe left/right in the preview to navigate between photos
- Close the preview with the × button
Keyboard Shortcuts
None — the web client is intentionally minimal.
Architecture
| File | Purpose |
|---|---|
index.html | Entry point, minimal HTML shell |
src/main.ts | All logic: signalling, WebRTC, gallery rendering, preview |
src/lib.ts | Pure utilities: parseHash, inferMime, assembleChunks |
src/style.css | Dark theme, grid layout, responsive design |
public/robots.txt | Blocks search engine crawlers |
Dependencies
Zero runtime dependencies. The web client is vanilla TypeScript bundled with Vite.
Configuration
Config is stored in the app's SQLite database (siegu.db) as key-value pairs.
Config file location
| Platform | Path |
|---|---|
| Linux | ~/.config/io.denzyl.siegu/siegu.db |
| macOS | ~/Library/Application Support/io.denzyl.siegu/siegu.db |
| Windows | %APPDATA%\io.denzyl.siegu\siegu.db |
| Android | /data/data/io.denzyl.siegu/files/siegu.db |
| iOS | ~/Library/Application Support/io.denzyl.siegu/siegu.db |
Override with --config-dir flag on CLI commands.
All Config Keys
| Key | Type | Default | Description |
|---|---|---|---|
theme | string | system | light, dark, or system |
language | string | en | UI language code |
scan_threads | integer | 4 | Parallel scan threads (1–32) |
indexing_mode | string | immediate | immediate, idle, or manual |
tier | string | free | Feature tier: free or paid |
sync_path | string | — | Custom sync download directory |
auto_scan | string | — | Enable automatic scanning (true/false) |
sync_enabled | string | — | Enable mesh sync (true/false) |
max_storage_mb | integer | 0 (unlimited) | Max storage for synced files (1–1,000,000) |
model_enabled_clip | string | — | Enable CLIP model (true/false) |
model_enabled_face | string | — | Enable face detection, recognition and grouping |
model_enabled_ocr | string | — | Enable OCR |
model_enabled_nsfw | string | — | Enable NSFW detection |
model_enabled_aesthetics | string | — | Enable aesthetics scoring |
model_enabled_yolo | string | — | Enable object detection |
model_enabled_blip | string | — | Enable image captioning |
model_enabled_arcface | string | — | Legacy alias of model_enabled_face (kept in sync by the app) |
model_enabled_midas | string | — | Enable depth estimation |
model_enabled_whisper | string | — | Enable audio transcription |
model_enabled_sam | string | — | Enable SAM segmentation |
model_enabled_superres | string | — | Enable super-resolution |
last_scan_completed | string | — | Timestamp of last scan (read-only) |
CLI Usage
# View all config
siegu-cli config get
# Get a specific key
siegu-cli config get-key theme
# Set a value
siegu-cli config set theme dark
# List all valid keys
siegu-cli config keys
Config key validation: keys are whitelisted, values have type/range checking. Invalid values are rejected with a descriptive error.
Network / TURN (host environment variables)
The host reads these from its environment when creating WebRTC connections, so guests behind restrictive networks (mobile data, carrier-grade NAT) can still connect through a relay. See NAT Traversal & TURN for the full setup.
| Variable | Default | Description |
|---|---|---|
SIEGU_TURN_URLS | None | Comma-separated TURN URLs, e.g. turn:home.example.com:3478 |
SIEGU_TURN_USERNAME | None | TURN username (only needed if the relay has auth) |
SIEGU_TURN_CREDENTIAL | None | TURN password/credential |
Security & privacy
Core Principles
- Local-First AI: All 9 AI models run on-device via ONNX Runtime. No data leaves your computer.
- Zero Telemetry: No analytics, crash reporting, or usage tracking.
- No Accounts: No user accounts, no cloud sync, no sign-up.
Data Protection
Model Downloads
- Model files are downloaded from HuggingFace and other sources over HTTPS
- SHA-256 hash verification ensures file integrity
- Files with mismatched hashes are deleted automatically
Peer-to-Peer Sync
- DTLS Encryption: WebRTC data channels are encrypted with DTLS in transit
- Zero-Knowledge Signaling: The signaling server relays only encrypted SDP/ICE data — it never sees files, metadata, or manifests
- No Persistent Server: LAN mode uses a local signaling server; remote mode uses a minimal relay that has no access to content
File Handling
- Filename Sanitization: Synced filenames are sanitized to prevent path traversal and control character injection
- Temp Landing: Received files land in
sync_temp/first, are verified, then moved to the library - Storage Quota: Configurable limit prevents disk exhaustion
Application Security
Graceful Shutdown
ShutdownCoordinator signals all background tasks (scan, sync, ML) before exit, preventing data corruption.
Transaction Safety
- All ML batch writes use
BEGIN/COMMIT/ROLLBACK - Periodically runs
VACUUMfor database maintenance
Config Validation
- All 22 config keys are whitelisted (unknown keys rejected)
- Values are type-checked with range constraints (e.g.,
scan_threads: 1–32) - Invalid values are rejected with a descriptive error
Scan Deduplication
ScanGuardprevents concurrent scan operations- Each scan skips paths already in the database
Vulnerability Reporting
Report security issues to the project maintainer via GitHub Issues or direct contact. Do not file public issues for critical vulnerabilities.
Command line (siegu-cli)
The siegu-cli binary provides headless access to all core features.
Install
cargo install --path crates/siegu-cli
Global Flags
| Flag | Description |
|---|---|
--config-dir <path> | Override config directory (default: OS-appropriate path) |
Commands
siegu-cli scan
Scan directories for media files and import into the library.
# Scan a specific folder (and add it to watched directories)
siegu-cli scan /path/to/photos
# Scan all configured watched directories
siegu-cli scan
siegu-cli analyze
Run ML analysis on photos.
# Analyze all unprocessed photos
siegu-cli analyze all
# Analyze a single photo by ID
siegu-cli analyze photo <photo-id>
# Run a specific model on all photos
siegu-cli analyze model <model-id>
Model IDs: clip, face, ocr, nsfw, aesthetics, yolo, blip, midas, whisper (ultraface/arcface are accepted as aliases of face)
All three forms accept --headless, which prints progress lines and an E2E summary instead of showing the interactive TUI (used by CI scripts).
siegu-cli models
Manage AI model files.
# List all models with download status
siegu-cli models list
# Download all models
siegu-cli models download
# Download specific models
siegu-cli models download clip face nsfw
# Show disk usage per model
siegu-cli models usage
siegu-cli config
Manage configuration.
# View all config
siegu-cli config get
# Get a specific key
siegu-cli config get-key theme
# Set a config value
siegu-cli config set theme dark
# List valid config keys
siegu-cli config keys
siegu-cli mesh
Peer-to-peer mesh synchronization.
# Host a LAN sync session (starts a signaling server + mDNS)
siegu-cli mesh host
# Host on a specific port (default 0 = pick a free port)
siegu-cli mesh host --port 9090
# Host against an existing signaling server, joining/creating a room
siegu-cli mesh host --server ws://192.168.1.100:8080 --room myroom
# Join a mesh room (room ID is positional; URL goes in --server)
siegu-cli mesh join myroom
siegu-cli mesh join myroom --server ws://192.168.1.100:8080
# When joining a --server host with a pre-agreed room, create the WebRTC offer
siegu-cli mesh join myroom --server ws://192.168.1.100:8080 --initiator
# Show session status / disconnect / storage quota usage
siegu-cli mesh status
siegu-cli mesh disconnect
siegu-cli mesh quota
# Browse a peer's library view-only and verify the manifest (#9, e2e helper)
siegu-cli mesh browse myroom --server ws://192.168.1.100:8080
# Browse in album-share mode for a specific album (#16)
siegu-cli mesh browse myroom --album <album-id>
# Send a single RPC command to the peer and print its reply (#19, e2e helper)
siegu-cli mesh rpc myroom list_files --server ws://192.168.1.100:8080
siegu-cli mesh rpc myroom toggle_favorite '{"id": "<photo-id>"}'
# Seed a manual album with the first N photos (prints ALBUM ID, e2e helper)
siegu-cli mesh seed-album --name "Shared" --take-first 5
Availability and defaults:
host—--serverconnects to an existing signaling server instead of starting a local one;--roomnames the room (required with--server).--share-mode <ro|rw>sets the permission level for connected peers (defaultro):roallows browsing only,rwalso allows favorites/trash mutations.join—--initiatormakes this peer create the WebRTC offer (needed when joining a--serverhost).browse,rpc, andseed-albumare e2e test helpers; they print greppableVIEWONLY,RPC RESULT, andALBUM IDmarkers used byscripts/e2e-view-only.sh.- All mesh subcommands accept
-c/--configto point at a config directory.
Remote sync via mesh
There is no separate siegu-cli sync command. Remote (non-LAN) sync is done with the mesh commands above — host on one machine, join on the other — using a signaling server URL in --server.
siegu-cli serve
Start a standalone LAN signaling server.
siegu-cli serve --port 8080
siegu-cli web
Share this machine's library as a browser gallery (#11, #19). Starts an embedded signaling server plus a small static web server and prints a one-off link. Opening the link is the consent step — anyone holding it can browse the library until the command stops. Nothing is downloaded or written on the viewing device; media streams over the WebRTC data channel on demand.
siegu-cli web
# Open in a browser on this machine:
# http://127.0.0.1:8787/#<code>.<token>
# Or from another device on this network:
# http://192.168.1.45:8787/#<code>.<token>
Flags: --port for the static client port (default 8787), --config as usual, and --share-mode <ro|rw> (default ro). The default ro is view-only — guests can browse but not change anything. rw additionally lets guests toggle favorites and trash photos. The browser webclient itself is read-only; the rw mode is consumed by the mesh browse/rpc test helpers.
The web bundle lives in webclient/; build it once with cd webclient && bun install && bun run build (npm also works), or point SIEGU_WEB_DIST at a built dist/ directory.
siegu-cli status
Show app overview.
siegu-cli status
Output includes: config directory, database status, photo/video counts, watched folders, config values, model disk usage, available memory.
Looking for the full developer documentation? Browse the GitHub docs.
