StagFS (Simple Tagger) is a FUSE-based filesystem that upgrades your filesystem to support a tag-based structure. It turns tags into folders and remains compatible with a standard Unix utilities and file managers.
Key features are:
- Tags are Folder: Each tag corresponds to a folder in your filesystem, which stack recursively for files with multiple tags.
- Files are Files: Each file that you tag will show up in one or more folders, integrating seamlessly with any file manager.
- Same Tools as Usual: Browse and manage your files the same way you would before, using your favorite file manager or the CLI.
StagFS is fully functional, but it's still in alpha, so things might change a bit before the first full release. Once everything settles down, I'll start putting out official versions.
Before running StagFS, ensure you have the following dependencies installed
- FUSE
- Python 3 (version 3.6 or newer recommended)
- Click (Python package for command-line interfaces)
- fusepy (Python bindings for FUSE)
StagFS is distributed as a standalone Python script that you can easily download with
$ wget https://github.com/jpmvferreira/stagfs/raw/refs/heads/master/stagfs
make it executable
$ chmod +x stagfs
and move it to a directory in your $PATH
, e.g.
$ mv stagfs ~/usr/bin/stagfs
To run StagFS in the background with Systemd, download the provided unit file and place it in your user systemd directory
$ wget https://github.com/jpmvferreira/stagfs/raw/refs/heads/master/[email protected] -O ~/.config/systemd/user/[email protected]
$ systemctl --user daemon-reload
To get started with StagFS, begin by creating a new repository. For example, to create a repository called myrepo
$ stagfs init myrepo
Note
StagFS assumes the repository is located in ~/.local/share/stagfs
by default. This can be overwritten using the flag -r
.
You can list all repositories at any time with
$ stagfs ls
StagFS works by mounting your repository as a virtual filesystem. To do this, create a mount point and mount your repository
$ mkdir mnt
$ stagfs mount myrepo mnt
$ cd mnt
Tip
If you use the Systemd unit file, you can mount a repository in the background with:
systemctl --user start stagfs@<repository name>:<mount point>
Systemd will warn you about using /
, to avoid issues, replace all /
with -
, e.g.:
systemctl --user enable now stagfs@wallpapers:-home-user-wallpapers-
Add files to your repository as you would in any directory, by copying or moving them into the mount point. For demonstration purposes, let's create the following files
$ touch lisbon.txt bern.txt venice.txt
In StagFS, tags are directories. To create tags such as city
, mountains
, and ocean
$ mkdir city ocean mountains
To add a tag to a file, use the ln
command. For example, to tag lisbon.txt
and venice.txt
with city
$ ln lisbon.txt city
$ ln venice.txt city
You can add multiple tags at once, for instance, to tag bern.txt
with both city
and mountains
$ ln bern.txt city/mountains
If you wish to remove a tag from a file, use rm
with the path to the file inside the tag directory
$ rm city/bern.txt
this will remove the tag city
from ``bern.txt`, leaving other tags untouched.
It's possible to remove multiple tags at once, e.g., both city
and mountains
from bern.txt
with
$ rm city/mountains/bern.txt
To remove a file entirely from the repository, delete it from the root of the mount point
$ rm bern.txt
To remove a tag from the repository:
$ rmdir mountains
Caution
Do not use rm -r
to remove tags, as it will attempt to delete all files within the tag. Always use rmdir
to safely remove tags.
It is possible to manage both tags and files using mv
. For instance
$ mv <old_tags>/file.txt <new_tags>/file.txt
will remove all tags from file.txt
, disregarding <old_tags>
, and add <new_tags>
.
If you want to rename a file, you must call mv
within the same path and change the file name, i.e.
$ mv <tags>/file.txt <tags>/newname.txt
For renaming tags, you can run
$ mv <tags>/<tag> <tags_alt>/<tag_new>
where <tags>
and <tags_alt>
are ignored and <tag>
will be renamed to <tag_new>
. If <tag_new>
already exists, they will be merged.
Note
To avoid ghost overwrites, StagFS does not allow you to change the name of a file to one that already exists. As for tags, it will refuse to change the name to a tag that is not visible in the current subdirectory to avoid ghost merges.
Ever you ever started doing some spring cleaning and realized that
$ find wallpapers -type f | wc -l
1603
and, as if this is not bad enough already, you stumbled across
$ find memes -type f | wc -l
1377
Yeah... But, you know what could help you sort all of this mess? That's right: stop hoarding Tags! So I just need to find a program that:
- Tags file(s);
- Integrates with the filesystem to browse the files and tags;
- Uses terminal utilities to interact with files and tags.
As far as I know, there is only one project that comes close to this: TMSU. However, I don't like the folder structure, the CLI is quite complicated and the interaction via filesystem is lacking. It also does more than what I want it to.
Therefore, I decided to make my own version of TMSU, with blackjack smaller codebase and hookers better filesystem integration.
This is a small program developed by somebody who is not an experienced programmer. If you have any comments, feedback, suggestions or even feature requests, feel free to open a ticket or a discussion in this repository.
If you'd like to contribute code, first open up an issue with your proposed changes. All of the code (filesystem and CLI) are implemented in the stagfs Python script. To modify this program you need basic understanding of Python, FUSE, and SQL.
StagFS is a personal project, not enterprise grade software. I use it myself and it works well for me, but bugs can happen, so don’t trust it with important files unless you’ve got backups (which you should have anyways!). StagFS repositories are kept in a single folder, so backing up is very straight forward.
The fusepy Github repository, in particular the Python object FUSE implemented in fuse.py
.
The official libfuse documentation, mainly the file that defines the operations available in a FUSE filesystem (Data Structures > fuse_operations).