English | 简体中文
FileTrail is a file synchronization tool with Git version control. It watches the files and directories you choose, syncs changes into a local Git repository, and lets you review and commit them on your terms.
Use it for dotfiles, scripts, notes, or other files spread across your machine.
Keep separate macOS and Linux configurations in the same repository. Everything
runs from a single executable. Built-in synchronization and version-control commands
need no separate Git installation; the optional filetrail git passthrough uses system Git.
Run the following from the project directory:
cargo install --path . --locked
filetrail --helpTo install FileTrail and enable Tab completion in one step:
./install.shThe script detects Bash, Zsh, or Fish from $SHELL. You can select one explicitly
with ./install.sh zsh. It installs with Cargo, then configures that shell's
completion. Open a new shell afterward. The installation root defaults to
${CARGO_HOME:-$HOME/.cargo}; set CARGO_INSTALL_ROOT to override it.
The FileTrail skill teaches an agent what FileTrail does and how to use its commands, including restoration. To install it, simply send Codex this message:
Please install this Skill: https://github.com/RinChanNOWWW/FileTrail/tree/master/skills/filetrail
You can also run Codex's GitHub skill installer manually:
python3 "${CODEX_HOME:-$HOME/.codex}/skills/.system/skill-installer/scripts/install-skill-from-github.py" \
--repo RinChanNOWWW/FileTrail --ref master --path skills/filetrailIf the skill is on another branch or tag, replace master with that ref.
The skill installs as filetrail; invoke it with $filetrail in a supporting
agent environment. It provides instructions only: the agent still needs access
to the FileTrail executable and the files on the machine being managed.
If you installed FileTrail with cargo install, enable completion with:
filetrail completions --installThis detects your shell from $SHELL. To select a shell explicitly:
filetrail completions zsh --install
filetrail completions bash --install
filetrail completions fish --installRun the command for the shell you use, then open a new shell. Tab completes
subcommands (including daemon and service actions), options, and file paths.
For example, try filetrail da<Tab>, filetrail daemon st<Tab>, or
filetrail add --f<Tab>. This also enables filetrail cd to change the current
shell's directory to the target repository.
Installation preserves existing shell configuration and is safe to repeat. It
uses .zshrc (respecting ZDOTDIR), .bashrc and Bash's active login profile,
or Fish's completion and function directories (respecting XDG_CONFIG_HOME). Home paths use
$HOME in the installed hooks and command output, so your username is not embedded.
Paths outside Home retain their absolute location. Completion stays
in sync when you upgrade the executable at the same location. Run installation
again if you move it. To remove completion, delete the marked FileTrail block
from the configured files printed by the install command.
To print a completion script for manual setup, omit --install:
filetrail completions zshfiletrail init ~/dotfiles --subdir macos
filetrail add ~/.zshrc
filetrail add ~/.config/nvim
filetrail daemon startOn Linux, use --subdir linux. Omit --subdir to save at the repository root.
FileTrail creates the destination and initializes Git if needed. Adding a source
immediately copies its existing files; the daemon keeps subsequent changes in sync.
Sources inside Home are stored under __HOME__, preserving their Home-relative
paths. All other sources are stored under __ROOT__, preserving their absolute
hierarchy without the leading /. These directories sit inside the subdirectory
selected during init, or directly at the repository root when it is omitted.
| Source | Subdirectory | File in the repository |
|---|---|---|
~/.zshrc |
macos |
macos/__HOME__/.zshrc |
~/.config/nvim |
linux |
linux/__HOME__/.config/nvim/init.lua |
/opt/scripts/build.sh |
macos |
macos/__ROOT__/opt/scripts/build.sh |
/opt/scripts |
Omitted | __ROOT__/opt/scripts/build.sh |
For restoration, __HOME__ refers to the current user's Home and __ROOT__ to /.
Custom target paths are not supported: preserving source paths makes the original
location unambiguous. __HOME__ and __ROOT__ are reserved and cannot be used as
components of --subdir.
filetrail add /opt/scripts
filetrail add ~/notes --exclude '**/*.tmp'Directories are watched recursively. Exclusions are relative to the source root. Relative source paths are resolved from your current directory; parent-directory symlinks are resolved to their actual locations. Sources, destinations, and the application data directory must not overlap.
Select an existing FileTrail repository with init on a new machine, then restore:
filetrail init ~/dotfiles --subdir macos # Only for a profile not yet initialized
filetrail restore --dry-run
filetrail restore
filetrail restore macos/__HOME__/.zshrc macos/__HOME__/.config/nvim
filetrail restore --track macos/__HOME__/.zshrc
filetrail restore --overwrite macos/__HOME__/.zshrcPaths are relative to the repository root, including the configured subdirectory.
Supply multiple files or directories; directories are copied recursively and overlapping
selections are copied once. With no paths, restore all files under the current
subdirectory's __HOME__ and __ROOT__. Other subdirectories and repository files
such as READMEs are not restored. __HOME__ maps to the current user's Home;
__ROOT__ maps to / and requires write access at the original absolute locations.
The repository's current working files are used, including uncommitted files.
By default, this only copies files and leaves management unchanged. Identical files
are left alone; different local contents, file types, or permissions require
--overwrite. Local directories are never replaced by files or links. Files absent
from the repository are not deleted. File permissions and symlinks are preserved;
symlink targets are not copied or rewritten. Restore refuses symlink ancestors,
paths into the repository or application data directory, and .git paths.
Nested .git entries are skipped.
--track also adds each restored file or symlink to management with deletion disabled,
so extra local files in the same directory do not become managed. Compatible existing
mappings retain their settings; disabled or excluded mappings must be adjusted before
using --track. Files encoded under __ROOT__ that now belong inside Home can be
copied, but must use the __HOME__ layout to be tracked. Empty directories are created
but are not added as management entries. Afterward, ordinary synchronization flows
from this system back to the repository; restore does not start the daemon or commit.
--dry-run previews copying and optional management changes without applying them.
All selections and conflicts are checked before copying. An I/O error during execution
can leave some files restored; fix the error and rerun the command.
To switch repositories while keeping your sources, exclusions, and deletion settings:
filetrail retarget ~/new-dotfiles
filetrail retarget ~/new-dotfiles --subdir linux
filetrail retarget ~/new-dotfiles --subdir . # Save at the repository rootOmitting --subdir keeps the current subdirectory. You can also change just the
subdirectory by specifying the current repository. FileTrail creates the repository
if needed and immediately syncs enabled sources to the new location. The daemon
continues using the new target and retains its paused/running status.
The old files and Git history remain where they are; they are not moved or deleted.
Different content already present at the new destination is reported as a conflict
and kept for you to resolve. The target has changed even if this initial sync reports
conflicts; use conflicts and resolve against the new repository.
To stop using a profile or initialize it again from scratch:
filetrail deinit
filetrail init ~/another-repository --subdir macosdeinit stops the daemon, uninstalls its registered startup service, and clears
this profile's configuration and synchronization records. It preserves source files,
repositories, Git history, logs, and shell completion. You can run it again safely.
After reinitializing, add your sources and start the daemon or install the service again.
Use the same --data-dir if you selected a custom profile.
filetrail add --from ./files.txtWrite one source per line. Use single or double quotes around paths containing spaces. A second column for a custom target is not supported.
# source
~/.zshrc
~/.config/nvim
/opt/scripts
"~/My Notes"
'./local scripts'
Relative source paths are resolved from the list's directory. Blank lines and
# comments are allowed. Use ~ for HOME; environment variables and commands in
the list are not expanded or executed. The whole list is checked before any entries
are added. Editing it later does not update previously imported entries.
filetrail list
filetrail disable 1
filetrail enable 1
filetrail remove 1
filetrail sync
filetrail sync --dry-runUse IDs from list. remove stops tracking a source and keeps its destination
files. sync copies current changes immediately; --dry-run previews them.
Source deletions are retained at the destination by default. Enable deletion propagation when adding a source:
filetrail add ~/scripts --deleteOnly previously synchronized files can be deleted. If an entire source directory
becomes unavailable, FileTrail keeps its destination files. Symlinks are copied as
links, not followed; Git does not track empty directories. .git is always excluded,
and destination Git ignore rules apply when committing.
filetrail status
filetrail diff
filetrail diff -- macos/__HOME__/.config/nvim
filetrail commit
filetrail commit -m 'Update shell configuration'
filetrail commit -- macos/__HOME__/.zshrcThe daemon never commits or pushes automatically. diff includes new file contents.
commit includes only managed files and refuses to proceed if other changes are
already staged. Set your Git name and email before your first commit.
Without -m, FileTrail generates a message listing the selected changes:
FileTrail: sync 3 files (+1 ~1 -1)
add "macos/__HOME__/.config/nvim/init.lua"
delete "macos/__HOME__/.oldrc"
modify "macos/__HOME__/.zshrc"
To keep the destination stable while reviewing:
filetrail pause
filetrail diff
filetrail commit
filetrail resumeresume catches up with changes made while paused. Explicit sync and add
commands still copy files while automatic synchronization is paused. Paths passed
to diff, commit, and resolve are relative to the repository root.
With Bash, Zsh, or Fish integration installed, jump to the target repository:
filetrail completions --install # Also run once when upgrading to enable directory jumping
# Open a new shell, then:
filetrail cdThis changes the current shell's directory to the repository root, even when a
--subdir is configured. Without shell integration, the executable prints the path;
in Bash or Zsh you can use cd "$(command filetrail cd)". Use command filetrail cd
to print the path when integration is loaded, or add --print0 for NUL-terminated output.
Run any system Git command in the target repository without changing directories:
filetrail git status
filetrail git log --oneline -10
filetrail git push origin master
filetrail --data-dir ~/filetrail-work git push origin masterThis requires git on PATH and uses its normal configuration, credentials, and hooks.
Put FileTrail's --data-dir before git; Git arguments, input/output, and exit codes
are passed through. Synchronization waits while the Git command runs. No automatic
sync, staging, or commit is added. filetrail git commit follows normal Git staging
and can include any staged file; filetrail commit remains limited to managed changes.
FileTrail reports a conflict if a destination differs from an existing source on first sync, or if you modify the destination outside FileTrail. To explicitly use the source version:
filetrail conflicts
filetrail resolve macos/__HOME__/.zshrc --use-sourceYou can also make both copies identical yourself and run filetrail sync again.
Finish any Git merge/rebase or unresolved Git conflicts before resuming synchronization.
filetrail daemon start
filetrail daemon status
filetrail daemon restart
filetrail daemon stop
filetrail daemon run # Foreground mode
filetrail daemon start --poll # Use periodic scans instead of filesystem eventsFor automatic startup at login, install a user service after placing the executable in a stable location:
filetrail service show
filetrail service install
filetrail service uninstallmacOS uses launchd and Linux uses systemd user services. Once installed, use
service uninstall to stop the service and prevent automatic restarts.
FileTrail stores its application data in $HOME/.filetrail on both platforms.
Your synchronized files and Git history live in the repository chosen during init.
To use a different data directory, pass the same --data-dir to each command:
filetrail --data-dir ~/filetrail-work init ~/work-dotfiles --subdir macos
filetrail --data-dir ~/filetrail-work daemon startUse one data directory per repository. To inspect problems or discover more options:
filetrail doctor
filetrail logs --follow
filetrail --help
filetrail add --helpFor development instructions, see AGENTS.md.