Cross-platform dotfiles and machine manager for macOS, Windows, and Linux.
Bootstrap a bare machine (installs uv and git if needed, clones repo, installs mc):
Unix (macOS/Linux/WSL):
curl -LsSf https://raw.githubusercontent.com/mohdfareed/machine/main/scripts/bootstrap.sh | shWindows (PowerShell):
irm https://raw.githubusercontent.com/mohdfareed/machine/main/scripts/bootstrap.ps1 | iexThe repo is cloned to ~/.machine by default. Override with MC_HOME=<path> before running.
Re-run bootstrap on an existing machine to reinstall the CLI after moving the repo:
cd $MC_HOME
./scripts/bootstrap.shmc apply [modules] # Deploy configs, packages, and scripts
mc sync # Pull and push latest repo changes
mc update [modules] # Update packages and run update scriptsRun mc -h or mc <command> -h for full options.
~/.machine/
├── config/ <- shared modules (git, shell, ...)
│ └── <name>/
│ ├── module.py <- Module(files, packages, scripts)
│ └── ...
├── machines/ <- per-host manifests
│ └── <id>/
│ ├── manifest.py <- MachineManifest(modules, files, packages, scripts)
│ ├── machine.env <- committed config vars (paths, hostname, ...)
│ └── ...
└── src/machine/ <- CLI (core.py, app.py, cli.py, manifest.py)Modules (config/<name>/module.py) export a Module:
| Field | Description |
|---|---|
files |
FileMapping(source, target) → symlinked to ~ |
packages |
Package(name, brew=, apt=, snap=, winget=, scoop=, mas=, script=) |
scripts |
Platform-tagged scripts to run |
overrides |
FileMapping(source, target) → machine-local override symlinks |
depends |
Module names that must be included before this |
Manifests (machines/<id>/manifest.py) export a MachineManifest:
| Field | Description |
|---|---|
name |
Public display name; defaults to machine ID |
modules |
Module names to compose |
files |
Machine-specific symlinks |
packages |
Machine-specific packages |
scripts |
Machine-specific scripts |
Platform tags on script filenames filter by platform - no tag means all platforms:
| Tag | Runs on |
|---|---|
.macos |
macOS |
.linux |
Linux |
.unix |
macOS, Linux, WSL, GHCS |
.win |
Windows |
.wsl |
WSL |
.ghcs |
GitHub Codespaces |
Script prefixes control execution behavior:
| Prefix | Behavior |
|---|---|
init_ |
Runs before packages (env/tool setup) |
once_ |
Runs once per machine, then skipped |
watch_ |
Reruns when the script's content changes |
up_ |
Runs only during mc update |
Env vars are available to every script subprocess at runtime via three-tier sourcing:
~/.env- generated bymc apply, contains onlyMC_HOMEandMC_ID$MC_HOME/machines/$MC_ID/machine.env- machine-specific config vars$MC_PRIVATE/env/$MC_ID.env- machine secrets, plain dotenv format
mc loads all three tiers into every script subprocess.
Shell profiles (.zshenv, profile.ps1) source the same three tiers.
Local overrides: modules declare which machine-specific files they accept via the overrides field.
Drop matching files in your machine dir and they are auto-discovered and symlinked:
~/.gitconfig.local- declared bygitmodule, included by gitconfig~/.zshenv.local- declared byshellmodule, sourced by zshenv~/.zshrc.local- declared byshellmodule, sourced by zshrc~/term.settings.json- declared bywin-termmodule, used by Windows Terminal
Secrets are stored outside the repo in MC_PRIVATE - defaults to app_dir/private
but typically overridden in machine.env (e.g. $ICLOUD/.machine on macOS,
$HOME/.machine on Linux). The directory is never checked into git.
MC_PRIVATE/
├── env/
│ └── <MC_ID>.env <- per-machine secrets (plain dotenv)
├── ssh/
│ └── <MC_ID> <- machine private key (optional)
│ └── <MC_ID>.pub <- matching public key (optional)The homelab module (config/homelab/) deploys and manages Docker Compose services over Tailscale.
See config/homelab/README.md for architecture,
environment variables, and setup instructions.
Any machine can include this module as a deployment target.
By default, the homelab machine acts as the central orchestrator and also
serves as a target for its own services.
cd $MC_HOME
# build and run for development
uv sync --dev
uv run mc --help
# format and auto-fix (run before committing)
./scripts/fix.sh
# code validation (run before committing)
./scripts/check.sh