Skip to content
Copied!
published on 2026-07-18

Tutorial (macOS and Linux)

Starting from nothing under management, this tutorial walks step by step through putting your dotfiles under Rigo and syncing them with a second machine, then goes on to organizing (per-OS, per-machine, secrets) and daily operations. If you work in Windows Terminal, see the tutorial (Windows) instead.

There are only two prerequisites.

  • Installation is done
  • You have some way to sync a directory between machines (Syncthing, Dropbox, iCloud Drive, and so on). Rigo does not care which. You can also do without one while trying things out on a single machine

The examples place the vault at ~/Sync/Vault; substitute the directory your sync tool actually syncs. Absolute paths in the example output use macOS notation (/Users/ada); on most Linux systems the home directory is /home/ada instead.

Step 1 — Create the Vault

The vault is a plain directory. The only fixed thing is where the config file rigo.toml sits (<vault>/.config/rigo/rigo.toml), and it can be empty.

sh
mkdir -p ~/Sync/Vault/.config/rigo
touch ~/Sync/Vault/.config/rigo/rigo.toml

Only for the first run, name this rigo.toml directly with -f and run apply.

sh
rigo -f ~/Sync/Vault/.config/rigo/rigo.toml apply
linked    .config/rigo/rigo.toml

1 linked, 0 conflict, 0 broken, 0 failed, 0 excluded

At this point the rigo.toml inside the vault has been linked to ~/.config/rigo/rigo.toml. Rigo follows this symlink to discover the vault, so -f is no longer needed from here on.

sh
rigo status
host: mymac (mode: exclude)

linked    .config/rigo/rigo.toml

The mymac in the header is this machine's host name (the identifier used later for per-machine selection).

Step 2 — Manage Your First File

rigo add moves the real content into the vault and links it back into place.

sh
rigo add ~/.zshrc
added .zshrc

Let's see what happened.

sh
ls -l ~/.zshrc
lrwxr-xr-x  1 ada  staff  28 Jul 18 10:00 /Users/ada/.zshrc -> /Users/ada/Sync/Vault/.zshrc

Open and edit ~/.zshrc in your editor as you always have; what actually changes is the vault copy. The change rides the sync tool to your other machines as it is. There is no extra "edit, then apply" step.

Step 3 — Manage a Directory

When you add a directory, you choose between two treatments.

  • --dir
    Deploys the whole directory as one symlink. New files created inside come under management automatically. Suited to things that form one unit of configuration or plugins (.vim/, .hammerspoon/, and so on).
  • --files
    Moves and links each file inside individually instead of the directory as a unit. Suited to things you want to control per file, for example when part of the contents may become OS-specific later.
sh
# Manage ~/.vim as one symlink, grouped under a tag
rigo add --dir --tag vim ~/.vim
added .vim/ (directory unit)

Running add on a directory without either flag asks interactively.

  d) whole directory: one symlink, new files follow automatically
  f) files: move and link each file individually
  a) abort
choice:

A directory added with --dir is recorded automatically in dirs in rigo.toml (or in [tags] when --tag is given). --tag groups entries under a tag, enabling bulk operations such as rigo tag link vim later.

Manual Work Is Fine Too

We have used rigo add so far, but it is not a required path. Rigo keeps no hidden state file or database; its only sources of truth are the vault's directory tree and the actual state of your files. As long as the result is the same, doing things by hand breaks nothing.

  • Move a file into its place in the vault yourself and create the symlink yourself. The next rigo status recognizes it as linked
  • Put a file in the vault without linking it. The entry shows up as pending (if you moved it) or unlinked (if you copied it and the contents are identical), and rigo apply picks it up and links it
  • Edit rigo.toml directly. The automatic additions made by --dir / --tag are conveniences only, and writing the same thing by hand is equivalent (later steps do in fact edit it by hand)

The commands exist to save you busywork: staging and rollback, conflict checks, config bookkeeping. Mix them with manual work freely.

Step 4 — Connect a Second Machine

Install Rigo on the second machine too, and wait for the sync tool to finish syncing the vault. All that remains is the first-run bootstrap.

sh
rigo -f ~/Sync/Vault/.config/rigo/rigo.toml apply
linked    .config/rigo/rigo.toml
linked    .vim
conflict  .zshrc  (resolve with "rigo link .zshrc")

2 linked, 1 conflict, 0 broken, 0 failed, 0 excluded

Files that did not exist yet (pending) were simply linked. The second machine, however, already had a ~/.zshrc with different content, so it is reported as a conflict. Rigo never resolves a conflict silently. Resolve it as instructed.

sh
rigo link .zshrc
conflict: .zshrc
  vault: 1234 B, modified 2026-07-18 10:00:12
  local: 987 B, modified 2026-07-01 08:15:44
  +12 -3

If the diff is 40 lines or fewer it is shown right below, followed by the choices.

  1) take the vault version (local content is replaced)
  2) adopt the local content into the vault, then link
  3) abort
choice:
  • To align with the first machine, choose 1
  • To make the second machine's content the truth and adopt it into the vault, choose 2

In machine-setup scripts and the like, rigo link --force .zshrc resolves non-interactively by taking the vault side.

The two machines now share the same real content. Edit on either machine and the change reaches the other via the sync tool. Day to day, rigo status is the check-in and rigo apply deploys newly synced entries.

Step 5 — Per-OS Files

Files whose content should differ between macOS and Linux are added with --os. The entry goes under .os/<darwin|linux|windows>/ in the vault and deploys only on machines running that OS.

sh
# On the Mac: this Karabiner config only makes sense on macOS
rigo add --os --dir ~/.config/karabiner

When the same logical path exists in both the common layer and an OS layer, the OS layer wins. A "common by default, macOS overrides" setup is just .zshrc in the common layer plus a replacement at .os/darwin/.zshrc. See How It Works for details.

Step 6 — Choose What Deploys Where

Entries you do not want on a work machine, a server that should get the bare minimum, and similar choices are declared in rigo.toml. Since rigo.toml is itself managed, editing it on any machine reaches all of them.

toml
[groups]                     # group → hosts (Ansible inventory style)
work = ["workpc", "buildbox"]

[include]                    # host/group → ONLY these deploy (allowlist)
servers = ["zsh", ".gitconfig"]

[exclude]                    # host/group → these do NOT deploy
work = ["vim"]
  • Host names are the identifier shown in the rigo status header (host name up to the first dot, lowercased).
  • List items can be tag names or paths.
  • A host with an include switches to allowlist mode: only what is listed deploys.

Deselected entries show as excluded in status, and apply never touches them.

Step 7 — Secrets

Sensitive files such as API tokens and .netrc are materialized from a password manager instead of having real content in the vault. Only references go into rigo.toml (the current backend is 1Password's op:// references; the op CLI is required).

toml
[secrets]                    # target path → password-manager reference
".netrc"           = { ref = "op://Personal/netrc/notesPlain", mode = 0o600 }
".config/gh/token" = "op://Personal/GitHub/token"
sh
rigo secrets apply
applied  .config/gh/token
applied  .netrc

2 secret(s) written

The written files are real files, not symlinks, and never enter the vault (nor the sync). The password manager remains the source of truth; after updating a value, re-run rigo secrets apply on each machine. rigo secrets status checks existence, and rigo secrets remove deletes the files when handing off a machine.

Step 8 — Daily Operations

Finally, the commands you will use day to day.

sh
# Anything drifted? (read-only; exit 1 when differences exist)
rigo diff

# Converge after the sync tool delivers new entries
rigo apply

# Materialize an entry for a while (e.g. to experiment locally)
rigo unlink .zshrc
rigo link .zshrc          # back to the shared version

# Stop managing something (local file stays; vault copy goes to the trash)
rigo forget .zshrc

# The trash is the undo for forget
rigo trash ls
rigo trash restore .zshrc

# Clean up broken links (e.g. after a forget on another machine)
rigo clean

The real content of a forget-ed entry stays in the in-vault trash, so it can be undone. The trash is a safety net shared by all machines, so run rigo trash empty only once you are truly done with it (age limits such as --older-than 30d are available).

That covers Rigo's daily operations. For every flag and behavior of each command, see the command reference; for every rigo.toml item, the configuration reference.