Self-hosted service
LC044/TrailSnap avatar
LC044/TrailSnap

TrailSnap: an AGPL-3.0 photo album that reads your train tickets

TrailSnap (行影集) | AI-Powered open-source photo album for travel & life memories.(AI赋能的开源相册工具,珍藏旅行与生活点滴)

731 stars97 forksPythonAGPL-3.0

At a glance

What is it?
TrailSnap (行影集) is a self-hosted Python photo album built around travel records: ticket OCR, a footprint map, face and scene classification, and an agent layer that plugs into Claude Code and OpenClaw. The README is honest about what is finished and what is not, and that distinction should drive your decision.
Who is it for?
Adopt TrailSnap if you already run Docker on a machine with a GPU or a spare CPU, you keep your photos in local folders, and you want ticket OCR, a footprint map and an agent interface rather than a polished mobile gallery. Do not adopt it if you need a mature travel-log workflow, a managed phone backup, or a permissive licence for a closed product, since AGPL-3.0 will follow any modified version you expose over a network.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap TrailSnap is aiming at: photos that never become a trip

Most self-hosted galleries treat a photo as a file with a timestamp. TrailSnap treats it as evidence of a journey. The README states the intent plainly: it wants to record the train tickets, attraction tickets and concert tickets sitting inside your camera roll, and to turn a trip from something you photographed into something you can revisit and share. The feature table backs this up with rows that a general-purpose gallery does not have: 车票识别 (ticket recognition) for train tickets and itineraries, 去过的景区 (visited scenic areas) with a 5A-level attraction count, 点亮的城市 (lit-up cities), and an annual report that assembles a photo wall, travel cities, itinerary timeline and route mileage. The target user is someone who keeps a local photo library, travels enough to accumulate tickets and location data, and is willing to run Docker to get that structure. It is not aimed at someone who wants a phone app that silently uploads to a cloud.

Four containers: what the compose file actually tells you about the architecture

The manual deployment section of the README gives a docker-compose.yml that splits the system into four services. postgres runs siyuan044/pgvector:pg18-trixie, a Postgres 18 image with pgvector, which implies embeddings are stored in the same database as relational data. server runs siyuan044/trailsnap-server:latest on port 8000, mounts ./data and a local photo directory, and receives DB_URL, RAILWAY_DB_URL, AI_API_URL=http://ai:8001 and TRAILSNAP_ROOT_PATH=/api as environment variables. ai runs siyuan044/trailsnap-ai:latest on 8001, shares the same ./data volume, and exposes a /health-check endpoint that the compose healthcheck calls with a three second timeout. frontend is the fourth image, siyuan044/trailsnap-frontend, which is where the Docker pulls badge in the README points. The split matters for planning: the AI container is the one that will hold model weights and do the heavy work on faces, scenes and OCR, while server handles indexing and the API. Two details in the compose file are easy to miss and will cost you an evening. The photo mount is written as F:\Photos:/app/Photos/, a Windows host path, and the README warns in the same breath that you must change the mount path to a local path or the scanner cannot see your photos. The other is TRAILSNAP_PUBLIC_URL, commented as needing to be the host's LAN address so the app can auto-discover the instance.

Getting it running: three routes, and the one that avoids the most typing

The README offers three installation paths. The simplest is a desktop package from the Releases page, downloaded and installed per platform. The second is a one-line installer: curl -fsSL https://trailsnap.cn/install.sh | bash on Linux, macOS or WSL2, or irm https://trailsnap.cn/install.ps1 | iex in Windows PowerShell. The README says the script handles Docker installation, registry mirror configuration and service deployment, and that non-interactive mode, GPU acceleration and custom ports are documented separately at trailsnap.cn/docs/guide/install.html. The third is the manual compose file quoted above. Whichever route you take, the configuration surface you will actually touch is small: DB_URL and RAILWAY_DB_URL for the two databases, AI_API_URL pointing the server at the ai container, TRAILSNAP_ROOT_PATH for the API prefix, TRAILSNAP_PUBLIC_URL for LAN discovery, and the volume lines. The Postgres service sets POSTGRES_DB, POSTGRES_USER and POSTGRES_PASSWORD all to trailsnap in the example, which is fine for a home network and not fine for anything reachable from outside. There is also a hosted demo at demo.siyuan.ink with the credentials trailsnap / trailsnap if you want to see the interface before pulling four images.

The agent layer is the differentiator, and the least documented part

TrailSnap ships a CLI and a SKILL mechanism, and the feature table marks both as implemented. The README says the skill support lets you connect platforms such as OpenClaw and Claude Code so that automatic task execution can be driven from outside the app, and the repository topics include agent, agent-skills, skill-md and yolo. That combination is unusual for a photo album and it is the reason to look at this project rather than at a conventional gallery. What the supplied material does not contain is the skill file format, the CLI command surface, or any example invocation. The README describes the Agent row as conversation with a large model that generates a travel journal in one action, but the travel log row in the same table is marked 待开发 (to be developed), and the core-features list puts AI-generated travel journals under a section headed as still in progress. So the agent plumbing exists, and the end-to-end journal feature it is meant to serve is not finished. If agent-driven photo workflows are your reason for adopting, budget time to read the skill definitions in the repository before you assume the documented outcome works.

What is finished versus what is promised

The feature table is more useful than most, because it separates the two. Marked as implemented: the agent, the CLI, skill support, ticket recognition for train tickets and itineraries, the annual report, AI analysis that generates descriptions and scores for a digital gallery, the same-day-in-previous-years view, lit-up cities, visited scenic areas with custom boundaries, adding external folders as scan sources, live photo support for iPhone, vivo, oppo and Xiaomi, the timeline, the footprint album with list, map, timeline and track views, face recognition, scene classification into categories such as night scenes, pets, food and selfies, smart search across people, content and time, tags, conditional albums and smart albums. Marked as not finished: travel logs, and the richer itinerary management covering concert tickets, scenic area tickets, hotel orders and movie tickets. The core-features section also lists AI video editing for VLOG generation, AI photo retouching and automatic high-quality photo selection as 待开发. The todo list marks MCP protocol support as unchecked. Read that table before you plan a workflow around ticket scanning beyond train tickets, because the category is broader in the pitch than in the implementation.

Where it is the wrong tool

The compose file is the clearest statement of the constraint. This is a server you run, with a Postgres instance and a separate AI container, not a service that backs up your phone. If your photos live in iCloud or Google Photos and you have no local folder to mount, the external-folder feature has nothing to scan and the whole indexing pipeline has no input. The AI container is also the part most likely to disappoint on modest hardware: the README documents GPU acceleration as an option in the installer, which implies the default is CPU, and face recognition, scene classification and OCR over a large library are exactly the workloads where CPU-only processing becomes a background job measured in days. The ticket recognition scope is a second boundary. Train tickets and itineraries are implemented; concert tickets, hotel orders and movie tickets are on the todo list, so a user whose travel records are mostly flights and hotels will find the headline feature covers less than expected. Third, the travel log is not built. If the thing you want is a written record of each trip assembled from your photos, the agent can converse and the CLI exists, but the feature that would produce the artifact is marked as pending.

The alternative, and the actual difference in approach

The obvious comparison is Immich, the self-hosted photo and video backup tool that has become the default answer for people leaving cloud galleries. The difference is in what each treats as the primary object. Immich is organised around the library and the device: it takes over backup from your phone, deduplicates, and gives you a fast chronological and map-based browser with its own machine learning for faces and search. TrailSnap is organised around the trip. Its distinctive tables are tickets, itineraries, scenic areas and cities, and its annual report assembles route mileage and a travel timeline rather than a storage summary. The practical consequence is that Immich is the better tool if your problem is that your photos are scattered across phones and clouds and you want one authoritative copy. TrailSnap is the better tool if your photos are already on a disk you control and the problem is that a trip disappears into a folder the moment you get home. They are not mutually exclusive in principle, but running both means two Postgres instances, two machine learning pipelines and two sets of embeddings over the same files, so pick the one whose primary object matches your actual complaint.

Licence, release cadence and the cost of staying current

TrailSnap is AGPL-3.0. For a self-hosted personal deployment that changes nothing: you run it, you keep your modifications to yourself, and the copyleft obligation does not attach to anything you distribute. It matters if you intend to modify TrailSnap and expose the modified version to users over a network, because the AGPL's network clause treats that as distribution and requires you to offer the corresponding source. It also matters if you were hoping to embed this in a closed product. This is a description of the licence, not legal advice; if your situation is commercial, read the full text or ask someone qualified. On maintenance, the release history shows v0.14.1 on 2026-09-08, v0.14.0 the day before, and v0.13.1 on 2026-09-04, with the last push to the default branch on 2026-09-10. Patch releases arriving within days of each other suggest active development and also suggest that pinning a specific tag is wiser than tracking siyuan044/trailsnap-server:latest, which the compose file uses. The upgrade cost is concentrated in the database: the pgvector image and the ./pg_data volume are the state you cannot rebuild from the containers, so back up that volume before pulling a new tag, and check whether a release notes a schema change before you do.

Editorial conclusion

Adopt TrailSnap if you already run Docker on a machine with a GPU or a spare CPU, you keep your photos in local folders, and you want ticket OCR, a footprint map and an agent interface rather than a polished mobile gallery. Do not adopt it if you need a mature travel-log workflow, a managed phone backup, or a permissive licence for a closed product, since AGPL-3.0 will follow any modified version you expose over a network. Before committing, verify three things: that the ai container reports healthy on /health-check, that TRAILSNAP_PUBLIC_URL matches the LAN address you actually browse from, and that the mount line pointing at your photo directory resolves inside the container rather than only on the host.

Official sources

  1. LC044/TrailSnap on GitHub
  2. License: AGPL-3.0
  3. Project website
  4. README
  5. Releases
Community notes

Community notes