Self-hosted service
LC044/TrailSnap avatar
LC044/TrailSnap

TrailSnap's manual compose block ships a database and no application

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

763 stars96 forksPythonAGPL-3.0

At a glance

What is it?
A self-hosted AI photo album that indexes faces, places and ticket photos, with a Docker stack, desktop installers and agent integrations. The README is Chinese, and its feature table disagrees with its own feature list about what is finished.
Who is it for?
TrailSnap is a wide feature set for a self-hosted album, with the recognition and organisation work in place and the agent integration visible in the repository, but read its documentation as a mixture of two vintages. Check the boxes for yourself before planning around a feature, because the capability list, the feature table and the Todo List give three different answers for ticket recognition, the travel diary and MCP.
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 received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

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

Editorial analysis

The manual compose example defines a database and nothing else

The README is written in Chinese, with an English version linked from the header at doc/README_en.md, and the default branch is master rather than main. The installation section offers three routes: a desktop package from the Releases page, a one click script, and manual deployment.

The manual route is the interesting one. The instructions say to make sure Docker and Docker Compose are installed, then tell you to edit docker-compose.yml so the mount paths point at your local directories, and the compose file that follows contains a single service:

yml
version: '3.8'

services:
  postgres:
    image: siyuan044/pgvector:pg18-trixie
    container_name: postgres_container
    restart: always
    environment:
      TZ: Asia/Shanghai
      POSTGRES_DB: trailsnap
      POSTGRES_USER: trailsnap
      POSTGRES_PASSWORD: trailsnap
      POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=C --lc-ctype=C"
      PGDATA: /var/lib/postgresql/data/pgdata
    networks: [ app-network ]
    volumes:
      - ./pg_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U trailsnap -d trailsnap -p 5432"]
      interval: 5s

There is no application service in that block, no image for TrailSnap itself and no mount for your photo directory. The compose files that do define the stack live in a docker-compose/ directory at the repository root, and the step after the snippet is simply to start what was shown with `docker-compose up -d`. Anyone following the manual route literally gets a Postgres container with pgvector, credentials set to trailsnap for the database, user and password, and a health check every five seconds.

The feature table and the feature list disagree about what is finished

The README describes the features twice, in two different notations, and the two do not match.

The bullet list of core capabilities marks trip records, which cover train tickets, itineraries and scenic or concert tickets with automatic recognition, as under development. The feature overview table underneath marks the same capability, ticket recognition with automatic extraction of itinerary details, with a check. Further down the table, Agent is checked and described as talking to a large language model to generate a travel diary in one click, while the bullet list marks that same one sentence travel diary as still to be developed, and the table's own travel diary row is marked as to be developed.

The Todo List adds a third version. The recycle bin and the skills support are ticked, while MCP protocol support, richer trip management for concert, hotel and cinema tickets, and the fuller AI capabilities are not. The tree at the repository root contains an .mcp.json, so the protocol work is at least partly in the repository while its checkbox is still open.

Everything else in the table is checked: cities, scenic spots, external folders, live photo, timeline, footprint album, face recognition, scene classification, smart search, tags, conditional albums and smart albums.

The agent bridge is a private package with no tsconfig.json

The MCP and skill integration lives in the root package.json, which is named trailsnap-pi-agent, marked private, and carries version 0.2.0 while the application itself is at v0.16.0. Its description says it is a TrailSnap MCP bridge and agent skill for Pi, and its only runtime dependency is @modelcontextprotocol/sdk at 1.30.0.

Two peer dependencies, @earendil-works/pi-coding-agent and typebox, are declared optional in peerDependenciesMeta, so the bridge runs without them. A pi block registers an extension at integrations/pi/extensions/trailsnap-mcp.ts and a skill at ./skills/trailsnap-agent.

The type checking is worth noting. check:pi runs tsc with the whole option list spelled out on the command line, NodeNext for both module and resolution, ES2022 as the target, skipLibCheck and allowImportingTsExtensions, against exactly two files, the extension and its test. There is no tsconfig.json anywhere in the repository root, so this check is configured entirely by flags. The matching test script runs tsx --test over the files in integrations/pi/tests. The README's claim that the skill plugs into OpenClaw and Claude Code is consistent with those paths, and its MCP checkbox is not.

The install script installs Docker and rewrites registry configuration

The one click route is two lines:

bash
curl -fsSL https://trailsnap.cn/install.sh | bash

and, on Windows PowerShell:

powershell
irm https://trailsnap.cn/install.ps1 | iex

What that script is described as doing is worth reading before running it: it completes the Docker installation, configures an image accelerator, and deploys the service. So this is not an application installer, it is a machine configuration script that installs a container runtime, changes how your Docker daemon fetches images, and then deploys the app. The non interactive mode, GPU acceleration and custom port options are not in the repository; they are documented on the project site at trailsnap.cn/docs/guide/install.html, along with the source deployment guide.

The desktop package route is the least invasive one. The Releases page carries per platform installers, and the newest three tags are v0.14.2 on 2026-09-11, v0.15.0 on 2026-09-18 and v0.16.0 on 2026-09-24, with the last push to the repository on 2026-10-02.

One address on port 3180, and the database never leaves the internal network

The web interface, the mobile app and the CLI all point at the same TrailSnap address, given as http://192.168.1.10:3180 in the README, with the API collected under /api by a gateway. The server, the AI components and the database talk only inside the Docker network and are not meant to be exposed to users, which is why the compose snippet above opens no port at all for Postgres.

Phone discovery is handled in three ways, and the fallback is the interesting one. The Android app tries to find the instance automatically, and when mDNS returns nothing it probes the default unified entry point on the local network, which is why a bridge network deployment does not need multicast ports opened. Linux users who want stronger mDNS can start an optional host broadcast service with a compose profile:

bash
docker compose --profile lan-discovery up -d

Other platforms are told to scan the QR code generated from the connect phone app entry in settings. So LAN discovery depends on either multicast, a probe of a guessed address, or a QR code, and only the Linux path is a documented switch you control.

The demo site publishes the account and the password

The README offers a hosted demo at https://demo.siyuan.ink for anyone who does not want to deploy, and gives the credentials in the same line: the account and the password are both trailsnap.

That is a deliberate choice for a public trial, and it also means the demo is a shared environment. Anything uploaded there is visible to whoever else is signed in, the account is not private, and nothing on that page suggests the instance is reset between visitors. The README's own framing of the project is that your data should truly belong to you, which makes the hosted demo the one place where that does not hold.

The annual report for 2025 is also hosted rather than generated locally, with a preview link to siyuan.ink/annual-report. That is a preview of the feature, not something a self-hosted instance produces for you, and the feature table's entry for it describes generating statistics for 2025 including a photo wall, cities visited, scenic spots, a trip timeline and route mileage.

The README says more than 90 percent of the code was written by AI

The acknowledgements section is unusually candid. It states that more than 90 percent of the code in this project was generated by AI, then lists the tools and what each was used for: TRAE, after a monthly plan turned into an annual one, which is also where the writing prompts are published; Claude Code, used for committing code and writing documentation; Doubao, described as talking nonsense but still offering useful suggestions; and ChatGPT, used to teach Doubao how to do AI work.

The same section names one comparable project, InkTime, a self hostable e ink photo frame that scores photos by how much they are worth remembering and shows the photo of the day. It is the only alternative the README points at.

The surrounding page has its share of gaps. The QQ group heading has no content under it, while the WeChat group heading has an image link. The Star History badge points at a URL that stops mid parameter, and the header is a stack of about nine anchor elements with nothing inside them, including one that is commented out and one marked as a download counter. Those are cosmetic, but they are the first thing a visitor sees, and the badge images are all missing.

Editorial conclusion

TrailSnap is a wide feature set for a self-hosted album, with the recognition and organisation work in place and the agent integration visible in the repository, but read its documentation as a mixture of two vintages. Check the boxes for yourself before planning around a feature, because the capability list, the feature table and the Todo List give three different answers for ticket recognition, the travel diary and MCP. For installation, pick the route that matches your appetite: the desktop package from Releases avoids the container stack entirely, while the one line script installs Docker and changes registry configuration before it deploys anything. Either way the database stays inside the compose network, the shared address is port 3180, and your photos are mounted from a host directory you have to point at yourself. If you intend to publish anything derived from this code, note that the repository is AGPL-3.0 and the agent bridge package declares AGPL-3.0-only.

Frequently asked questions

How do I install TrailSnap?

Three routes. A desktop installer for your platform from the Releases page, a one click script that runs curl -fsSL https://trailsnap.cn/install.sh | bash on Linux, macOS and WSL2 or the install.ps1 equivalent in PowerShell, or manual deployment where you provide a compose file and run docker-compose up -d. The README's compose example defines only the Postgres service.

Does TrailSnap need to expose the database port?

No. The server, the AI components and the database communicate only inside the Docker network, and the API is collected under /api by a gateway on the single TrailSnap address, given as http://192.168.1.10:3180. The Postgres service in the compose example opens no ports.

How does the TrailSnap mobile app find the server?

The Android app tries automatically and, when mDNS returns nothing, probes the default unified entry point on the LAN, so a bridge network deployment needs no multicast ports. Linux users can enable an optional host broadcast service with docker compose --profile lan-discovery up -d. Other platforms use the QR code generated from the connect phone app setting.

Which TrailSnap features are finished and which are not?

The feature table checks face recognition, scene classification, OCR, smart search, tags, cities, scenic spots, external folders, live photo, the annual report, AI analysis and the agent entry point, while marking the travel diary as to be developed. The bullet list separately marks ticket recognition as under development, and the Todo List still has MCP protocol support and the AI video and photo editing capabilities unticked.

Can TrailSnap be driven by Claude Code or OpenClaw?

The feature table marks a SKILL entry as done and describes support for connecting to platforms such as OpenClaw and Claude Code for automatic task execution. The repository has a skills directory and a private package manifest named trailsnap-pi-agent that wraps @modelcontextprotocol/sdk as a TypeScript extension. The MCP checkbox in the Todo List is still open.

Where does TrailSnap keep my photos?

External folders can be added as data sources and are scanned and indexed automatically, and the deployment note warns that the mount paths must be changed to your local directories or the local photo folders will not be scanned. Metadata and vectors go to Postgres with pgvector, configured with the trailsnap database and user credentials in the compose example.

Official sources

  1. LC044/TrailSnap on GitHub
  2. License: AGPL-3.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/lc044-trailsnap.svg)](https://hysenlabs.com/projects/lc044-trailsnap)