An XDG-centric GNU stow replacement for managing dotfiles, written in Rust.
- Smart symlinking of dotfiles from a
.config/directory toXDG_CONFIG_HOME(or$HOME/.config) - Support for
.stowignorefiles using gitignore-style patterns - Easy removal of stowed packages with the
--rmflag - Safe operation - verifies symlinks before removal
Install from crates.io:
cargo install xdg-config-stowOr build from source:
cargo build --release
# Binary will be in target/release/xdg-config-stowRun xdg-config-stow from your dotfiles repository root (the directory containing .config/).
Link all files from .config/fish to $HOME/.config/fish:
xdg-config-stow fishRemove symlinks for a previously stowed package:
xdg-config-stow --rm fishPreview what changes would be made without actually making them. Output uses colored diff-like syntax with + for additions and - for removals:
# See what would be stowed
xdg-config-stow --dry-run fish
# Output:
# DRY RUN: No changes will be made
#
# + config.fish -> /path/to/dotfiles/.config/fish/config.fish
# + functions/ -> /path/to/dotfiles/.config/fish/functions
# See what would be removed
xdg-config-stow --rm --dry-run fish
# Output:
# DRY RUN: No changes will be made
#
# - config.fish
# - functions/Create a .stowignore file inside your package directory (e.g., .config/fish/.stowignore) using gitignore syntax:
# Ignore completions directory
completions/
# Ignore specific files
fish_variablesNote: If you add a .stowignore file after initially stowing a package, simply re-run the stow command to automatically update the symlinks:
xdg-config-stow fish # Automatically migrates and respects new ignore rulesmy-dotfiles-repo/
.config/
fish/
config.fish
functions/
.stowignore
nvim/
init.lua
lua/
README.md
setup.sh
- Detects the
.config/directory in your current working directory - Resolves the target directory using
XDG_CONFIG_HOMEor falls back to$HOME/.config - Creates symlinks for all files in the specified package
- Respects
.stowignorefiles for excluding specific paths - Safely verifies symlink targets when removing packages
- Rust 1.85 or later (for building)
- Unix-like operating system (Linux, macOS, BSD)
- Write access to
XDG_CONFIG_HOMEor$HOME/.config
The project includes comprehensive unit and integration tests:
# Run all tests
cargo test
# Run with output
cargo test -- --nocapture
# Run specific test
cargo test test_stow_single_fileSee TESTS.md for detailed test coverage information.
- 23 total tests covering:
- Core stowing/unstowing functionality
- .stowignore pattern matching
- Error handling and edge cases
- XDG_CONFIG_HOME resolution
- Complex directory structures
- Automatic migration safety (6 dedicated safety tests)
Contributions are welcome! Before submitting a pull request:
- Ensure your code is properly formatted:
cargo fmt - Check for linting issues:
cargo clippy -- -D warnings - Run all tests:
cargo test
To automatically run these checks before every commit, you can set up git hooks:
./scripts/setup-hooks.shThis will install a pre-commit hook that runs formatting checks, clippy, and tests before allowing commits. You can bypass the hook when needed with git commit --no-verify.
MIT