A vault for
your dotfiles.
Clone, deploy, and keep in sync across Linux, macOS, and Windows.
One Rust binary replaces stow and the pile of
.setup / .update bash scripts around it.
Copy-based deploy with manifest-tracked drift detection, driven by a
declarative .krypt.toml.
$ krypt update → pull ✓ dotfiles up to date (3 commits, auto-stashed 1 file) → deploy ✓ 71 files · 2 updated · 0 drifted → hooks [hook] reload-hypr platform:linux ✓ [hook] rebuild-bat command_exists:bat ✓ [hook] brew-bundle platform:macos skipped ✓ up to date in 1.2s $ krypt diff M ~/.config/nvim/init.lua deployed ≠ staged $ krypt adopt-edits ✓ adopted edits for 1 entries (70 clean, 0 missing)
why
stow can't run your setup. bash can't track your drift.
One binary, three OSes
Linux, macOS, Windows from the same .krypt.toml. No Perl,
no Python, no shell dialect roulette.
Copy-based deploy + drift
Replaces stow. Every deployed file is recorded in a
manifest, so krypt diff tells you exactly what drifted,
krypt adopt-edits copies those hand-edits back into the
repo, and krypt adopt <path> imports a new file and
prints the [[link]] block for it.
Declarative .krypt.toml
Links, templates, packages, prompts, commands, and hooks in one schema,
splittable across files with include globs.
krypt validate runs the whole include +
${VAR} pipeline, so a typo fails there instead of at first
dispatch.
Step runner with predicates
Steps gate on command_exists: / platform: /
env: / file_exists:. The machine that doesn't
have bat just skips the bat hook — no
if command -v soup.
Package managers, abstracted
pacman · paru · apt · dnf · brew · scoop · winget behind one dependency list. Declare the package once, install it on whatever distro you woke up on.
First-run [prompts.*]
krypt setup walks the wizard your
[prompts.*] sections declare — git identity, machine
profile, whatever you write — and writes the answers through the
[[template]] files that name them. Packages are
krypt deps, deploy is krypt link.
Generic subcommand dispatcher
Any [[command]] entry is reachable as
krypt <group> <name> with no binary changes.
Your rofi launchers become first-class subcommands.
${VAR} interpolation
Built-ins (${HOME}, ${XDG_CONFIG},
${LOCAL_BIN}) then process env, resolved eagerly at config
load. Unknown var = hard error citing file, location, and name.
Auto-stash on update
Uncommitted work at pull time gets stashed via gix-stash,
pulled over, and popped back. Conflicts surface with the stash OID so
you can apply by hand. Opt out with --no-stash. Clone and
pull run through gix — no git binary, HTTPS
remotes only.
Platform-correct notifications
krypt notify <title> <body> picks the backend
the host actually has: notify-send on Linux,
terminal-notifier or osascript on macOS,
PowerShell MessageBox on Windows (no BurntToast install),
stderr when there is nothing. Pin one with
[meta] notify_backend.
Four-crate workspace
krypt-cli (thin clap dispatch) ·
krypt-core (schema, resolver, copy engine, manifest,
runner, predicates, hooks) · krypt-pkg ·
krypt-platform.
Coming from stow + bash
docs/migrating-from-bash.md ↗
maps stow → [[link]], .update →
krypt update, launcher scripts → [[command]].
commands
Five verbs cover the daily loop.
| krypt init <url> | clone your dotfiles repo to the XDG path |
| krypt setup | interactive [prompts.*] wizard |
| krypt deps | install [[deps]] via the host's package manager |
| krypt link | deploy files to their declared destinations |
| krypt update | the daily one: pull, redeploy, run post-update hooks |
| krypt doctor | diagnose config, paths, and missing dependencies |
| krypt validate | parse .krypt.toml, report schema errors |
| krypt diff | show staged vs deployed differences |
| krypt adopt <path> | import a file into the repo, print its [[link]] |
| krypt adopt-edits | sync every drifted deployed file back into the repo |
| krypt unlink / relink | reverse or refresh a deploy |
| krypt paths | print every resolved path variable |
| krypt notify <title> <body> | desktop notification on whatever OS you're on |
| krypt menu [name] | list or run group = "menu" commands |
| krypt <group> <name> | generic dispatcher for any declared command group |
| krypt battery |
built-in battery report / log /
clear
|
Worked example: mxaddict/dotfiles ↗ — Arch + Hyprland, ~70 links, ~30 commands, ~10 post-update hooks.
install
Every channel drops a krypt on your $PATH.
Arch via AUR, macOS via the Homebrew tap, Windows via Scoop, or the prebuilt
binaries on the release page — those four track every tag. The
krypt name on crates.io is held by an unrelated stale project,
so the binary crate is published as krypt-cli, and that one
channel is paused: the gix-stash plumbing krypt needs still
lives on a fork, which cargo publish won't accept, so
cargo install krypt-cli currently lands an older build.
Publishing resumes when the upstream gitoxide PR merges.
# Arch (AUR) $ paru -S krypt-bin # macOS (Homebrew tap) $ brew install kryptic-sh/tap/krypt # Windows (Scoop) $ scoop bucket add kryptic https://github.com/kryptic-sh/scoop-bucket $ scoop install krypt # any platform (crates.io — publishing paused, older build) $ cargo install krypt-cli
$ krypt init https://github.com/you/dotfiles $ krypt setup $ krypt deps $ krypt link # then, forever after: $ krypt update