,.
(\(\)
,_ ; o >
{`-. / (_)
`={\`-._____/` |
`-{ / -=`\ |
`={ -= = _/ /
`\ .-' /` _ __ ___ ___ ___| |_
{`-,__.'= | '__/ _ \ / _ \/ __| __|
|| | | | (_) | (_) \__ \ |_
| \ |_| \___/ \___/|___/\__|
--------/\/\---------------------------------------------
roost — TUI-first dotfile manager, written in Rust. Per-device dotfile profiles, symlink-backed, git-synced.
Roost is a terminal-based dotfile manager that moves your application configuration files into a central directory (~/.roost/), organized by device-specific profiles, and creates symlinks back to their original locations. Optionally sync everything via Git for multi-device setups.
Note
Pairs great with vim!
- Per-device profiles — different machines get different config sets
- Symlink-based — apps write to their standard locations, edits are reflected instantly
- Interactive TUI and CLI — browse and manage configs in a terminal interface, or script with subcommands
- Git sync — push/pull your entire dotfile store to a remote repository with conflict detection
- Safe rollback — selective git checkout preserves apps not present at the target commit
- Cross-profile sharing — link apps from one profile into another (zero-copy) or copy them independently
- Built-in diagnostics —
roost doctorchecks for broken symlinks, config inconsistencies, orphaned files - Git history —
diff,log,undo, androllbackcommands for config change management - Fuzzy search — quickly find apps and files in the TUI
- Confidence-scored app detection — automatically identifies 120+ known applications during setup
- Safety features — atomic config writes, path traversal validation, app name sanitization, and config validation on load
- Compatible with MacOS and Linux (Windows untested)
- Rust 1.85 or later (edition 2024)
gitCLI
From crates.io:
cargo install roost-dotFrom source:
git clone https://github.com/mt-22/roost.git
cd roost
cargo install --path .roost init— Interactive setup wizard: choose a profile name, set up git remote (optional), select apps to manage- After init, your configs are symlinked into
~/.roost/<profile>/ roost— Launch the TUI to browse apps, edit configs, manage profilesroost sync— Push changes to your remote repository- On another device,
roost initwith the same remote, and your configs are available
| Command | Description |
|---|---|
roost init |
Initialize roost (interactive setup wizard) |
roost |
Launch the TUI (default when no command given) |
roost add <path> |
Ingest a config path into the active profile |
roost remove <app> |
Stop managing an app, restore original files |
roost remove --all |
Stop managing ALL apps in the active profile, restore all original files |
roost restore <app> |
Restore a single app's symlink |
roost status |
Show managed apps and link status |
roost where <app> |
Print where an app's files live in ~/.roost/ |
roost sync |
Stage, commit, pull (rebase), and push |
roost save [message] |
Stage and commit changes |
roost diff |
Show uncommitted changes |
roost log |
Show recent commits |
roost undo [n] |
Undo the last n commit(s) (destructive) |
roost rollback <hash> |
Reset to a specific commit (destructive) |
roost doctor |
Run diagnostics on config and symlinks |
roost remote |
Show the current git remote URL |
roost remote <url> |
Set the git remote URL |
roost profile add <name> |
Create a new profile (clones active profile's apps) |
roost profile add <name> --from <profile> |
Create a new profile copying apps from an existing profile |
roost profile list |
List all profiles (active marked with *) |
roost profile switch <name> |
Switch active profile (relinks symlinks) |
roost profile delete <name> |
Delete a profile from config |
roost profile rename <old> <new> |
Rename a profile in config |
roost import <app> --from <profile> |
Import an app from another profile (symlink) |
roost copy <app> --to <profile> |
Copy an app to another profile (physical copy) |
roost ignore <pattern> |
Add a global ignore pattern |
roost ignore --app <app> <pattern> |
Add an ignore pattern for a specific app |
roost ignore --list |
List all ignore patterns |
roost adopt |
Adopt orphaned files into roost |
roost completions <shell> |
Generate shell completion script (bash, zsh, fish, powershell, elvish) |
| Key | Action |
|---|---|
j / Down |
Move down |
k / Up |
Move up |
h / Left |
Go to parent (Miller columns) / switch focus to Apps |
l / Right |
Enter directory / open file / switch focus to Files |
Tab |
Toggle focus between Apps and Files panels |
/ |
Fuzzy search apps or files |
q / Esc |
Quit / close dialog |
| Key | Action |
|---|---|
e / Enter |
Open file in $EDITOR |
o |
Open primary config of selected app |
p |
Set primary config for current file |
a |
Add a new app |
x |
Remove selected app |
s |
Save changes (git commit) |
S |
Sync with remote |
d |
Show working tree diff |
g |
View git log |
u |
Undo last commit |
r |
Rollback to selected commit (git log dialog only) |
f |
Import app from another profile (symlink) |
m |
Paste app into another profile (copy) |
i |
Manage ignore patterns |
P |
Profile dialog (switch / create / delete) |
? |
Help (searchable keybind reference) |
~/.roost/ is the home of all managed configs.
roost.toml— shared, git-tracked config (profiles, apps, ignore patterns, remote URL)local.toml— device-local, git-ignored (active profile, OS info, per-device link paths)- Profile directories (
~/.roost/<profile>/) hold the actual config files
During setup, the original config file is moved into ~/.roost/<profile>/ and a symlink is created at the original location pointing to the roost copy. Apps continue reading and writing to their standard paths — all changes are stored inside the roost directory.
~/.roost/
├── roost.toml # Shared config (git-tracked)
├── local.toml # Device-local config (git-ignored)
├── laptop/ # Profile directory
│ ├── nvim/ # App configs (directories)
│ │ └── init.lua
│ └── misc/ # Standalone files
│ └── .gitconfig
└── desktop/
└── ...
Device A (desktop): Run roost init, create profile "shared" with common apps (zsh, git, tmux, nvim), set up git remote, roost sync.
Device B (laptop): Run roost init with the same git remote — pulls the shared profile. Create a new "laptop" profile for device-specific configs. Add the laptop's device-specific configs. Then use the TUI to share common apps:
-
Link from profile (press
fin the Apps panel): Select the "shared" profile, then pick an app (e.g., nvim). This creates a symlink chain so both profiles read from the same files:~/.config/nvim → ~/.roost/laptop/nvim → ~/.roost/shared/nvimEdits from either device are visible everywhere — perfect for configs you want identical across machines.
-
Paste into profile (press
min the Apps panel): Select the "shared" profile, then pick an app. This creates an independent copy so each profile can diverge. Ideal for apps that need device-specific tweaks.
Sync: On each device, roost sync pushes/pulls changes. The symlink chains are stored in config, so they work on any device after a pull.
┌─ laptop/nvim → shared/nvim (symlink, shared config)
~/.config/nvim ─────┤
└─ desktop/nvim (independent copy)
~/.config/zshrc ──── shared/misc/.zshrc (linked from both profiles)
MIT — see LICENSE