Declarative symlink manager
Inspired by mise dotfiles
Via Homebrew:
brew tap veerendra2/homebrew-tap
brew install symlinkrOr download from GitHub Releases
symlinkr - Declarative symlink manager
Usage:
symlinkr [flags]
Flags:
-c, --config <path> Config file path (default: symlinkr.yaml or symlinkr.yml)
-r Uninstall mode (remove all symlinks)
-f Force overwrite existing files
--dry-run Preview changes without executing
-v Show version information
Examples:
symlinkr # Apply config
symlinkr --dry-run # Preview changes
symlinkr -c ~/dotfiles.yaml # Custom config
symlinkr -f # Force overwrite
symlinkr -r # Uninstall
symlinkr -r --dry-run # Preview uninstallDefault configuration file is symlinkr.yaml in the current working directory, with symlinkr.yml as a fallback.
root_dir: "~/projects/dotfiles"
force_overwrite: false
symlinks:
- ~/.bashrc: bashrc
- ~/.gitconfig: gitconfig
- ~/.config/nvim: config/nvim
recursive: true| Field | Type | Required | Description |
|---|---|---|---|
root_dir |
string | Yes | Base directory containing source files. Supports ~ and $VAR / ${VAR}. |
force_overwrite |
boolean | No | Remove and overwrite non-symlink targets. Overridden by -f flag (default: false). |
symlinks |
list | Yes | List of destination: source mappings. Destination supports ~ and env vars; source is relative to root_dir. |
symlinks[].recursive |
boolean | No | When true, mirrors directory tree with individual file symlinks (default: false). |
Without recursive - Creates single directory symlink:
~/.config/nvim -> ~/dotfiles/config/nvim
With recursive: true - Creates directory structure with individual file symlinks:
~/.config/nvim/init.lua -> ~/dotfiles/config/nvim/init.lua
~/.config/nvim/lua/plugins.lua -> ~/dotfiles/config/nvim/lua/plugins.lua
symlinkr is a lightweight single binary, a good fit for managing dotfiles repositories.
You can drop the standalone binary and a symlinkr.yaml config directly into your dotfiles repository or install script:
dotfiles/
├── bin/
│ └── symlinkr
├── config/
│ └── nvim/
├── bashrc
├── gitconfig
└── symlinkr.yaml
Bootstrap a new machine with a single command:
./bin/symlinkr --config ./symlinkr.yaml- Stateless:
symlinkrdoes not store state or maintain a registry of created links. It evaluates the YAML config against the current filesystem. Removing an entry from your config will not automatically delete its existing symlink on-r. - No automatic backups: Existing regular files or directories at destination paths are skipped by default. Using
-forforce_overwrite: truepermanently removes them without creating.bakfiles. - Root confinement: Source paths must reside inside
root_dir. Any path attempting to escaperoot_dir(e.g.../file) is rejected.
Build and test using Taskfile:
task build # Build binary
task test # Run tests
task lint # Run linter