A pure-Rust dotfiles manager — and eventually, a complete new-machine bootstrap system.
`notfiles` started as a Rust replacement for [GNU Stow](https://www.gnu.org/software/stow/). It's growing into a **Cargo workspace** of focused crates that together replace an entire shell-script-based dotfiles ecosystem.
`notcore` is the only shared dependency. No circular deps.
---
## How `notfiles` Works
Each subdirectory of your dotfiles repo is a **package**. `notfiles link` walks each package and symlinks its contents into a target directory (default: `$HOME`), mirroring the directory structure.
```
dotfiles/
└── zsh/
└── .zshrc → symlink → ~/.zshrc
dotfiles/
└── git/
└── .config/
└── git/
└── config → symlink → ~/.config/git/config
```
State is tracked in `.notfiles-state.toml` so `unlink` and `status` know exactly what was linked, when, and how.
This powers `status` (diff expected vs actual) and `unlink` (clean removal with empty-parent cleanup).
---
## New Machine Bootstrap (notstrap)
The hardest part of a new machine is the chicken-and-egg problem: you need secrets to set up the machine, but secrets live in an encrypted file that requires a key you haven't retrieved yet.
`notstrap` solves this with a staged bootstrap:
```
notstrap run
│
├─ 1. Prerequisites check
│ Is bw/sops/age available? Print exactly what's missing and stop.
│
├─ 2. notsecrets — retrieve age key
│ ├─ try: Bitwarden CLI (bw unlock)
│ ├─ fallback: --key-file <path> (USB drive)
│ └─ fallback: interactive prompt (paste key)
│ └─ sops decrypt secrets.sops.env → env injected
│ (now op, bw, github, openai, anthropic tokens are live)
│
├─ 3. Clone dotfiles repo (if not present)
│
├─ 4. notfiles link — stow all packages
│
├─ 5. nothooks --phase dot
│ shell config, git config, AI tool configs (~seconds, re-runnable)
│
├─ 6. nothooks --phase setup
│ Homebrew/Nix packages, mise runtimes, dev tools, op install (~minutes, once)
│
└─ 7. Report
✓ linked 142 files ✓ 3 dot hooks ✓ 7 setup hooks
```
Note: 1Password (`op`) is installed as a **hook** in phase `setup` — after secrets are already available via sops. It takes over secret management for day-to-day use once the machine is live.
| `setup` | ~minutes | No (tracked) | Homebrew packages, mise runtimes, op install |
`setup` hooks are tracked in `.nothooks-state.toml` — already-run hooks are skipped unless `--force` is passed. `dot` hooks always re-run (they're idempotent by design).
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.