Skip to content

Latest commit

 

History

History
202 lines (152 loc) · 6.11 KB

getting-started.md

File metadata and controls

202 lines (152 loc) · 6.11 KB

Getting Started

This page takes you from nothing to a managed ~/.zshrc in about five minutes, then sets up a second machine from the same repository.

Install

# Homebrew (macOS, Linux)
brew install subbeh/tap/statemate

# Arch Linux (AUR)
yay -S statemate-bin            # or: paru -S statemate-bin

# Prebuilt binary: mate_{linux,darwin}_{amd64,arm64}.tar.gz
mkdir -p ~/.local/bin
curl -fsSL https://github.com/subbeh/statemate/releases/download/latest/mate_linux_amd64.tar.gz \
  | tar -xz -C ~/.local/bin mate

# From source (Go 1.25+)
go install github.com/subbeh/statemate/cmd/mate@latest

The binary is called mate. Check it with mate version.

Create a repository

statemate keeps your configuration in an ordinary git repository, usually ~/dotfiles:

mkdir ~/dotfiles && cd ~/dotfiles
mate init

mate init asks for a config format (press Enter for YAML), then:

  • writes a commented mate.yaml
  • writes a README.md with setup instructions, unless you already have one
  • runs git init, unless the directory is already in a git repository
  • offers to register the directory: answer y
Register this directory as your dotfiles location? [Y/n]: y
Saved to ~/.config/statemate/config.yaml

Registering writes source_dir: "~/dotfiles" to the local config, which is what lets every mate command work from any directory. mate config source-dir prints the directory in use.

Create a source

A source is a directory in the repository whose contents are deployed relative to your home directory. Create one per application and list it in mate.yaml:

mkdir zsh
# mate.yaml
sources: [zsh]

Inside a source, paths mirror your home directory: zsh/.zshrc deploys to ~/.zshrc, and nvim/.config/nvim/init.lua deploys to ~/.config/nvim/init.lua. See Organising Your Repository for a layout that scales.

Add your first file

mate add ~/.zshrc

mate add copies the file into a source and leaves the original in place. It asks which source to use, offering the ones listed in mate.yaml. Pick one with the arrow keys, or press / to search:

? Select source:
  ▸ zsh
    nvim
    git

Skip the question with --source zsh, or set default_source in mate.yaml. The source must be listed under sources:. If --source names one whose directory does not exist yet, mate add offers to create the directory and adds the file to it; it does not edit mate.yaml, so list the new source under sources: yourself.

To add all files in a directory, including hidden files and nested directories:

mate add ~/.config/nvim --source nvim

The directory structure stays relative to the target base: this puts the files under nvim/.config/nvim/ in your repository. --for-profile, --encrypt, and --template apply to every added file. File permissions are copied and the original files stay in place.

Files already managed by the selected source are left unchanged. If any file belongs to a different active source, the command reports an error before copying any files. Adding an individual managed file still reports an error. File symlinks are copied as ordinary files containing the linked file's contents; directory symlinks are skipped. Empty directories and configured source directories are also skipped, so adding a parent of your source cannot copy it into itself. Broken symlinks, unreadable files, and special files cause an error. If reading or writing a file fails during copying, files already added remain in the source; correct the error and run the command again.

~/dotfiles/
  mate.yaml
  zsh/
    .zshrc        →  ~/.zshrc

Nothing is reported as pending yet, because ~/.zshrc and its source are identical. statemate starts tracking it on the next mate apply:

mate apply          # 1 unchanged

The apply cycle

From now on, edit the copy in the repository, not the deployed file. An edit made to ~/.zshrc directly turns into a conflict on the next apply. mate edit ~/.zshrc opens the right one for you.

Then, in increasing order of commitment:

mate status      # which files would change
mate diff        # exactly how they would change
mate apply       # write them
$ mate status
  TARGET    SOURCE
~ ~/.zshrc  zsh

$ mate apply
applied 1

mate apply --dry-run walks the whole run, including scripts and packages, without writing anything, and -l lists every file written.

If a deployed file was changed behind statemate's back, apply stops and asks what to do:

Conflict: /home/you/.zshrc
  Target has been modified since last apply
  [o]verwrite, [i]mport, [s]kip, [d]iff, [a]bort:

[i]mport copies the change back into the repository. See Concepts for how statemate tells which side changed.

Commit and push the repository as you would any other:

cd ~/dotfiles && git add -A && git commit -m "Add zsh" && git push

Set up a second machine

Install mate, then clone and register the repository:

git clone git@github.com:you/dotfiles.git ~/dotfiles
cd ~/dotfiles && mate init      # finds mate.yaml, registers it
mate apply

On a machine that already has its own ~/.zshrc, the first apply reports a conflict for it, since statemate has no record of which version is newer. Answer [d] to compare, then [o] to take the repository's version or [i] to keep the machine's.

Setting Up a New Machine covers the rest: encryption keys, secrets, packages, and a bootstrap script.

Next steps