View photos and safely import camera media on Omarchy.
Connect → View → Select → Import → Verify → Back Up
Marketplace preview captured from PhotoDock with a synthetic demo image. It contains no personal photo, camera serial number, GPS data, or source metadata.
PhotoDock is a local-first photo and image viewer for Omarchy. Open a mounted folder or camera card to browse thumbnails, switch between Grid and List views, and open a large photo view—even when you only want to look at photos and do not want to import them. When you are ready, PhotoDock can safely copy selected photos and videos into durable local storage, verify the copies, create an optional independent backup, and leave the source files untouched.
PhotoDock never deletes, renames, edits, or formats files on source media.
- Opens photos directly on Omarchy from mounted folders, camera cards, card readers, and supported USB mass-storage cameras
- Provides responsive Grid and List browsing plus a large keyboard-accessible photo view
- Detects supported camera cards, card readers, and USB mass-storage cameras
- Reviews eligible images, videos, file classes, sizes, and RAW/JPEG pairs
- Builds a clear destination plan before copying begins
- Prevents silent destination overwrites
- Verifies imports with an optional SHA-256 read-back workflow
- Creates an optional verified backup on a second physical device
- Recovers safely from interruption, disconnects, and partial failures
- Keeps settings, history, previews, and diagnostics local
Viewing does not require an import. Choose a mounted local photo folder or camera-media source, browse it in Grid or List mode, and open any supported image in the large detail view. PhotoDock prepares privacy-minimal local previews and leaves the source files untouched. Import controls remain available only when you decide to copy selected files. This gives the Omarchy desktop a dedicated photo-viewer surface instead of requiring a separate app just to open and inspect an image.
This repository is an unreleased v0.1 implementation candidate. Synthetic
tests are authoritative; no hardware or filesystem is publicly claimed as
supported until its report is recorded in docs/supported-hardware.md.
Mounted removable media and manual folders can currently be scanned and imported. The media browser supports a responsive thumbnail grid, a compact list, large per-file detail viewing, paginated selection, bounded embedded/JPEG previews, and an opt-in camera/exposure summary that excludes GPS and serial data. Grid and List both support Control/Command-click toggles and Shift-click range selection on the current page. Selected rows and tiles stay highlighted, and Shift plus an arrow key extends or shrinks the range. Selections are retained across views and pages. At half-screen widths, media actions reflow into two rows and the browser compacts vertically so the import settings remain reachable. An always-visible Start import action routes to any missing setting, runs the required preflight review, then becomes the final reviewed start confirmation. Device mount/unmount/eject, settings/history maintenance, delayed backup retry, notifications, and the remaining release matrices stay guarded until the evidence in implementation-status.md is complete.
Review the repository first: Omarchy plugins run unsandboxed with your user permissions. When a reviewed commit is available, install it with:
omarchy plugin add https://github.com/rodrix2000/omarchy-photodock.git --enableDuring development, validate the checkout directly:
make validate- Source paths are exposed through a read-only capability using no-follow directory/file descriptors.
- RAW/JPEG thumbnails and inspection first copy through that capability into a private cache; isolated helpers create a stripped 960×640 preview and never receive a card path. Grid thumbnails are requested sequentially and collect no camera metadata.
- Non-regular files and symlinks are rejected.
- Destination data is streamed to an exclusive hidden temporary file.
- A final path appears only through atomic
renameat2(RENAME_NOREPLACE). - Strong verification reads the complete temporary copy back and compares SHA-256 before commit.
- Duplicate means equal full SHA-256 and size, never filename or timestamp.
- A backup is called independent only when a different physical device is proven.
- Completed primary files survive cancel, backup failure, UI reload, and recovery.
- The planned unmount/eject flow is explicit and never forced; it remains guarded in this candidate until its disposable-hardware matrix is complete.
See docs/safety.md for the complete invariant contract.
The intended v1 handles mounted removable block media and manually selected local folders.
Direct PTP/MTP, gphoto2, tethering, full RAW decoding, culling, metadata editing,
file renaming, source cleanup, cloud/NAS targets, and automatic eject are not
part of v1.
PhotoDock uses current Omarchy components only: Quickshell/Qt 6, Python 3, PyGObject/Gio, UDisks2 with stock polkit, SQLite/hashlib, and the systemd user manager. It installs no package, hook, privileged helper, system unit, udev or polkit rule. It makes no network request and needs no account.
Optional local inspection uses already-installed Exiv2 and ImageMagick in a bounded transient service. Import remains functional when inspection is absent.
Mutable data lives only under XDG config/data/state/cache/runtime locations. The plugin checkout remains clean.
make validate
make test
make test-safety
make test-integration
make qml-check
make package-checkUse only generated fixtures and disposable media. See CONTRIBUTING.md and SECURITY.md.
omarchy plugin disable io.github.rodrix2000.photodock
omarchy plugin remove io.github.rodrix2000.photodockFinish or reconcile any active job first. Removing the plugin checkout does not delete XDG metadata, imported files, backups, or source photos. Data removal is deliberately separate and documented in docs/troubleshooting.md.
PhotoDock code and documentation are available under the MIT License. Copyright © 2026 Rudy Rodriguez. Third-party material, if introduced, must be listed in THIRD_PARTY_NOTICES.md.
