Lightweight git-native dotfiles management.
Track dotfiles across machines with one command. Lnk moves files into a Git repo (defaults to ~/.config/lnk; override with --repo flag or LNK_HOME / LNK_REPO), symlinks them back, and stays out of your way. Setup multiple host/scopes in addition to a common scope to separate work and personal settings.
lnk init # create a local repo
lnk clone git@github.com:you/dotfiles.git # clone a remote repo
lnk add ~/.vimrc ~/.bashrc ~/.gitconfig # track files
lnk add --host work ~/.ssh/config # per-machine config
lnk push # push to remote
lnk update # pull and restore symlinkscurl -sSL https://raw.githubusercontent.com/polymorcodeus/lnk/main/install.sh | bashOr grab a binary from releases, or build from source:
go install github.com/polymorcodeus/lnk@latestNOTE:
Installing with Homebrew is not yet supported.
-
Initialize on a new machine:
lnk clone git@github.com:you/dotfiles.git --bootstrap lnk update lnk update --host $(hostname)That's it. Bootstrap runs automatically (with flag), symlinks get restored, you're working.
-
Add dotfiles on your daily machine:
lnk add ~/.vimrc ~/.bashrc ~/.gitconfig
-
Sync changes:
lnk push
Before: ~/.vimrc (regular file)
After: ~/.vimrc → ~/.config/lnk/.vimrc (symlink into git repo)Common files live at the repo root (v1) or under common.lnk/ (v2). Host-specific files go in <hostname>.lnk/ subdirectories. A plain text .lnk file tracks what's managed — one path per line, no special format.
~/.config/lnk/
├── .lnkrepo # version marker (v2)
├── .lnk.common # tracked common files (v2)
├── .lnk.work # tracked work-specific files
├── common.lnk/ # v2: common storage directory
│ ├── .vimrc
│ └── .gitconfig
└── work.lnk/ # host-specific storage
└── .ssh/config~/.config/lnk/
├── .lnk # tracked common files (v1)
├── .lnk.work # tracked work-specific files
├── .vimrc # v1: common files and directories in repo root.
├── .gitconfig
├── .config/
│ └── ghostty
└── work.lnk/ # host-specific storage
└── .ssh/configlnk add ~/.vimrc ~/.bashrc # multiple at once
lnk add --host laptop ~/.ssh/config # host-specificlnk move ~/.ssh/config --to-common # move to common scope
lnk move ~/.vimrc --to-host work # move to host scopelnk status # full git status output
lnk status --color # colorized git status
lnk diff # uncommitted changes
lnk diff --color # colorized diff
lnk commit -m "updated vim config" # stage and commit - not needed after `lnk add`
lnk commit # commit with default message - not needed after `lnk add`
lnk push # push existing commits
lnk pull # pull repo changes
lnk restore # restore symlinks (no pull)
lnk update # pull + restore symlinks
lnk update --host work # include host-specific files
lnk restore --dry-run # preview what would be restoredstatus shows the full git status output. If no remote is configured, it prints Remote not set at the top. Use --color to enable colorized output (default is plain text).
lnk remove ~/.vimrc # stop managing, restore file locally
lnk forget ~/.bashrc # stop tracking, keep stored repo copyremove restores the file to its original location and removes it from the repo. forget keeps the stored copy in the repo but removes the symlink and tracking entry — useful for temporarily stopping management of a path.
lnk list # common files
lnk list --host work # host-specific
lnk list --all # all scopeslnk doctor # audit repo and profile health
lnk doctor --fix # apply safe automatic fixes
lnk doctor --fix --prune-empty # also remove empty host scopes
lnk doctor --all # check all scopesWhen restoring symlinks, if a real file exists at the target location (not a symlink), it will be renamed to <path>.lnk-backup to preserve your data before the symlink is created. Check for .lnk-backup files after running restore, update, or doctor if you expect them.
lnk format # show current repo format
lnk format --v2 # migrate to v2 format, i.e. common files under lnk.common
lnk format --v1 # migrate back to v1 formatv2 aggregates common dotfiles under common.lnk/ for cleaner repo organization. New repos are initialized as v2 by default. After the format, run a lnk doctor --fix as all your common symlinks will be broken.
Drop a bootstrap.sh in your dotfiles repo. Lnk runs it automatically on lnk clone <url> --bootstrap.
lnk clone <url> # clones repo locally, no bootstrap.sh
lnk clone <url> --bootstrap # runs bootstrap.sh after clone
lnk bootstrap # run manually| Command | What it does |
|---|---|
init |
Create or adopt a local lnk repo |
clone <url> [--bootstrap] |
Clone a remote lnk repo |
add [--host H] <path...> |
Track files (move to repo + symlink) |
move <path> (--to-common | --to-host H) |
Move a tracked path between scopes |
remove [--host H] <path> |
Stop managing, restore file locally |
forget [--host H] <path> |
Stop tracking, keep stored repo copy |
list [--host H | --all] |
Show tracked files by scope |
status [--color] |
Show full git status output |
diff [--color] |
Show uncommitted changes |
commit [-m message] |
Stage all changes and commit |
push |
Push existing commits |
pull |
Pull repo changes |
restore [--host H] [--dry-run] |
Restore symlinks without pulling |
update [--host H] |
Pull and restore the effective profile |
doctor [--host H | --all] [--fix] [--prune-empty] |
Audit and fix repo health |
format [--v1 | --v2] |
Migrate repo format |
bootstrap |
Run bootstrap.sh explicitly |
Available with all commands:
| Option | Default | What it does |
|---|---|---|
--repo <path> |
~/.config/lnk |
Path to the lnk repository |
This originally started off as a fork of yarlson/lnk with a number of features that I wanted. It has since turned into a standalone version after I saw the plan to rewrite a v2 in Rust. I've cleaned up the legacy code and added some opinionated fixes along the way. This should™ be fully compatible with the original repos from yarlson's tool, but now stands alone. I can't guarantee backwards or cross compatibility going forward so use both at your own peril.
git clone https://github.com/polymorcodeus/lnk.git
cd lnk
make check # fmt, vet, lint, test