Fast C# Native AOT utility to create symbolic links from dotfiles to your home directory. Supports Windows, Linux, and macOS while respecting your dotfiles repository structure.
- Download the latest binary from the GitHub Releases page and place it in a directory that is in your PATH.
- Run executable file
DotfilesLinker
in your terminal.
# Safe mode, do not overwrite existing files
$ DotfilesLinker
# use --force=y to overwrite destination files
$ DotfilesLinker --force=y
DotfilesLinker creates symbolic links based on your dotfiles repository structure:
- Dotfiles in the root directory → linked to
$HOME
- Files in the
HOME
directory → linked to the corresponding path in$HOME
- Files in the
ROOT
directory → linked to the corresponding path in the root directory (/
) (Linux and macOS only)
Install DotfilesLinker using Scoop:
$ scoop bucket add guitarrapc https://github.com/guitarrapc/scoop-bucket.git
$ scoop install DotfilesLinker
Download the latest binary from the GitHub Releases page and place it in a directory that is in your PATH.
Available platforms:
- Windows (x64, ARM64)
- Linux (x64, ARM64)
- macOS (x64, ARM64)
git clone https://github.com/guitarrapc/DotfilesLinker.git
cd DotfilesLinker
dotnet publish -r win-x64 --artifacts-path ./artifacts
- Prepare your dotfiles repository structure as shown below.
Linux example
dotefiles
├─.bashrc_custom # link to $HOME/.bashrc_custom
├─.gitignore_global # link to $HOME/.gitignore_global
├─.gitconfig # link to $HOME/.gitconfig
├─aqua.yaml # non-dotfiles file automatically ignore
├─dotfiles_ignore # ignore list for dotfiles link
├─.github
│ └─workflows # automatically ignore
├─HOME
│ ├─.config
│ │ └─aquaproj-aqua
│ │ └─aqua.yaml # link to $HOME/.config/aquaproj-aqua/aqua.yaml
│ └─.ssh
│ └─config # link to $HOME/.ssh/config
└─ROOT
└─etc
└─profile.d
└─profile_foo.sh # link to /etc/profile.d/profile_foo.sh
Windows example
dotefiles
├─dotfiles_ignore # ignore list for dotfiles link
├─.gitignore_global # link to $HOME/.gitignore_global
├─.gitconfig # link to $HOME/.gitconfig
├─.textlintrc.json # link to $HOME/.textlintrc.json
├─.wslconfig # link to $HOME/.wslconfig
├─aqua.yaml # non-dotfiles file automatically ignore
├─.github
│ └─workflows # automatically ignore
└─HOME
├─.config
│ └─git
│ └─config # link to $HOME/.config/git/config
│ └─ignore # link to $HOME/.config/git/ignore
├─.ssh
│ ├─config # link to $HOME/.ssh/config
│ └─conf.d
│ └─github # link to $HOME/.ssh/conf.d/github
└─AppData
├─Local
│ └─Packages
│ └─Microsoft.WindowsTerminal_8wekyb3d8bbwe
│ └─LocalState
│ └─settings.json # link to $HOME/AppData/Local/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json
└─Roaming
└─Code
└─User
└─settings.json # link to $HOME/AppData/Roaming/Code/User/settings.json
- Run the DotfilesLinker command. The
--force=y
option is required to overwrite existing files.
$ DotfilesLinker --force=y
[o] Skipping already linked: C:\Users\guitarrapc\.textlintrc.json -> D:\github\guitarrapc\dotfiles-win\.textlintrc.json
[o] Skipping already linked: C:\Users\guitarrapc\.wslconfig -> D:\github\guitarrapc\dotfiles-win\.wslconfig
[o] Skipping already linked: C:\Users\guitarrapc\.ssh\config -> D:\github\guitarrapc\dotfiles-win\HOME\.ssh\config
[o] Skipping already linked: C:\Users\guitarrapc\.config\git\config -> D:\github\guitarrapc\dotfiles-win\HOME\.config\git\config
[o] Skipping already linked: C:\Users\guitarrapc\.config\git\ignore -> D:\github\guitarrapc\dotfiles-win\HOME\.config\git\ignore
[o] Skipping already linked: C:\Users\guitarrapc\.ssh\conf.d\aws.conf -> D:\github\guitarrapc\dotfiles-win\HOME\.ssh\conf.d\aws.conf
[o] Skipping already linked: C:\Users\guitarrapc\.ssh\conf.d\github.conf -> D:\github\guitarrapc\dotfiles-win\HOME\.ssh\conf.d\github.conf
[o] Skipping already linked: C:\Users\guitarrapc\Documents\PowerShell\Microsoft.PowerShell_profile.ps1 -> D:\github\guitarrapc\dotfiles-win\HOME\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
[o] Skipping already linked: C:\Users\guitarrapc\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 -> D:\github\guitarrapc\dotfiles-win\HOME\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
[o] Skipping already linked: C:\Users\guitarrapc\AppData\Roaming\Code\User\settings.json -> D:\github\guitarrapc\dotfiles-win\HOME\AppData\Roaming\Code\User\settings.json
[o] Skipping already linked: C:\Users\guitarrapc\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json -> D:\github\guitarrapc\dotfiles-win\HOME\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
[o] Skipping already linked: C:\Users\guitarrapc\Documents\Visual Studio 2022\Templates\ItemTemplates\CSharp\Code\1033\Class\Class.cs -> D:\github\guitarrapc\dotfiles-win\HOME\Documents\Visual Studio 2022\Templates\ItemTemplates\CSharp\Code\1033\Class\Class.cs
[o] Skipping already linked: C:\Users\guitarrapc\Documents\Visual Studio 2022\Templates\ItemTemplates\CSharp\Code\1033\Class\Class.vstemplate -> D:\github\guitarrapc\dotfiles-win\HOME\Documents\Visual Studio 2022\Templates\ItemTemplates\CSharp\Code\1033\Class\Class.vstemplate
[o] All operations completed.
You can also use the dry-run mode to see what would happen without making any changes:
$ DotfilesLinker --dry-run
DRY RUN MODE: No files will be actually linked
Starting to link dotfiles from /home/user/dotfiles to /home/user
Using ignore file: dotfiles_ignore
[o] [DRY-RUN] Would create file symlink: /home/user/.gitconfig -> /home/user/dotfiles/.gitconfig
[o] [DRY-RUN] Would create file symlink: /home/user/.config/git/config -> /home/user/dotfiles/HOME/.config/git/config
DRY RUN COMPLETED: No files were actually linked
Dry run completed successfully. No changes were made.
- Verify the symbolic links created by DotfilesLinker.
$ ls -la $HOME
HOME
drwxr-x--- 18 guitarrapc guitarrapc 4096 Apr 10 03:08 .
drwxr-xr-x 3 root root 4096 Mar 27 02:33 ..
-rw-r--r-- 1 guitarrapc guitarrapc 4015 Mar 27 02:38 .bashrc
lrwxrwxrwx 1 guitarrapc guitarrapc 64 Mar 27 02:38 .bashrc_custom -> /home/guitarrapc/github/guitarrapc/dotfiles/.bashrc_custom
lrwxrwxrwx 1 guitarrapc guitarrapc 60 Mar 27 02:38 .gitconfig -> /home/guitarrapc/github/guitarrapc/dotfiles/.gitconfig
lrwxrwxrwx 1 guitarrapc guitarrapc 67 Mar 27 02:38 .gitignore_global -> /home/guitarrapc/github/guitarrapc/dotfiles/.gitignore_global
drwxr-xr-x 2 guitarrapc guitarrapc 4096 Mar 27 02:38 .ssh
$ ls -la ~/.config/aquaproj-aqua/
total 12
drwxr-xr-x 2 guitarrapc guitarrapc 4096 Mar 27 02:38 .
drwxr-xr-x 5 guitarrapc guitarrapc 4096 Mar 27 18:31 ..
lrwxrwxrwx 1 guitarrapc guitarrapc 86 Mar 27 02:38 aqua.yaml -> /home/guitarrapc/github/guitarrapc/dotfiles/HOME/.config/aquaproj-aqua/aqua.yaml
$ ls -la ~/.ssh
total 12
drwxr-xr-x 2 guitarrapc guitarrapc 4096 Mar 27 02:38 .
drwxr-x--- 18 guitarrapc guitarrapc 4096 Apr 10 03:08 ..
lrwxrwxrwx 1 guitarrapc guitarrapc 66 Mar 27 02:38 config -> /home/guitarrapc/github/guitarrapc/dotfiles/HOME/.ssh/config
- Run the following command to see all available options:
DotfilesLinker --help
All options are optional. The default behavior is to create symbolic links for all dotfiles in the repository.
Option | Description |
---|---|
--help , -h |
Display help information |
--version |
Display version information |
--force=y |
Overwrite existing files or directories |
--verbose , -v |
Display detailed information during execution |
--dry-run , -d |
Simulate operations without making any changes to the filesystem |
DotfilesLinker can be configured using the following environment variables:
Variable | Description | Default |
---|---|---|
DOTFILES_ROOT |
Root directory of your dotfiles repository | Current directory |
DOTFILES_HOME |
User's home directory | User profile directory ($HOME ) |
DOTFILES_IGNORE_FILE |
Name of the ignore file | dotfiles_ignore |
Example usage with environment variables:
# Set custom dotfiles repository path
export DOTFILES_ROOT=/path/to/my/dotfiles
# Set custom home directory
export DOTFILES_HOME=/custom/home/path
# Run with custom settings
DotfilesLinker --force=y
You can specify files or directories to be excluded from linking in the dotfiles_ignore
file. DotfilesLinker supports several pattern types for flexible file exclusion:
# Example dotfiles_ignore
.git
.github
README.md
LICENSE
DotfilesLinker supports the following pattern types in the dotfiles_ignore
file:
# Simple filenames or paths that match exactly
.github
README.md
LICENSE
# Wildcard patterns
# `*` matches any string (excluding path separators)
# `?` matches any single character
*.log
temp*
backup.???
# Gitignore-style patterns
# A pattern containing `/` matches a specific path from the repository root
# `**` matches any number of directories (including zero)
# A pattern ending with `/` matches directories only
docs/build/
config/local_*.json
HOME/**.log
**/temp/
# Negation patterns
# A pattern starting with `!` explicitly includes files that would otherwise be ignored
# Processed after non-negated patterns
# --------------------------
# Patterns are processed in two stages:
# 1. First, all non-negation patterns are evaluated
# 2. Then, negation patterns (`!`) are applied and can override previous exclusions
## Exclude all .log files except important.log
*.log
!important.log
## Exclude everything in docs except README.md
docs/
!docs/README.md
The following files and directories are automatically excluded:
- Version control system folders (
.git
,.svn
,.hg
) - Non-dotfiles in the root directory
- OS-specific files like
.DS_Store
(macOS) andThumbs.db
(Windows) - Temporary files like
*.bak
,*.tmp
, and vim swap files
All release artifacts are digitally signed using Cosign to ensure their integrity and authenticity. This helps prevent security warnings from antivirus software like Windows Defender.
You can verify the signatures using the Cosign CLI:
# Download the public key (only needed once)
curl -O https://raw.githubusercontent.com/guitarrapc/DotfilesLinker/main/cosign.pub
# Verify an artifact (replace with the artifact you downloaded)
cosign verify-blob --key cosign.pub --signature DotfilesLinker_win_amd64.zip.sig DotfilesLinker_win_amd64.zip
A successful verification confirms the file was released officially and has not been tampered with.
Each release also includes:
- SBOM (Software Bill of Materials) files in SPDX format
- SHA256 checksums for all artifacts
This project is licensed under the MIT License - see the LICENSE file for details.