TagStudio: where to get it, and how its SQLite library works
A User-Focused Photo & File Management System
At a glance
- What is it?
- TagStudio organizes photos and files with tags stored in a SQLite database inside a .TagStudio folder, leaving your files exactly where they are. The mechanism is unusual and the tradeoffs are specific: Alpha-tagged releases, Python 3.14 only for source builds, and field names that are not yours to choose yet.
- Who is it for?
- Adopt TagStudio if you want multi-value tags over a folder tree you cannot reorganize, and accept that every release is labelled Alpha and that a source build needs Python 3.14. Skip it if you need custom field names today, a thumbnail for every format, or automatic rescanning above 10,000 files.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- 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 November 14, 2026, and from our analysis. They are not legal advice.
Star history
- TagStudioDev/TagStudio7,294 ★ · +87
| Repository | 2026-09-23 | 2026-11-14 |
|---|---|---|
| TagStudioDev/TagStudio | 7.2k | 7.3k |
87 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
A library is a SQLite index inside a .TagStudio folder, not a new folder tree
TagStudio never reorganizes the folders you already have. Point it at a directory and it creates a `.TagStudio` folder there, holding a SQLite database with every file entry, its tags and the rest of the library data. The files themselves are not moved, and no sidecar files appear next to your images. The README compares the arrangement to Obsidian vaults: a layer over existing structure rather than a container you import into. The usual description of an Obsidian vault is a folder of notes you edit in place, with metadata sitting inside those notes. TagStudio draws the line differently, keeping an index in one database file and leaving the bytes of every file alone.
That choice buys you two things. Any other program that reads the folder still works, and moving the folder somewhere else moves the library with it. It also creates one thing to protect. Because nothing is written next to the files, copy the photos to a new machine without the `.TagStudio` folder and the tags stay behind. Treat it as the one file in your photo directory that cannot be regenerated.
Python 3.14 and an exact PySide6 pin decide whether a source build happens
The packaging metadata is blunt about the toolchain. `pyproject.toml` declares the build backend as hatchling, the supported interpreter range as `>=3.14,<3.15`, and the GUI toolkit as an exact pin:
requires-python = ">=3.14,<3.15"
[project.gui-scripts]
tagstudio = "tagstudio.__main__:main"That entry point is what a source install gives you: a `tagstudio` command that starts the application. Pillow is ranged as `>=10.2,<12` while PySide6 is fixed to `6.11.2`, so a Qt change arrives when the project bumps the pin rather than drifting in from the package index.
For people who do not want to build, the README sends readers to the documentation site and the project's releases, where binaries are published under the Alpha label. v9.6.4 shipped on 2026-10-02, v9.6.3 on 2026-08-15 and v9.6.2 on 2026-08-07, so the cadence is a release every few weeks, each one named Alpha.
Tag names are not unique, and parent tags stand in during a search
A tag is a small record rather than a line of text. The attributes are Name, Shorthand Name, Aliases, Color, Parent Tags and Is Category. The Name field explicitly does not have to be unique, which is the design decision that separates this from a plain string tag system.
Parent tags create inheritance at query time. A tag can be substituted in searches for any parent it lists, so a photo tagged "Freddy Fazbear" turns up in a search for "Five Nights at Freddy's". Duplicate names are handled by a disambiguation checkbox beside each parent. Check it and the display becomes "Freddy Fazbear (Five Nights at Freddy's)", or "Freddy Fazbear (FNAF)" when the parent carries the shorthand.
The consequence lands on whoever builds the vocabulary. Two tags named "Berlin" from different folders are legal, and if you skip the disambiguation box they show identically. Decide the naming rules before importing a large collection, not after.
Path search runs on glob syntax, so a bare filename returns nothing
Search goes beyond tag names. You can query by `path:`, by `filetype:` and by `mediatype:`, and combine terms with the boolean operators `AND`, `OR` and `NOT`, parenthesised groups, quotation escaping and automatic substitution of underscores.
The path part is the trap. Path searches use glob syntax, and the README states you may need to wrap a filename or filepath in asterisks while searching, adding that this will not be strictly necessary in future versions. A query for a name without the wildcards may match nothing, and the empty result looks identical to a file that does not exist. If a search surprises you, add the asterisks before you go looking for missing files.
Two special conditions do the housekeeping work. `special:untagged` returns entries with no tags and `special:empty` returns entries with no fields, which is how you find what a scan brought in that nobody has described yet.
Above 10,000 files, libraries stop scanning themselves when you open them
Automatic scanning has a size threshold written into the README: libraries under 10,000 files scan for new or modified files when they are opened. Above that number, opening the library does not do it. You refresh by hand with "Refresh Directories" under the File menu, or with Ctrl+R, or with Command+R on macOS.
For a photo library that grows past it, the failure is quiet. Another tool drops files into the folder, TagStudio shows the old set on launch, and the new arrivals stay invisible until someone presses the shortcut. `special:untagged` then reports a backlog that grows on its own.
Tag creation has the same keyboard shape: Ctrl+T, or Command+T on macOS, opens the panel for a name, an optional shorthand, optional aliases, optional parent tags and an optional color. The Tag Manager sits behind Ctrl+M, or Command+M, and it is where tags get searched, edited and permanently deleted. Permanent is the operative word there.
Preview coverage is narrower than file coverage, and the dependency list shows why
All file types are supported inside a library, and not all of them have a dedicated preview. The documentation site holds the preview support page, and playback exists for videos, audio files and supported animated image formats. The generalized list covers raster images such as JPEG and PNG, vector SVG, animated GIF, WEBP and APNG, RAW formats, videos, plaintext, documents and eBooks where supported, plus Photoshop PSDs, Blender Projects and Krita Projects.
The dependency list in `pyproject.toml` explains what each format costs. `pillow-heif~=1.5.0` and `pillow-jxl-plugin~=1.3` cover HEIF and JPEG XL, `rawpy~=0.27` handles RAW, and `ffmpeg-python~=0.2` with `pydub~=0.25`, `mutagen~=1.47` and `audioop-lts~=0.2.2` covers video and audio work, alongside `opencv_python~=4.11` and `numpy~=2.2`.
An entry can therefore sit in your library with no thumbnail at all. Check the support page for the formats you actually own before you import years of photographs.
Fields are locked to hardcoded names until a planned update lands
Fields are the second metadata layer, attached to individual file entries rather than to groups of them. Right now they carry several hardcoded names, with Title, Author and Series given as examples, and custom field names are described as planned for an upcoming update. The field types on offer are Text Lines for single lines of text, Text Boxes for multi-line text and Datetimes for dates and times.
That list is the limitation. There is no numeric type, no choice list, and no field of your own naming, so a star rating, a print size or a purchase date has nowhere to go except inside a text box. Tags carry the structure of your library; fields carry a fixed set of descriptions until the custom names arrive, and the README gives no version or date for that change.
If your workflow depends on a field called something specific, plan for it not to exist. Model the distinction with parent tags and aliases, both of which you control today.
Every release carries the Alpha label, and the README screenshot lags behind it
Maintenance signals are consistent. The last push to the main branch landed on 2026-11-01, a month after v9.6.4 was published on 2026-10-02, and the three releases listed span August and October 2026. None of them drops the Alpha suffix that the release names use, and the screenshot caption in the README still reads "TagStudio Alpha v9.5.5 running on macOS Sequoia" while the current version is 9.6.4.
The project is GPL-3.0-only, with a `LICENSES/` directory and a `REUSE.toml` at the top level, and translations run through Weblate rather than through a hand-edited locale file. The repository keeps `src/`, `tests/`, `scripts/`, `docs/`, a `nix/` directory with `flake.nix` and `flake.lock`, an `overrides/` directory, `contrib/` and `CHANGELOG.md`.
Contributor tooling is declared as dependency groups: lint runs pyright, reuse and ruff, test pins pytest at 9.0.3, build pulls in `Pyinstaller~=6.21`, docs pins `mkdocs-redirects~=1.2` alongside `properdocs`, and extra carries `pre-commit~=4.2`. An Alpha label with a release every few weeks and a contributor toolchain this complete describes a project that moves fast and tells you so in the version name.
Editorial conclusion
Adopt TagStudio if you want multi-value tags over a folder tree you cannot reorganize, and accept that every release is labelled Alpha and that a source build needs Python 3.14. Skip it if you need custom field names today, a thumbnail for every format, or automatic rescanning above 10,000 files. Verify first: point a library at a real folder, run special:untagged right after the first scan to see what arrived untagged, and check the preview support page for your formats before moving anything.
Frequently asked questions
Is TagStudio safe for my existing photo folder?
Creating a library scans the folder you choose and records what it finds in a SQLite database inside a `.TagStudio` folder, and the README states that no files are moved during the process. Nothing is written next to your images, so the database is the only artifact to back up.
What does TagStudio do when it scans a library for the first time?
It creates the `.TagStudio` folder in the directory you selected, stores entries, tags and library data in a SQLite database there, and adds the files it finds without moving them. Libraries under 10,000 files also rescan for new or modified files each time they are opened.
Can TagStudio search by file path or file type?
Yes. Search accepts `path:`, `filetype:` and `mediatype:` terms with boolean operators, but path searches use glob syntax, so a filename often needs to be wrapped in asterisks. `special:untagged` and `special:empty` find entries with no tags or no fields.
Does TagStudio show a preview for every file type?
No. All file types are supported in a library, but not all have dedicated preview support, and the documentation site keeps the list of formats that do. Playback is available for videos, audio files and supported animated image formats.
Can I name my own fields in TagStudio?
Not yet. Fields currently use hardcoded names such as Title, Author and Series, and custom field names are described as planned for an upcoming update. The field types available now are Text Lines, Text Boxes and Datetimes.
Official sources
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.
[](https://hysenlabs.com/projects/tagstudiodev-tagstudio)Star history chart for your README
[](https://hysenlabs.com/projects/tagstudiodev-tagstudio)Was this useful?