{"id":50513937,"url":"https://github.com/omt-global/machete","last_synced_at":"2026-06-02T22:04:07.266Z","repository":{"id":360765549,"uuid":"1110921007","full_name":"OMT-Global/machete","owner":"OMT-Global","description":"Swiss army knife for macOS setup and maintenance.","archived":false,"fork":false,"pushed_at":"2026-05-27T18:59:46.000Z","size":183,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-27T20:22:37.675Z","etag":null,"topics":["automation","dotfiles","macos","provisioning","shell"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OMT-Global.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-12-05T23:44:08.000Z","updated_at":"2026-05-27T18:59:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/OMT-Global/machete","commit_stats":null,"previous_names":["omt-global/machete"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/OMT-Global/machete","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OMT-Global%2Fmachete","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OMT-Global%2Fmachete/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OMT-Global%2Fmachete/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OMT-Global%2Fmachete/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OMT-Global","download_url":"https://codeload.github.com/OMT-Global/machete/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OMT-Global%2Fmachete/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33838227,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","dotfiles","macos","provisioning","shell"],"created_at":"2026-06-02T22:04:02.933Z","updated_at":"2026-06-02T22:04:07.256Z","avatar_url":"https://github.com/OMT-Global.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# machete\n\n```\n                       _          _\n  _ __ ___   __ _  ___| |__   ___| |_ ___\n | '_ ` _ \\ / _` |/ __| '_ \\ / _ \\ __/ _ \\\n | | | | | | (_| | (__| | | |  __/ ||  __/\n |_| |_| |_|\\__,_|\\___|_| |_|\\___|\\__\\___|\n```\n\n**Hack your way through a fresh Mac.** 🔪\n\n`machete` is the swiss army knife for macOS setup and maintenance: snapshot\nyour current Mac into Git, restore it on a new machine in one command, and\nkeep everything in sync over time. No clicking through System Settings at\n2am. No \"I think I had a Homebrew formula for that.\" Just one binary, one\nrepo, one command.\n\n\u003e 💡 Built as a single statically-linked Go binary. No bash dependency\n\u003e spaghetti, no `curl | sudo bash` shenanigans.\n\n## ⚠️ Command Safety\n\n`machete` is intentionally high-impact: it can install packages, symlink\nfiles into `$HOME`, apply macOS defaults, start Homebrew services, and\nrewrite tracked snapshots from the current machine state. Read what each\ncommand does before pointing it at a machine you care about.\n\n- `./machete setup` installs or restores Homebrew packages, global packages, services, dotfile symlinks, and macOS defaults. Existing home files are backed up with timestamped names before symlinks are created.\n- `./machete sync` pulls the latest repo changes and re-runs setup for the active profile.\n- `./machete snapshot` copies selected live machine state into this repository. Review `git diff` before committing so private paths, identities, or secrets do not become portable profile data.\n- `./machete defaults` applies the shell commands in `defaults/macos-defaults.sh` to the current macOS user.\n- `./machete schedule` installs a per-user `launchd` job that runs `sync` and `update` on a schedule.\n\nRead-only inspection commands (safe to poke around with): `doctor`, `diff`,\n`history`, `verify` without `--init`, and `audit`.\n\n## 🛠️ Install\n\nYou need [Go](https://go.dev/dl/) 1.21+ to build from source.\n\n```bash\ngit clone https://github.com/OMT-Global/machete.git\ncd machete\nmake build        # builds dist/machete\nmake install      # optional: copies dist/machete to /usr/local/bin/machete\n```\n\n`./machete` at the repo root is a thin wrapper — it builds the Go binary\non first use and re-execs it for you, so you can just go.\n\n## 🗺️ Commands\n\n```\n./machete setup      Bootstrap a new Mac: Xcode tools, Homebrew, global packages, services, dotfiles, defaults\n./machete snapshot   Export current state to the active profile or --profile target\n./machete schedule   Install a daily launchd agent that runs sync + update automatically\n./machete track      Add one or more home-directory files to dotfiles/ and symlink them back into $HOME\n./machete untrack    Remove one or more files from dotfiles/ and stop managing them\n./machete uninstall  Dry-run or apply a reversible teardown of machete-managed home dotfile symlinks\n./machete services   Start Homebrew services listed in defaults/brew-services.txt\n./machete history    List rollback snapshot tags, newest first\n./machete rollback   Restore the latest snapshot tag and re-apply setup\n./machete verify     Hash tracked files and compare them to the checksum baseline\n./machete audit      Scan $HOME and report new, changed, or missing files since the last snapshot baseline\n./machete update     Upgrade all Homebrew packages and clean up\n./machete doctor     Check what's installed, symlinked, and in sync for the active profile\n./machete diff       Compare tracked dotfiles and Brewfile for the active profile\n./machete sync       Pull latest repo changes and re-apply setup (idempotent)\n./machete profile list\n./machete profile create work\n./machete defaults   Apply macOS system preferences from defaults/macos-defaults.sh\n./machete defaults --init\n                    Create defaults/macos-defaults.sh with an interactive preset picker\n```\n\n## 🔁 How It Works\n\n```\nCurrent Mac                   Git Repository              New Mac\n┌──────────────────────┐      ┌──────────────────┐      ┌──────────────────────┐\n│ ./machete snapshot   │ ───► │ Brewfile         │ ───► │ ./machete setup      │\n│  - brew bundle dump  │      │ packages/        │      │  - Xcode CLI tools   │\n│  - global pkg lists  │      │ dotfiles/        │      │  - Homebrew          │\n│  - copy dotfiles     │      │ defaults/        │      │  - brew bundle       │\n│  - brew services     │      │   brew-services  │      │  - global pkg restore│\n│  - defaults template │      │   macos-defaults │      │  - brew services     │\n│                      │      │                  │      │  - symlink dotfiles  │\n│                      │      │                  │      │  - apply defaults    │\n└──────────────────────┘      └──────────────────┘      └──────────────────────┘\n```\n\nOne side captures, Git carries it, the other side restores. The boring,\npredictable, beautiful part is that both sides run the same binary.\n\n## 🚀 Quick Start\n\n### On your current Mac (first time)\n\n```bash\ngit clone https://github.com/OMT-Global/machete.git\ncd machete\n./machete snapshot                  # captures the default profile in the repo root\n./machete snapshot --with-extensions\n./machete profile create work\n./machete snapshot --profile work   # captures a separate machine under profiles/work/\nvim defaults/macos-defaults.sh      # customize your system preferences\ngit status --short\ngit diff --stat\ngit add Brewfile dotfiles defaults packages profiles\ngit commit -m \"snapshot: $(date +%Y-%m-%d)\" \u0026\u0026 git push\n```\n\n`setup`, `snapshot`, and `sync` quietly stash a rollback tag before they\ntouch state, named `snapshot/YYYY-MM-DDTHH-MM-SS`. If something goes\nsideways, `./machete rollback` puts you back where you were.\n\n\u003e 🕵️ Before committing a snapshot, inspect `git status --short`,\n\u003e `git diff --stat`, and the full diff for private paths, API tokens,\n\u003e machine-local shell snippets, and personal identity fields that should\n\u003e stay out of a shared repo.\n\n### On a new Mac\n\n```bash\ngit clone https://github.com/OMT-Global/machete.git\ncd machete\n./machete setup\n```\n\nGo make coffee. ☕ Come back to a fully provisioned machine.\n\n### Day-to-day maintenance\n\n```bash\n./machete doctor     # see what's drifted\n./machete diff       # compare live state before snapshotting\n./machete verify --init  # record a checksum baseline\n./machete verify     # check tracked files against that baseline\n./machete audit      # full-home drift report since the last snapshot baseline\n./machete schedule   # install a daily sync + update launch agent\n./machete doctor --profile work\n./machete services   # start saved Homebrew services\n./machete update     # upgrade all packages\n./machete sync       # pull latest + re-apply\n./machete track .config/ghostty/config\n./machete untrack .vimrc\n./machete history    # list rollback snapshots\n./machete rollback   # restore the newest snapshot and re-apply setup\n```\n\n`./machete verify --init` records SHA256 checksums for the active profile's\ntracked dotfiles and Brewfile in `~/.machete/checksums.sqlite`. Later\n`./machete verify` runs report `NEW`, `CHANGED`, or `MISSING` files and\nexit non-zero when drift is found. Use `./machete verify --full --init`\nand `./machete verify --full` for a broader `$HOME` scan.\n\n`./machete snapshot` also refreshes a full-home audit baseline in the\nbackground. `./machete audit` compares the current filesystem against\nthat baseline, groups output into `NEW FILES`, `CHANGED FILES`, and\n`MISSING FILES`, and exits non-zero when drift is found. Use `--dir` to\nlimit the report to a subtree, `--since YYYY-MM-DD` to filter recent\nchanges, and `--export report.csv` to write CSV output.\n\n`./machete schedule` installs a per-user `launchd` plist in\n`~/Library/LaunchAgents/` and a small runner script in\n`~/.machete/schedule/\u003cprofile\u003e/run.sh`. By default it runs daily at\n`09:00` local time, calling `./machete sync` and then `./machete update`\nfor the active profile. Use `--hour` and `--minute` to change the schedule.\n\nTo restore a specific snapshot, pass its tag:\n\n```bash\n./machete rollback snapshot/2026-04-22T09-30-00\n```\n\n## 📂 File Structure\n\n```\nmachete/\n  machete                  # thin shell wrapper that builds + runs the Go binary\n  cmd/machete/             # Go entrypoint (main.go)\n  pkg/                     # Go packages: brewfile, dotfiles, profiles, snapshot, ...\n  Makefile                 # build, install, test, clean\n  go.mod, go.sum           # Go module definition\n  Brewfile                 # default-profile Homebrew packages\n  packages/                # default-profile global package snapshots\n    npm-global.txt\n    pip-global.txt\n    cargo-global.txt\n    vscode-extensions.txt  # VS Code-compatible editor extensions (opt-in snapshot)\n  dotfiles/                # default-profile dotfiles, symlinked to $HOME by setup\n    .zshrc\n    .zprofile\n    .gitconfig\n    ...\n  defaults/                # default-profile defaults\n    macos-defaults.sh\n    brew-services.txt\n  profiles/\n    base/\n      Brewfile\n      dotfiles/\n    work/\n      Brewfile\n      dotfiles/\n      packages/\n      defaults/\n        macos-defaults.sh\n        brew-services.txt\n```\n\n## 👥 Profiles\n\n`machete` supports multiple machine profiles in one repo — perfect for\nthe \"personal laptop vs. work laptop vs. that experimental media server\"\nsituation.\n\n- `default` keeps the existing flat repo layout for backward compatibility.\n- When `profiles/base/` exists, it is always applied first and named profiles layer on top of it.\n- Named profiles live under `profiles/\u003cname\u003e/`.\n- `--profile \u003cname\u003e` works with `setup`, `snapshot`, `sync`, `doctor`, and `diff`.\n- The last explicit `--profile` is stored in `~/.machete/profile` and reused on later commands.\n\n```bash\nmkdir -p profiles/base\n./machete profile create work\n./machete snapshot --profile work\n./machete doctor           # now uses the persisted work profile\n./machete profile list\n```\n\n## 📦 Global Packages\n\n`./machete snapshot` records user/global packages for:\n- `npm -g` → `packages/npm-global.txt`\n- `pip install --user` → `packages/pip-global.txt`\n- `cargo install` → `packages/cargo-global.txt`\n\n`./machete setup` restores each list when the corresponding tool is\navailable, and `./machete doctor` reports drift if the live machine no\nlonger matches the saved snapshot.\n\n## 🔗 Dotfiles\n\nFiles in `dotfiles/` are **symlinked** (not copied) into `$HOME` by\n`./machete setup`. This means:\n- Editing `~/.zshrc` edits the repo file directly\n- No manual syncing required\n- `./machete snapshot` re-copies them if you add new dotfiles to track\n\nTo start tracking a new file, run `./machete track PATH`. This copies\n`~/PATH` into `dotfiles/PATH` and replaces the home file with a symlink\nback into the repo. Machete refuses non-portable paths such as auth\nstate, sessions, caches, `.env` files, SSH/GitHub/AWS/Kubernetes\ncredentials, and filenames that look token-, cookie-, credential-,\nsession-, or secret-bearing. (Yes, we will save you from yourself.)\n\nTo stop tracking a file, run `./machete untrack PATH`. If the home file\nis still symlinked to the repo copy, machete converts it back into a\nregular file before removing `dotfiles/PATH`.\n\nTo undo the machine-local dotfile install without touching the repo\ncopy, run `./machete uninstall --dotfiles` for a dry run, then\n`./machete uninstall --dotfiles --apply` to remove repo-managed symlinks\nand restore the newest `\u003cfile\u003e.bak.\u003ctimestamp\u003e` backup when one exists.\n\n`./machete snapshot` refreshes portable files already tracked under\n`dotfiles/` and skips any tracked path that matches the non-portable\ndenylist. On a brand-new repo with no tracked dotfiles yet, it still\nseeds the default starter set (`.zshrc`, `.zprofile`, `.gitconfig`,\n`.gitignore_global`, `.vimrc`) when those files exist.\n\n\u003e 🙈 Before publishing or sharing a machete repo, template personal\n\u003e identity fields in dotfiles such as `.gitconfig` and remove shell\n\u003e snippets that load local API tokens from the keychain or environment.\n\n## ⚙️ macOS Defaults\n\n`defaults/macos-defaults.sh` is generated on first `./machete snapshot`,\nor any time with `./machete defaults --init`.\nThe preset picker offers:\n- `minimal`: conservative Finder, dialog, and screenshot defaults\n- `developer`: minimal defaults plus fast keyboard, power-user Finder, Dock, and Activity Monitor settings\n- `privacy`: minimal defaults plus reduced ad personalization and web search leakage\n\nAfter choosing a base preset, answer yes/no prompts to layer individual\nsettings. In non-interactive runs such as `CI=true`, machete skips\nprompts and writes the safe `minimal` preset.\n\nEdit it freely and re-run `./machete defaults` to apply changes.\n\n## 🍺 Homebrew Services\n\n`./machete snapshot` writes currently running Homebrew services to\n`defaults/brew-services.txt`. `./machete setup` starts each saved\nservice after installing packages, and `./machete services` can re-run\nthat step by itself.\n\nIf a saved service is not installed, machete prints a warning and skips\nit. `./machete doctor` reports saved services that are missing or not\nrunning.\n\n## ✏️ Editor Extensions\n\n`./machete snapshot --with-extensions` writes extensions from the first\navailable VS Code-compatible CLI (`code`, `cursor`, or `codium`) to\n`packages/vscode-extensions.txt`. When that file exists, `./machete\nsetup` installs each saved extension with the first available editor\nCLI. If no supported editor CLI is installed, setup prints a warning\nand continues. `./machete doctor` reports extension drift only when\n`packages/vscode-extensions.txt` exists.\n\n## ✅ Requirements\n\n- macOS (Intel or Apple Silicon)\n- Git\n- Go 1.21+ (to build the binary)\n- Internet connection (for Homebrew)\n\n## 🩹 Troubleshooting\n\n- **Homebrew not found after install**: ensure `/opt/homebrew/bin` (Apple Silicon) or `/usr/local/bin` (Intel) is in your `PATH`.\n- **Permission denied on `./machete`**: `chmod +x machete`.\n- **`go: command not found` when running the wrapper**: install Go from [go.dev/dl](https://go.dev/dl/), or build elsewhere with `make build` and copy `dist/machete` over.\n- **Symlink conflicts**: `./machete setup` backs up existing files to `\u003cfile\u003e.bak.\u003ctimestamp\u003e` before symlinking.\n- **Back out a setup run**: `./machete uninstall --dotfiles` shows which repo-managed symlinks would be removed; add `--apply` to perform the teardown. It does not uninstall Homebrew packages, clear caches, or restore shell history.\n\n## 🔒 Privacy\n\nDo not commit private keys, SSH configs, auth files, shell history,\nsession state, cache directories, local Claude/Codex worktrees, or\nfiles that contain tokens, passwords, cookies, or machine-local secrets.\nKeep local tool state such as `.claude/` and `.codex/` out of the repo\nunless you have separated a small, portable scaffold from generated\nruntime data.\n\nThe bootstrap docs under `docs/bootstrap/` are maintainer/operator notes\nfor this repository. They are not required for normal public `machete`\nusage.\n\n## 📜 License\n\nMIT. Use it, fork it, swing it around. Just don't blame us if you `rm -rf` something important. 🪦\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fomt-global%2Fmachete","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fomt-global%2Fmachete","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fomt-global%2Fmachete/lists"}