Metadata-Version: 2.5
Name: mackup-ng
Version: 2.4.1
Summary: Backup and keep your application settings in sync (maintained fork of mackup).
Project-URL: Repository, https://github.com/grigorii-horos/mackup-ng.git
Project-URL: Issues, https://github.com/grigorii-horos/mackup-ng/issues
Project-URL: Changelog, https://github.com/grigorii-horos/mackup-ng/releases
Author-email: Grigorii Horos <horosgrisa@gmail.com>, Laurent Raufaste <analogue@glop.org>
License-Expression: GPL-3.0-or-later
License-File: LICENSE
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: System :: Archiving :: Backup
Classifier: Topic :: Utilities
Requires-Python: >=3.12
Requires-Dist: docopt-ng>=0.9.0
Description-Content-Type: text/markdown

# mackup-ng

[![Tests](https://github.com/grigorii-horos/mackup-ng/actions/workflows/test.yaml/badge.svg)](https://github.com/grigorii-horos/mackup-ng/actions/workflows/test.yaml)
[![PyPI version](https://badge.fury.io/py/mackup-ng.svg)](https://badge.fury.io/py/mackup-ng)
[![Python Versions](https://img.shields.io/pypi/pyversions/mackup-ng.svg)](https://pypi.org/project/mackup-ng/)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![mypy](https://img.shields.io/badge/mypy-checked-blue)](http://mypy-lang.org/)
[![License](https://img.shields.io/github/license/grigorii-horos/mackup-ng.svg)](https://github.com/grigorii-horos/mackup-ng/blob/master/LICENSE)

Backup and keep your application settings in sync.

> **mackup-ng** is a maintained fork of [mackup](https://github.com/lra/mackup)
> by Laurent Raufaste. It replaces the backup/restore/link commands with a
> single two-way `sync` plus an `rm` command, while keeping the same on-disk
> conventions (`.mackup.cfg`, the `Mackup` storage folder).
>
> ⚠️ **Incompatible with the original `mackup`.** This package installs a
> `mackup` command (and a `mackup-ng` alias) that **shadows the upstream
> `mackup`** — do not install both in the same environment, or the last one
> installed wins. The on-disk format also diverges: mackup-ng records deletion
> tombstones (`.mackup-deletions`) and syncs by modification time, so a folder
> written by mackup-ng is not meant to be managed by the original mackup.

## Table of contents

- [mackup-ng](#mackup-ng)
  - [Table of contents](#table-of-contents)
  - [Quickstart](#quickstart)
  - [Usage](#usage)
  - [What does it do](#what-does-it-do)
    - [Sync mode](#sync-mode)
    - [Ignored files](#ignored-files)
  - [Supported Storages](#supported-storages)
  - [Unsupported Storages](#unsupported-storages)
  - [Supported Applications](#supported-applications)
  - [Can you support application X](#can-you-support-application-x)
  - [Personalization \& configuration](#personalization--configuration)
  - [Fork Additions](#fork-additions)
  - [Why did you do this](#why-did-you-do-this)
  - [What platforms are supported](#what-platforms-are-supported)
  - [What's up with the weird name](#whats-up-with-the-weird-name)
  - [Architecture](#architecture)
  - [Where can I find more information](#where-can-i-find-more-information)

## Quickstart

Install it with [pip](https://pip.pypa.io/en/stable/) (or
[uv](https://docs.astral.sh/uv/)):

```bash
# Install mackup-ng with pip
pip install --upgrade mackup-ng

# ...or as an isolated tool with uv
uv tool install mackup-ng

# Launch it and sync your files
mackup-ng sync
```

You're all set and can back up from now on.

Next, on any new workstation, do:

```bash
# Install mackup-ng
pip install --upgrade mackup-ng

# Launch it and sync your files
mackup-ng sync
```

Done!

You can find more detailed instructions in [INSTALL.md](INSTALL.md).

## Usage

`mackup-ng sync`

Synchronize your application files between your home folder and the Mackup folder.

`mackup-ng rm <path>`

Remove a managed config path locally and from the Mackup folder, and record the
deletion so future syncs remove it on other machines too.

`mackup-ng info <path>...`

Report how a path relates to the backup: the config that manages it, whether it
is synced (and why not, when it isn't), both copies with their size and mtime,
what the last sync on this machine did to it, and whether the two sides still
agree. Exits with status 1 when a path is managed by no config.

```console
$ mackup-ng info ~/.zshrc
Path: .zshrc
Config: zsh (Zsh)
Sync: yes
Local: /home/you/.zshrc — 8.9 KiB, 2026-08-17 13:33
Backup: /home/you/Dropbox/Mackup/.zshrc — 8.5 KiB, 2026-08-14 09:02
Last sync: 2026-08-14 09:02 (Backed up)
State: diverged — local is newer; next sync backs it up
```

The "Last sync" line comes from a machine-local log that `mackup-ng sync`
writes to `$XDG_STATE_HOME/mackup/sync-log.json`; it reads `never recorded on
this machine` until the first sync after upgrading.

`mackup-ng list`

Display the list of applications supported by mackup-ng.

`mackup-ng mark <marker>` / `mackup-ng unmark <marker>` / `mackup-ng markers`

Set / remove / list machine-local markers (e.g. `backup`, `low-resource`,
`no-linger`, `no-apikey`, `no-dconf`). See "Machine-local extras" below.

`mackup-ng dconf-add <path>...`

Track and dump dconf path(s), e.g. `/org/gnome/terminal/` (Linux/GNOME).

`mackup-ng apply`

Run every config's action blocks (without syncing files); blocks also run
automatically during `sync`.

`mackup-ng -h`

Get some help, obviously...

## What does it do

By only tracking pure configuration files, it keeps the crap out of your
freshly new installed workstation (no cache, temporary and locally specific
files are transferred).

mackup-ng makes setting up the environment easy and simple.

mackup-ng uses sync mode.

### Sync mode

Sync mode is used to synchronize your files.
The files are stored in the configured Mackup folder,
which can be in Dropbox, iCloud, or wherever you configure it.

It is covered by the commands:

- `mackup-ng sync`
- `mackup-ng rm <path>`

`sync` reconciles every managed file in both directions by modification time.
To drop a single managed path everywhere, use `mackup-ng rm <path>`: it removes
the file locally and from the Mackup folder, and records a deletion tombstone so
future syncs remove it on your other machines too.

### Ignored files

Storage backends drop their own bookkeeping inside the folders they sync.
Syncthing is the loud one: each concurrent edit leaves a `*.sync-conflict-*`
copy next to the file. mackup-ng carries none of it in either direction, and
deletes none of it either — those files belong to the tool that made them. A
fresh conflict copy is skipped when picking the newer side too, so it cannot
beat a real edit on another machine.

Patterns live in `<name>.toml` files with an `[ignore]` table, read from the
package, then `~/.mackup/ignores/`, then `$XDG_CONFIG_HOME/mackup/ignores/`:

```toml
# ~/.mackup/ignores/mine.toml
[ignore]
name = "My junk"
patterns = ["*.bak", "*.orig"]
```

The built-in `syncthing.toml` covers `*.sync-conflict-*`, `~syncthing~*.tmp`,
`.syncthing.*.tmp`, `.stfolder`, `.stversions` and `.stignore`. A local file of
the same name replaces the built-in outright, so this turns the whole set off:

```toml
# ~/.mackup/ignores/syncthing.toml
[ignore]
patterns = []
```

A single application config can add patterns that apply to its own paths only:

```toml
# ~/.mackup/applications/notes.toml
name = "notes"
files = [".notes"]
ignore = ["*.bak"]
```

### Update check

At the end of `mackup sync`, mackup-ng checks whether a newer release is on
PyPI and prints one line if there is:

```text
mackup-ng 2.1.0 -> 2.2.0 available. Upgrade: uv tool upgrade mackup-ng
```

The upgrade command is guessed from where the running executable lives (snap,
uv tool, pipx, or plain pip). The result is cached under
`$XDG_CACHE_HOME/mackup/update-check.json` for a day, so at most one request a
day leaves the machine, and a dry run (`-n`) never checks at all. Any failure —
offline, timeout, a bad answer — is silent.

The request goes to `https://pypi.org/pypi/mackup-ng/json`. It carries nothing
but the package name, though like any request it discloses the machine's IP
address and the fact that mackup-ng is in use. To switch it off for good on a
machine:

```bash
mackup-ng mark no-update-check
```

## Supported Storages

- [Dropbox](https://www.dropbox.com/)
- [Google Drive](https://drive.google.com/)
- [iCloud](http://www.apple.com/icloud/)
- Anything able to sync a folder (e.g. [Git](http://git-scm.com/))

See the [README](doc/README.md) file in the doc directory for more info.

## Unsupported Storages

- [Box](https://www.box.com): No longer supported as it ignores dotfiles, see
  <https://github.com/lra/mackup/issues/807>.

## Supported Applications

- [1Password 4](https://agilebits.com/onepassword)
- [2Do](http://www.2doapp.com/)
- [Ack](http://beyondgrep.com/)
- [act](https://github.com/nektos/act)
- [ActivityWatch](http://activitywatch.net/)
- [Adium](https://adium.im/)
- [Adobe Camera Raw](http://www.adobe.com/products/photoshop/extend.html)
- [Adobe Illustrator CC](https://www.adobe.com/products/illustrator.html)
- [Adobe Photoshop CC](http://www.adobe.com/products/photoshop.html)
- [Adobe Photoshop Lightroom CC](https://www.adobe.com/products/photoshop-lightroom.html)
- [Adobe Photoshop Lightroom Classic](https://www.adobe.com/de/products/photoshop-lightroom-classic.html)
- [aerc](https://aerc-mail.org/)
- [AeroSpace](https://github.com/nikitabobko/AeroSpace)
- [Affinity Designer](https://affinity.serif.com/designer)
- [Affinity Photo](https://affinity.serif.com/photo)
- [Affinity Publisher](https://affinity.serif.com/publisher)
- [Airflow](https://airflowapp.com/)
- [Airmail](http://airmailapp.com/)
- [Akamai-CLI](https://developer.akamai.com/cli)
- [Alacritty](https://github.com/jwilm/alacritty)
- [AlDente](https://apphousekitchen.com/)
- [AltTab](https://alt-tab-macos.netlify.app/)
- [Amethyst](https://ianyh.com/amethyst/)
- [Ancient Domains of Mystery](http://www.adom.de/home/index.html)
- [Android Studio](https://developer.android.com/sdk/)
- [Ansible](http://www.ansible.com/)
- [AppCleaner](http://freemacsoft.net/appcleaner/)
- [AppCode](http://www.jetbrains.com/objc/)
- [Apple Music](https://www.apple.com/apple-music/)
- [Apptivate](http://www.apptivateapp.com/)
- [Arara](https://github.com/cereda/arara)
- [aria2c](http://aria2.sourceforge.net/)
- [Arm](https://www.atagar.com/arm/)
- [Artistic Style](http://astyle.sourceforge.net)
- [asciinema](https://asciinema.org/)
- [asdf version manager](https://github.com/asdf-vm/asdf)
- [Aspell](http://aspell.net/)
- [Atlantis](http://www.riverdark.net/atlantis/)
- [Atom](https://atom.io/)
- [Audacious](http://audacious-media-player.org/)
- [AusKey](https://abr.gov.au/AUSkey/)
- [Autokey](https://code.google.com/p/autokey/)
- [Awareness](http://iamfutureproof.com/tools/awareness/)
- [AWS Command Line Interface](https://aws.amazon.com/cli/)
- [Bartender](http://www.macbartender.com/)
- [Base](https://menial.co.uk/base/)
- [Bash it](https://github.com/Bash-it/bash-it)
- [Bash](http://www.gnu.org/software/bash/)
- [Bat](https://github.com/sharkdp/bat)
- [Bc](https://www.gnu.org/software/bc/)
- [Beatport Pro](https://www.beatport.com/desktop)
- [Beets](http://beets.io/)
- [BetterSnapTool](http://www.boastr.net/)
- [BetterTouchTool](http://www.boastr.net/)
- [Beyond Compare](https://scootersoftware.com/)
- [BibDesk](http://bibdesk.sourceforge.net/)
- [Billings Pro Server Admin](https://www.marketcircle.com/billingspro/download/billingspro-server/)
- [BitBar](https://getbitbar.com/)
- [Bitchx](http://www.bitchx.org/)
- [Blackfire](https://blackfire.io/)
- [ble.sh](https://github.com/akinomyoga/ble.sh)
- [Blender](https://blender.org/)
- [Boto](https://github.com/boto/boto)
- [Boxer](http://boxerapp.com)
- [Brackets](http://brackets.io/)
- [Brave](https://brave.com/)
- [Btop](https://github.com/aristocratos/btop)
- [Bump](https://github.com/fabiospampinato/bump)
- [Bundler](http://bundler.io)
- [Byobu](http://byobu.co/)
- [Caffeine](http://lightheadsw.com/caffeine/)
- [Calibre](https://calibre-ebook.com/)
- [Capture One](http://www.phaseone.com/Imaging-Software/Capture-One.aspx)
- [Cartographica](https://www.macgis.com/)
- [Cerebro](https://cerebroapp.com/)
- [Charles](http://www.charlesproxy.com)
- [Cheat](https://github.com/chrisallenlane/cheat)
- [Chef](https://www.chef.io/chef/)
- [Chicken](http://sourceforge.net/projects/chicken/)
- [Choosy](https://www.choosyosx.com/)
- [chunkwm](https://github.com/koekeishiya/chunkwm)
- [Cider](https://github.com/msanders/cider)
- [ClashX](https://github.com/yichengchen/clashX)
- [Clasp](https://github.com/google/clasp)
- [CleanShot](https://cleanshot.com/)
- [Clementine](https://www.clementine-player.org/)
- [CLion](https://www.jetbrains.com/clion/)
- [ClipMenu](http://www.clipmenu.com/)
- [Clipy](https://clipy-app.com/)
- [CloudApp](http://getcloudapp.com/)
- [Coda 2](http://panic.com/coda/)
- [Colloquy](http://colloquy.info/)
- [ColorSchemer Studio 2](http://www.colorschemer.com/osx_info.php)
- [ColorSlurp](http://colorslurp.com/)
- [ColorSync](https://en.wikipedia.org/wiki/ColorSync)
- [Composer](https://getcomposer.org/)
- [Concentrate](http://www.getconcentrating.com/)
- [Conky](https://github.com/brndnmtthws/conky)
- [Consular](https://github.com/achiu/consular)
- [Context7](https://context7.com/)
- [Contexts](https://contexts.co)
- [ControlPlane](http://www.controlplaneapp.com/)
- [CopyQ](https://github.com/hluk/CopyQ)
- [CoRD](http://cord.sourceforge.net/)
- [CotEditor](http://coteditor.com/)
- [Ctags](http://ctags.sourceforge.net/)
- [Cursor](https://cursor.sh/)
- [cVim](https://github.com/1995eaton/chromium-vim)
- [Cyberduck](https://cyberduck.io/)
- [DaisyDisk](https://daisydiskapp.com)
- [Dash](https://kapeli.com/dash)
- [DataGrip](https://www.jetbrains.com/datagrip/)
- [Day-O](http://www.shauninman.com/archive/2011/10/20/day_o_mac_menu_bar_clock)
- [DBeaver](https://dbeaver.io/)
- [DbVisualizer](https://www.dbvis.com/)
- [Deal Alert](http://dealalertapp.com/)
- [Deepin-dde-dock](https://github.com/linuxdeepin/dde-dock)
- [Deepin-dde-file-manager](https://www.deepin.org/en/original/dde-file-manager/)
- [Deepin-Terminal](https://github.com/linuxdeepin/deepin-terminal)
- [Default Folder X](http://www.stclairsoft.com/DefaultFolderX/)
- [Devil's Pie 2](http://www.gusnan.se/devilspie2/)
- [Devil's Pie](<https://en.wikipedia.org/wiki/Devil's_Pie_(software)>)
- [dig](<http://en.wikipedia.org/wiki/Dig_(command)>)
- [Divvy](http://mizage.com/divvy/)
- [Docker](https://www.docker.com/)
- [Dolphin](https://dolphin-emu.org/)
- [Doom Emacs](https://github.com/hlissner/doom-emacs)
- [Double Commander](http://doublecmd.sourceforge.net/)
- [Doxie](http://www.getdoxie.com/)
- [Dozer](https://github.com/Mortennn/Dozer)
- [Draft](https://draft.sh/)
- [Droplr](https://droplr.com/)
- [Dropzone 3](https://aptonic.com/dropzone3/)
- [Drush](http://www.drush.org/)
- [Eagle (ogdesign)](https://eagle.cool/)
- [EditorConfig](http://editorconfig.org/)
- [Electrum](https://electrum.org/#home)
- [Elgato StreamDeck](https://www.elgato.com/en/welcome-to-stream-deck)
- [Emacs](http://www.gnu.org/software/emacs/)
- [Enjoyable](https://yukkurigames.com/enjoyable/)
- [Environmental Station Alpha](http://www.hempuli.com/esa/)
- [eqMac2](https://bitgapp.com/eqmac/)
- [ESLint](https://eslint.org/)
- [espanso](https://espanso.org)
- [Exercism](http://exercism.io/)
- [ExpanDrive](http://www.expandrive.com/)
- [Factorio](https://www.factorio.com)
- [Factory Droid](https://factory.ai/)
- [Fantastical](http://flexibits.com/fantastical)
- [fasd](https://github.com/clvv/fasd)
- [fastlane](https://fastlane.tools)
- [FastScripts](https://redsweater.com/fastscripts/)
- [Feeds](http://www.feedsapp.com/)
- [FileZilla](https://filezilla-project.org/)
- [Finicky](https://github.com/johnste/finicky)
- [Fish](http://fishshell.com/)
- [Fisher](https://github.com/jorgebucaran/fisher)
- [Flake8](https://flake8.pycqa.org/)
- [Flameshot](https://flameshot.org)
- [FlexGet](http://flexget.com/)
- [Flux](https://justgetflux.com/)
- [Focus](https://heyfocus.com)
- [Fontconfig](https://www.freedesktop.org/wiki/Software/fontconfig/)
- [FontExplorer X](http://www.fontexplorerx.com/)
- [Forge](http://www.slightlymagic.net/wiki/Forge)
- [Fork](https://git-fork.com/)
- [ForkLift](http://www.binarynights.com/forklift/)
- [Franz](https://meetfranz.com)
- [Gas Mask](https://github.com/2ndalpha/gasmask/)
- [gdb](https://www.gnu.org/software/gdb/)
- [Gear Player](https://www.gearmusicplayer.com/)
- [GeekTool](http://projects.tynsoe.org/en/geektool/)
- [GHCi](https://wiki.haskell.org/GHC/GHCi)
- [Ghidra](https://ghidra-sre.org)
- [Ghostty](https://ghostty.org/)
- [Ghostwriter](https://wereturtle.github.io/ghostwriter/)
- [Gimp](https://www.gimp.org/)
- [Git Hooks](https://github.com/git-hooks/git-hooks)
- [Git](http://git-scm.com/)
- [Gitbox](http://gitboxapp.com/)
- [GitFox](https://www.gitfox.app)
- [GitHub CLI](https://cli.github.com/)
- [GitKraken](https://www.gitkraken.com)
- [GitUp](http://gitup.co/)
- [Gmail Notifr](http://ashchan.com/projects/gmail-notifr)
- [gmailctl](https://github.com/mbrt/gmailctl)
- [GMVault](http://gmvault.org/)
- [Gnome SSH Tunnel Manager](http://sourceforge.net/projects/gstm/)
- [GNU Stow](https://www.gnu.org/software/stow/)
- [GnuPG](https://www.gnupg.org/)
- [Go2Shell](http://zipzapmac.com/Go2Shell)
- [Goku](https://github.com/yqrashawn/GokuRakuJoudo)
- [GoLand](https://www.jetbrains.com/go/)
- [Goldendict](http://goldendict.org/)
- [GoodSync](https://goodsync.com/)
- [GoShare](https://github.com/dictget/goshare)
- [Gradle](http://gradle.org)
- [GrandTotal 3](http://www.mediaatelier.com/GrandTotal4/)
- [grsync](http://www.opbyte.it/grsync/)
- [Hammerspoon](http://www.hammerspoon.org/)
- [HandBrake](https://handbrake.fr/)
- [Hands Off!](http://www.oneperiodic.com/products/handsoff/)
- [Hazel](http://www.noodlesoft.com/hazel.php)
- [Helix](https://helix-editor.com/)
- [Hero Lab](http://www.wolflair.com/index.php?context=hero_lab)
- [Heroku](https://www.heroku.com/)
- [HexChat](https://hexchat.github.io/)
- [Hexels](http://hexraystudios.com/hexels/)
- [Hocus Focus](http://hocusfoc.us/)
- [Homebrew](https://brew.sh)
- [Homebridge](https://github.com/nfarina/homebridge)
- [Houdini](http://uglyapps.co.uk/houdini/)
- [Hstr](https://github.com/dvorka/hstr)
- [HTML Tidy](https://www.html-tidy.org/)
- [Htop](http://htop.sourceforge.net/)
- [HTTPie](https://httpie.org/)
- [hub](https://hub.github.com)
- [Hyper.app](https://hyper.is/)
- [HyperDock](https://bahoom.com/hyperdock)
- [HyperSwitch](https://bahoom.com/hyperswitch)
- [i2cssh](https://github.com/wouterdebie/i2cssh)
- [i3](https://i3wm.org/)
- [IDA Pro](https://www.hex-rays.com/products/ida/)
- [IdeaVim](https://github.com/JetBrains/ideavim)
- [IINA](https://iina.io)
- [Inkscape](https://inkscape.org/)
- [Insomnia](https://insomnia.rest/)
- [IntelliJIDEA](http://www.jetbrains.com/idea/)
- [IPython](http://ipython.org/)
- [Irssi](http://www.irssi.org/)
- [iStat Menus](https://bjango.com/mac/istatmenus/)
- [iTerm2](https://www.iterm2.com/)
- [iTermocil](https://github.com/TomAnthony/itermocil)
- [Itsycal](https://github.com/sfsam/Itsycal)
- [iTunes Scripts](https://www.apple.com/)
- [JankyBorders](https://github.com/FelixKratz/JankyBorders)
- [Janus](https://github.com/carlhuda/janus)
- [Jitouch](http://www.jitouch.com/)
- [Joplin](https://joplinapp.org/)
- [jrnl](https://jrnl.sh)
- [JS Beautifier](https://github.com/beautify-web/js-beautify)
- [JSHint](http://jshint.com/)
- [Julia](http://julialang.org)
- [Jumpcut](http://jumpcut.sourceforge.net/)
- [Jupyter](http://jupyter.org/)
- [k9s](https://k9scli.io/)
- [Kaggle](https://kaggle.com/)
- [Kaleidoscope](http://www.kaleidoscopeapp.com/)
- [Karabiner Elements](https://github.com/tekezo/Karabiner-Elements)
- [Karabiner](https://pqrs.org/osx/karabiner/)
- [Kdenlive](https://kdenlive.org/)
- [KeePassX](http://www.keepassx.org/)
- [KeePassXC](https://keepassxc.org/)
- [KeepingYouAwake](https://github.com/newmarcel/KeepingYouAwake)
- [Keka](http://www.kekaosx.com/en/)
- [Keybase](https://keybase.io/)
- [Keyboard Maestro](http://www.keyboardmaestro.com)
- [Keymo](http://manytricks.com/keymo/)
- [KeyRemap4MacBook](https://pqrs.org/osx/karabiner/)
- [Khd](https://github.com/koekeishiya/khd/)
- [Kiro](https://kiro.dev/)
- [kitty](https://sw.kovidgoyal.net/kitty/)
- [Krew](https://github.com/kubernetes-sigs/krew)
- [Kubectl](https://kubernetes.io/docs/reference/kubectl/overview/)
- [Kwm](https://koekeishiya.github.io/kwm/)
- [LaTeXiT](http://www.chachatelier.fr/latexit/latexit-home.php?lang=en)
- [LaunchBar](https://www.obdev.at/products/launchbar/index.html)
- [lazydocker](https://github.com/jesseduffield/lazydocker)
- [lazygit](https://github.com/jesseduffield/lazygit)
- [Ledger](http://ledger-cli.org)
- [Leiningen](http://leiningen.org/)
- [lf](https://github.com/gokcehan/lf)
- [LibreOffice](https://www.libreoffice.org/)
- [Liftoff](https://github.com/thoughtbot/liftoff)
- [Light Table](http://lighttable.com/)
- [LightPaper](https://getlightpaper.com/)
- [LimeChat](http://limechat.net/mac/)
- [Liquid Prompt](https://github.com/nojhan/liquidprompt)
- [LittleSnitch](http://www.obdev.at/products/littlesnitch/)
- [Livestreamer](http://livestreamer.tanuki.se/)
- [Logitech Options](https://www.logitech.com/en-us/product/options)
- [Logseq](https://logseq.com/)
- [Lollypop](https://gnumdk.github.io/lollypop-web/)
- [Loopback](https://rogueamoeba.com/loopback/)
- [Luftrausers](http://luftrausers.com)
- [LunarVim](https://www.lunarvim.org/)
- [MacDive](http://www.mac-dive.com/)
- [MacDown](http://macdown.uranusjr.com/)
- [MacOSX](http://www.apple.com/osx/)
- [MacVim](https://github.com/macvim-dev/macvim)
- [Magic Launch](https://www.oneperiodic.com/products/magiclaunch/)
- [MagicPrefs](http://magicprefs.com/)
- [Magnet](https://magnet.crowdcafe.com/)
- [Maid](https://github.com/benjaminoakes/maid/)
- [Mail](https://support.apple.com/guide/mail/welcome/mac)
- [Mailmate](http://freron.com/)
- [Mailplane](http://mailplaneapp.com/)
- [mako](https://wayland.emersion.fr/mako/)
- [Marked 2](http://marked2app.com)
- [Marta](https://marta.yanex.org/)
- [MATLAB](http://www.mathworks.com/products/matlab/)
- [Maven](http://maven.apache.org)
- [Max](http://sbooth.org/Max/)
- [Mendeley Desktop](https://www.mendeley.com)
- [MenuMeters](http://www.ragingmenace.com/software/menumeters/)
- [Mercurial](https://www.mercurial-scm.org/)
- [MercuryMover](http://www.heliumfoot.com/mercurymover/)
- [Messages](http://www.apple.com/osx/apps/#messages)
- [Micro](https://github.com/zyedidia/micro)
- [Microsoft Azure CLI](https://github.com/Azure/azure-xplat-cli)
- [Microsoft Remote Desktop](https://itunes.apple.com/us/app/microsoft-remote-desktop-10/id1295203466)
- [mise-en-place](https://github.com/jdx/mise)
- [mitmproxy](https://mitmproxy.org/)
- [mkcert](https://github.com/FiloSottile/mkcert)
- [Mole](https://github.com/tw93/Mole)
- [MonoDevelop](http://www.monodevelop.com)
- [Moom](http://manytricks.com/moom/)
- [Mosaic](https://lightpillar.com/mosaic.html)
- [Mou](http://25.io/mou/)
- [mpd](http://www.musicpd.org)
- [MPlayerX](http://mplayerx.org)
- [MPS Youtube](https://github.com/mps-youtube/mps-youtube)
- [MPV](https://mpv.io/)
- [MTMR](https://github.com/Toxblh/MTMR)
- [Multitouch](https://multitouch.app/)
- [Mumu](https://getmumu.com)
- [MusicBrainz Picard](https://picard.musicbrainz.org/)
- [MuteSpotifyAds](https://github.com/simonmeusel/MuteSpotifyAds)
- [mycli](https://www.mycli.net/)
- [myrepos](https://github.com/joeyh/myrepos)
- [MySQL Workbench](https://www.mysql.com/products/workbench/)
- [MySQL](http://www.mysql.com/)
- [Name Mangler](http://manytricks.com/namemangler/)
- [Nano](http://www.nano-editor.org/)
- [Navicat](http://navicat.com/)
- [ncmpcpp](http://rybczak.net/ncmpcpp/)
- [Neofetch](https://github.com/dylanaraps/neofetch)
- [neovim](https://github.com/neovim/neovim)
- [Nethack](http://www.nethack.org)
- [Netlify](https://www.netlify.com/)
- [newsbeuter](http://newsbeuter.org/)
- [ngrok](https://ngrok.com/)
- [ni](https://github.com/antfu/ni/)
- [Nomacs](http://nomacs.org/)
- [NoSQLBooster for MongoDB](https://www.nosqlbooster.com/)
- [notion-enhancer](https://notion-enhancer.github.io/)
- [Nova](https://www.nova.app/)
- [npm](https://www.npmjs.com/)
- [npmrc](https://github.com/deoxxa/npmrc/)
- [NSLogger](https://github.com/fpillet/NSLogger)
- [nuget](https://www.nuget.org/)
- [Nushell](https://www.nushell.sh/)
- [nvALT](http://brettterpstra.com/projects/nvalt/)
- [nvm](https://github.com/nvm-sh/nvm)
- [nvpy](https://github.com/cpbotha/nvpy)
- [OBS](https://obsproject.com)
- [OfflineIMAP](https://www.offlineimap.org/)
- [Oh My Fish](https://github.com/bpinto/oh-my-fish)
- [Oh My Tmux](https://github.com/gpakosz/.tmux)
- [okta-awscli](https://github.com/okta-awscli/okta-awscli)
- [OmniFocus](https://www.omnigroup.com/omnifocus/)
- [OmniGraffle](https://www.omnigroup.com/omnigraffle/)
- [Openbox](http://openbox.org)
- [OpenCode](https://opencode.ai)
- [OpenEmu](http://openemu.org)
- [OpenSSH](http://www.openssh.com/)
- [Opera](http://www.opera.com)
- [Oracle Cloud Infrastructure CLI](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/cliconcepts.htm)
- [Paintbrush](http://paintbrush.sourceforge.net/)
- [Pandoc](http://pandoc.org)
- [Pass](http://www.passwordstore.org/)
- [Pastebot](http://tapbots.com/software/pastebot/)
- [Path Finder](http://www.cocoatech.com/pathfinder/)
- [PDFjam](https://warwick.ac.uk/fac/sci/statistics/staff/academic-research/firth/software/pdfjam/)
- [Pear](http://pear.php.net/)
- [Pentadactyl](http://5digits.org/pentadactyl/)
- [Perl](https://www.perl.org/)
- [Phoenix](https://github.com/kasper/phoenix)
- [PhoneView](https://www.ecamm.com/mac/phoneview/)
- [PhpStorm](http://www.jetbrains.com/phpstorm/)
- [PicGo](https://github.com/Molunerfinn/PicGo)
- [Pidgin](https://www.pidgin.im)
- [PIP](http://www.pip-installer.org/)
- [PixelSnap 2](https://getpixelsnap.com/)
- [PixelSnap](https://getpixelsnap.com/)
- [Planner](https://useplanner.com/)
- [Plover](http://www.openstenoproject.org/plover/)
- [Pnpm](https://pnpm.js.org/)
- [Pock](https://pock.pigigaldi.com)
- [Podman](https://podman.io/)
- [Poedit](http://poedit.net/)
- [Poetry](https://python-poetry.org)
- [PokerStars](https://www.pokerstars.com/)
- [Polybar](https://polybar.github.io/)
- [PopClip](http://pilotmoon.com/popclip/)
- [Popcorn-Time](https://popcorntime.io/)
- [PostgreSQL](http://www.postgresql.org/)
- [Postico](https://eggerapps.at/postico/)
- [Pow](http://pow.cx/)
- [Powerlevel10k](https://github.com/romkatv/powerlevel10k)
- [Powerline-shell](https://github.com/b-ryan/powerline-shell)
- [Powerline](https://github.com/powerline/powerline)
- [Prezto](https://github.com/sorin-ionescu/prezto)
- [Processing](https://processing.org/)
- [Proselint](https://github.com/amperser/proselint)
- [ProxyChains NG](http://sourceforge.net/projects/proxychains-ng/)
- [ProxyChains](http://proxychains.sourceforge.net)
- [Proxyman](https://proxyman.io)
- [PrusaSlicer](https://www.prusa3d.com/prusaslicer/)
- [PsySH](https://psysh.org/)
- [Punto Switcher](https://punto.yandex.ru/)
- [PyCharm](https://www.jetbrains.com/pycharm/)
- [PyPI](https://pypi.python.org/pypi)
- [PyRadio](http://www.coderholic.com/pyradio/)
- [Querious](http://www.araelium.com/querious/)
- [Quicksilver](http://qsapp.com/)
- [Quitter](https://marco.org/apps)
- [Qutebrowser](http://qutebrowser.org/)
- [Qv2ray](https://qv2ray.net/)
- [R](http://www.r-project.org/)
- [Rails](http://rubyonrails.org/)
- [Ranger](https://ranger.github.io/)
- [Rbenv](https://www.github.com/rbenv/rbenv)
- [Rclone](https://rclone.org/)
- [Rectangle](https://rectangleapp.com/)
- [Redshift Scheduler](https://github.com/spantaleev/redshift-scheduler)
- [Redshift](http://jonls.dk/redshift/)
- [Remote Desktop Manager](https://remotedesktopmanager.com/)
- [Rhythmbox](https://wiki.gnome.org/Apps/Rhythmbox)
- [Rime](http://rime.im/)
- [ripgrep](https://github.com/BurntSushi/ripgrep)
- [Robo 3T](http://robomongo.org/)
- [Rocket](https://matthewpalmer.net/rocket/)
- [Rofi](https://github.com/DaveDavenport/rofi)
- [Royal TSX](http://www.royaltsx.com/ts/osx/features)
- [RStudio](https://www.rstudio.com/)
- [rTorrent](http://libtorrent.rakshasa.no/)
- [rtx](https://github.com/jdx/rtx)
- [rubiTrack 5](https://www.rubitrack.com)
- [Rubocop](https://github.com/bbatsov/rubocop)
- [Ruby Version Manager](https://rvm.io/)
- [Ruby Version](https://gist.github.com/fnichol/1912050)
- [Ruby](https://www.ruby-lang.org/)
- [RubyMine](http://www.jetbrains.com/ruby/)
- [Rust](https://www.rust-lang.org/)
- [RustRover](https://www.jetbrains.com/rust/)
- [S3cmd](http://s3tools.org/s3cmd)
- [SABnzbd](http://sabnzbd.org/)
- [SBCL](http://www.sbcl.org/)
- [SBT](http://www.scala-sbt.org/)
- [Scenario](http://www.lagentesoft.com/scenario/)
- [Screen](http://www.gnu.org/software/screen/)
- [Screenhero](https://screenhero.com)
- [Scrivener](http://www.literatureandlatte.com/scrivener.php)
- [Scroll Reverser](https://pilotmoon.com/scrollreverser/)
- [Secure Pipes](http://www.opoet.com/)
- [SecureCRT](https://www.vandyke.com/products/securecrt/)
- [Seil](https://pqrs.org/osx/karabiner/seil.html.en)
- [SelfControl](http://selfcontrolapp.com/)
- [Sequel Pro](http://www.sequelpro.com/)
- [ShadowsocksX-NG](https://github.com/shadowsocks/ShadowsocksX-NG)
- [ShiftIt](https://github.com/fikovnik/ShiftIt)
- [Shifty](https://shifty.natethompson.io/)
- [Shimo](https://www.feingeist.io/shimo/)
- [ShowyEdge](https://pqrs.org/osx/ShowyEdge/index.html.en)
- [SHSH Blobs](https://en.wikipedia.org/wiki/SHSH_blob)
- [Shuttle](http://fitztrev.github.io/shuttle/)
- [SizeUp](http://www.irradiatedsoftware.com/sizeup/)
- [Sizzy](https://sizzy.co/)
- [SketchyBar](https://felixkratz.github.io/SketchyBar/)
- [skhd](https://github.com/koekeishiya/skhd/)
- [Skim](http://skim-app.sourceforge.net/)
- [Skitch](https://evernote.com/skitch/)
- [Slate](https://github.com/jigish/slate)
- [Slic3r](http://slic3r.org)
- [Slogger](http://brettterpstra.com/projects/slogger/)
- [SmartGit](http://www.syntevo.com/smartgit/)
- [Smooth Mouse](http://smoothmouse.com/)
- [Soulver](http://www.acqualia.com/soulver/)
- [SourceTree](https://www.sourcetreeapp.com/)
- [SpaceLauncher](https://spacelauncherapp.com)
- [Spacemacs](https://github.com/syl20bnr/spacemacs)
- [SpaceVim](https://github.com/SpaceVim/SpaceVim)
- [SpamSieve](https://c-command.com/spamsieve)
- [Spark](http://www.shadowlab.org/softwares/spark.php)
- [Spectacle](https://www.spectacleapp.com/)
- [Spectrwm](https://github.com/conformal/spectrwm/wiki)
- [Splice](https://splice.com/)
- [Spotify Notifications](http://spotify-notifications.citruspi.io/)
- [Spotify](https://www.spotify.com/)
- [Sqitch](https://sqitch.org/)
- [Starship](https://starship.rs/)
- [Startupizer2](http://appledoc.gentlebytes.com/startupizer/)
- [Stata](http://www.stata.com/)
- [Stats](https://github.com/exelban/stats)
- [Stay](https://cordlessdog.com/stay/)
- [Storyist](http://storyist.com/)
- [Subler](https://subler.org)
- [Sublime Merge](https://www.sublimemerge.com/)
- [Sublime Text](http://www.sublimetext.com/)
- [Subversion](http://subversion.apache.org/)
- [SuperDuper!](http://www.shirt-pocket.com/SuperDuper/SuperDuperDescription.html)
- [Surge](http://surge.run/manual/)
- [Sway](https://swaywm.org/)
- [Swinsian](http://swinsian.com/)
- [Swish](https://highlyopinionated.co/swish/)
- [SwitchHosts](https://github.com/oldj/SwitchHosts)
- [T](http://sferik.github.io/t/)
- [TablePlus](https://tableplus.io)
- [TaskPaper](https://www.taskpaper.com)
- [Taskwarrior](http://taskwarrior.org/)
- [Teamocil](https://github.com/remi/teamocil)
- [Telegram for macOS](https://macos.telegram.org)
- [Terminal](http://www.apple.com/osx/apps/)
- [Terminator](https://launchpad.net/terminator/)
- [termite](https://github.com/thestinger/termite)
- [Termux](https://termux.dev/)
- [Terraform](https://developer.hashicorp.com/terraform)
- [TextExpander](https://smilesoftware.com/textexpander)
- [TextMate](http://macromates.com/)
- [Textual](http://www.codeux.com/textual/)
- [Things](https://culturedcode.com/things/)
- [Tig](https://github.com/jonas/tig)
- [Tiles](https://www.sempliva.com/tiles/)
- [Tilix](https://github.com/gnunn1/tilix)
- [Timeout](https://www.dejal.com/timeout/)
- [tint2](https://code.google.com/p/tint2/)
- [TinyFugue](http://tinyfugue.sourceforge.net)
- [Tmux](http://tmux.sourceforge.net/)
- [Tmuxinator](https://github.com/tmuxinator/tmuxinator)
- [Tmuxp](https://github.com/tony/tmuxp)
- [Todo.txt CLI](http://todotxt.com/)
- [ToothFairy](https://c-command.com/toothfairy/)
- [TotalSpaces2](http://totalspaces.binaryage.com/)
- [Tower](http://www.git-tower.com/)
- [Transmission](http://www.transmissionbt.com/)
- [Transmit](http://panic.com/transmit/)
- [TripMode](https://www.tripmode.ch)
- [Trizen](https://github.com/trizen/trizen)
- [Tunnelblick](https://tunnelblick.net)
- [tvnamer](https://github.com/dbr/tvnamer)
- [Twitterrific](http://twitterrific.com/)
- [Typinator](http://www.ergonis.com/products/typinator/)
- [Typora](https://typora.io)
- [Übersicht](http://tracesof.net/uebersicht/)
- [ulauncher](https://ulauncher.io/)
- [uTorrent](http://www.utorrent.com/)
- [Ventrilo](http://www.ventrilo.com/)
- [Verdaccio](https://verdaccio.org/)
- [Versions](http://www.versionsapp.com)
- [Vim](http://www.vim.org/)
- [Vimperator](http://www.vimperator.org/vimperator)
- [Vimwiki](https://vimwiki.github.io/)
- [Viscosity](http://www.sparklabs.com/viscosity/)
- [Visual Studio Code - Insiders](https://code.visualstudio.com/insiders)
- [Visual Studio Code - OSS](https://github.com/Microsoft/vscode)
- [Visual Studio Code](https://code.visualstudio.com/)
- [Visual Studio for Mac](https://www.visualstudio.com/vs/visual-studio-mac/)
- [VLC](http://www.videolan.org/)
- [Volt](https://github.com/vim-volt/volt)
- [VSCodium](https://vscodium.com/)
- [Wakatime](https://wakatime.com/)
- [Warp](https://www.warp.dev)
- [waybar](https://github.com/Alexays/Waybar)
- [WebStorm](https://www.jetbrains.com/webstorm/)
- [WezTerm](https://wezfurlong.org/wezterm/)
- [Wget](https://www.gnu.org/software/wget/)
- [WhatsApp Web](https://web.whatsapp.com/)
- [Windsurf](https://www.codeium.com)
- [Wireshark 2](https://www.wireshark.org)
- [Witch](http://manytricks.com/witch/)
- [WordGrinder](https://cowlark.com/wordgrinder/)
- [WordPress WP-CLI](http://wp-cli.org/)
- [Workrave](http://www.workrave.org/)
- [X11](http://www.x.org/)
- [Xamarin Studio](https://xamarin.com/studio)
- [xbar](https://xbarapp.com/)
- [XBindKeys](http://www.nongnu.org/xbindkeys/)
- [Xchat](http://xchat.org/)
- [Xcode](https://developer.apple.com/xcode/)
- [Xee](https://theunarchiver.com/xee)
- [XEmacs](http://www.xemacs.org/)
- [XLD](http://tmkk.undo.jp/xld/)
- [Xonsh](https://xon.sh)
- [XtraFinder](http://www.trankynam.com/xtrafinder/)
- [yabai](https://github.com/koekeishiya/yabai)
- [yarn](https://yarnpkg.com)
- [yazi](https://github.com/sxyazi/yazi)
- [youtube-dl](https://ytdl-org.github.io/youtube-dl/)
- [Yummy FTP](http://www.yummysoftware.com/)
- [zabbix-cli](https://github.com/usit-gd/zabbix-cli)
- [zathura](https://pwmt.org/projects/zathura/)
- [zed](https://zed.dev/)
- [Zoom](http://zoom.com/)
- [zoxide](https://github.com/ajeetdsouza/zoxide)
- [Zsh](http://zsh.sourceforge.net/)

## Can you support application X

We can [with your help](doc#get-official-support-for-an-application) ;)

## Personalization & configuration

Have an application that shouldn't be generally supported but that you use?
Or some personal files you want to sync, e.g. various config files in a `~/.config/`
directory or your personal `~/.gitignore`?

- Create a `~/.mackup` directory to [sync an application or any file or directory](doc#add-support-for-an-application-or-any-file-or-directory)

## Fork Additions

This fork adds path templating for application config definitions (`*.toml` in
`src/mackup_ng/applications`) to reduce duplication and simplify cross-platform
entries. App definitions are **flat TOML** (no `[application]` wrapper):
top-level `name` and a `files` array (plus an optional
`[mapped_files]` table and action blocks). A legacy `[application]` table is
still accepted.

### 1. Brace expansion (`{...}`)

You can define multiple paths in one line:

```toml
name = "Code"
files = [
    "${MACKUP_XDG_CONFIG}/Code/User/{snippets,keybindings.json,settings.json}",
]
```

This expands to one entry per item (cartesian product if multiple brace groups
are used).

### 2. Platform selector (`[...]`)

You can choose different path fragments per platform:

```toml
files = [
    "${MACKUP_XDG_CONFIG}/[mac:Blender,blender]",
]
```

Another example with a full-path fallback:

```toml
files = [
    "[linux:${MACKUP_XDG_CONFIG}/myapp/linux.conf,mac:${MACKUP_XDG_CONFIG}/MyApp/mac.conf,windows:${MACKUP_XDG_CONFIG}/MyApp/windows.conf,${MACKUP_XDG_CONFIG}/myapp/other.conf]",
]
```

- `linux:`, `mac:`, `windows:` are supported keys
- the last unkeyed item is the fallback
- in this fork, the fallback also acts as the canonical backup path

This means the selector can map different local paths to one shared backup path.
Example:

```toml
files = [
    "[mac:${MACKUP_XDG_CONFIG}/MyApp/config.json,linux:${MACKUP_XDG_CONFIG}/myapp/config.json,${MACKUP_XDG_CONFIG}/shared/myapp-config.json]",
]
```

Behavior:

- macOS local path: `${MACKUP_XDG_CONFIG}/MyApp/config.json`
- Linux local path: `${MACKUP_XDG_CONFIG}/myapp/config.json`
- backup path (all platforms): canonical Linux path for the fallback, i.e. `.config/shared/myapp-config.json`

### 3. Built-in XDG variables

These reserved Mackup-owned aliases (not OS environment variables) mimic the XDG
base directories on **every** OS, even ones that don't set the `XDG_*` env vars.
The `MACKUP_` prefix keeps them distinct from real `${VAR}` env references; `XDG`
marks the semantics:

- `${MACKUP_XDG_CONFIG}` -> `.config` (Linux) / `Library/Application Support` (macOS) / `AppData/Roaming` (Windows)
- `${MACKUP_XDG_DATA}` -> `.local/share` (Linux) / `Library/Application Support` (macOS) / `AppData/Local` (Windows)
- `${MACKUP_XDG_STATE}` -> `.local/state` (Linux) / `Library/Application Support` (macOS) / `AppData/Local` (Windows)
- `${MACKUP_XDG_CACHE}` -> `.cache` (Linux) / `Library/Caches` (macOS) / `AppData/Local` (Windows)

Important in this fork:

- built-in variables in local paths are resolved for the current OS
- built-in variables in backup paths are always resolved to Linux canonical paths
  (e.g. `${MACKUP_XDG_CONFIG}` in backup becomes `.config`)

### 4. Environment variables (`${VAR}` + `source_env`)

Any `${VAR}` that is not a reserved `MACKUP_*` built-in is resolved as a real
environment variable, falling back to `KEY=VALUE` lines in the app's
`source_env` files. It expands to the same value on both the local and backup
side, so use it for relative, machine-specific fragments (a profile dir name,
a hostname). Unresolved or absolute results skip just that entry.

```toml
name = "Firefox"
source_env = ["~/.config/mackup-env"]   # KEY=VALUE lines; env takes priority
files = [
    "${MACKUP_XDG_CONFIG}/firefox/${FF_PROFILE}/prefs.js",
]
```

### 5. Processing order

Path templates are resolved in this order:

1. Platform selector `[...]` (produces local path + canonical backup path)
2. Built-in variables (`${MACKUP_XDG_CONFIG}`, `${MACKUP_XDG_DATA}`, `${MACKUP_XDG_STATE}`, `${MACKUP_XDG_CACHE}`)
3. Environment variables (any other `${VAR}`, from env / `source_env`)
4. Brace expansion `{...}`

### 6. Config style in this fork

- Upstream-style `xdg_configuration_files` is not used in this fork; express entries directly in
  `files` using `${MACKUP_XDG_CONFIG}/...`
- many app definitions in this fork were normalized to use `${MACKUP_XDG_CONFIG}`,
  `${MACKUP_XDG_DATA}`, and selectors to avoid macOS/Linux duplicates
  (for example VS Code-family configs)

### 7. Explicit local → backup mapping (`[mapped_files]`)

`files` keeps the local path and storage layout identical. To
decouple them, add a `[mapped_files]` table with `LOCAL = BACKUP` pairs:

```toml
[mapped_files]
".config/app/grisa.profile/user.js" = ".config/app/profile/user.js"
```

Paths are quoted TOML strings, so spaces, dashes and even `->` are safe inside
them. Both sides honor selectors, built-in vars and braces (brace groups zip
pairwise). Handy when a machine-specific local path (e.g. a per-machine Firefox
profile dir) should share one canonical path in the backup folder.

One backup file can feed several local files — repeat the value:

```toml
[mapped_files]
".config/app/work.profile/user.js"     = ".config/app/profile/user.js"
".config/app/personal.profile/user.js" = ".config/app/profile/user.js"
```

All members of such a group are peers: whichever copy you edited last wins and
is propagated to the others on the next `mackup sync`.

Destinations are unique. If a later config maps the same local path to a
different backup file, the earlier mapping is dropped — that is how you
overwrite a stock config with your own. Configs are read stock first, then
`$XDG_CONFIG_HOME/mackup/applications`, then `~/.mackup/applications`, so your
own files always win. Run `mackup sync -v` to see which mappings were
overridden and which backup files are left without a destination.

An orphaned backup file (no destination maps to it) is left untouched; it is
only reported by `mackup sync -v`, never deleted on its own. `mackup rm <path>`
removes one destination and tombstones it — the shared backup source survives
as long as another destination still feeds from it, and is only deleted once
the last destination is removed. Re-declaring a destination with the *same*
backup file is not an override and is not reported.

`mackup rm` also accepts a path *inside* a managed directory. Because the
members of a group mirror each other, such a removal is applied to the whole
group: the file goes from the backup source and from every destination, and
the tombstone keeps it from coming back on the next sync.

### 8. Action blocks

A config file can also carry **action blocks** — imperative steps run around its
file sync (`pre`/`post`). A block has an optional `[when]` conditions sub-table
and exactly one action sub-table; there is no `type` key. Actions: `[copy]`,
`[chmod]`, `[run]`, `[xml]` (edit XML), `[systemd]` (user drop-in).

```toml
name = "SSH"
files = [".ssh"]

# after syncing .ssh, fix its permissions (default phase = post)
[when]
os = ["linux", "macos"]
[chmod]
path = "~/.ssh"
recursive = true
dir_mode = "700"
file_mode = "600"
```

`[when]` keys (any-of lists): `os`, `arch`, `marker`, `not_marker`, `command`,
`gui`, `exists`, `not_exists`, `env`. For more than one block per file use a
`[[block]]` array with `[block.when]` / `[block.<action>]`. Configs run sorted
by filename; `mackup apply` runs blocks without syncing. A block-only file (no
`files`) is a pure hook.

Conditions written at the top level of a config gate the **whole** config —
its synced files as well as its actions. A config whose conditions do not hold
on this machine declares nothing, so a mapping from another config keeps the
destination. That is how one machine can take a different source for the same
local file:

```toml
# ~/.mackup/applications/zz-termux-colors-eink.toml
[when]
os = ["android"]
marker = ["eink"]

[mapped_files]
".termux/colors.properties" = ".termux/colors-eink.properties"
```

Run `mackup show <app>` to see whether a config's conditions hold here, and
`mackup sync -v` to list the configs skipped for that reason. To gate a single
action instead of the config, put the condition inside `[[block]]` as
`[block.when]`.

Top-level keys (`files`, `mapped_files`, etc.) must come **before** the
`[when]` header in the file. TOML assigns a bare `key = value` line to
whichever table opened above it — write `files = [...]` after `[when]` and it
becomes `when.files` instead of the config's own file list, so the config
silently syncs nothing. Loading a config warns about this: an unrecognized
key inside `[when]` or a `[when]` that isn't a table at all both print a
`Warning:` line naming the config and the problem.

### 9. Machine-local extras (`~/.mackup/`)

Beyond custom app configs, `~/.mackup/` is the home for machine-local behavior:

```text
~/.mackup/
├── applications/   config *.toml files: sync lists AND action blocks
├── markers/        LOCAL marker definitions (*.toml, same format as apps)
└── dconf-backup/   dconf dumps (*.dconf)
```

Marker *state* (which markers are on) lives in
`$XDG_STATE_HOME/mackup/markers/` (default `~/.local/state/mackup/markers/`), not
under `~/.mackup/`; a pre-XDG `~/.mackup/markers/` is migrated automatically.

Marker state is not the only machine-local state: `sync` also records what it
did to each destination in `$XDG_STATE_HOME/mackup/sync-log.json`, which is what
`mackup-ng info` reports as "Last sync". Both stay out of the synced backup
folder, since they describe this machine only.

- **Markers** (`mark`/`unmark`/`markers`) are empty flag files gating behavior on
  one machine only. `backup` marks the source machine.
- **dconf** (Linux/GNOME): the backup-role machine dumps tracked paths before the
  file sync; other machines load them after. Opt out with the `no-dconf` marker;
  register paths with `dconf-add`.
- **Action blocks** (in `applications/*.toml`, applied during `sync` / via
  `apply`): each config file may carry blocks — a top-level implicit block
  and/or a `[[block]]` array. A block = base scalars + a `[when]` conditions
  sub-table + exactly one **action sub-table** whose name is the action
  (`[copy]` / `[chmod]` / `[run]` / `[xml]` / `[systemd]`); no `type` key. Base
  scalars: `phase` (`pre`/`post`, relative to that config's file sync) and
  optional `restart_service`. `[when]` holds short-keyed conditions (`os`,
  `arch`, `marker`, `not_marker`, `command`, `gui`, `exists`, `not_exists`,
  `env`). In a `[[block]]` array the sub-tables are `[block.when]` /
  `[block.<action>]`; at the top level `[when]` / `[<action>]`. Configs apply
  sorted by filename — cross-cutting hooks use numeric prefixes (`10-`, `40-`).
- **Environment contract**: `[run]` blocks receive a `MACKUP_*` environment
  (`MACKUP_ROLE`, `MACKUP_OS`, `MACKUP_ARCH`, `MACKUP_CONFIG_DIR`,
  `MACKUP_BACKUP_DIR`, `MACKUP_MARKERS_DIR`,
  `MACKUP_DCONF_BACKUP_DIR`, ...). A pre-sync executable is a `[run]` block with
  `phase = "pre"`.

Requires Python 3.12+.

## Why did you do this

Yesterday, I had a talk with [Zach Zaro](http://zacharyzaro.com/), complaining
about the pain it is to reconfigure our Macbook each time we get a new one or
install from scratch. That's a talk we have already had months ago.

I change my workstation every X months. Each time I either lose my apps'
configurations, or I just waste a bunch of hours getting setup like I was on my
old box. I also spend a lot of time reconfiguring the same stuff again on all my
workstations (home, work).

Boring...

Some people tried to solve the problem on the application layer, like
[Github's Boxen](https://boxen.github.com/),
but it solves a different problem, from my point of view. I don't spend a lot
of time installing or downloading stuff. I spend time configuring it.

For years, I've used a personal shell script that was copying known config
files into Subversion, Git or Dropbox, and linked them into my home. But I felt
a lot of us had the same problem: Making a more generic tool could help others
and I could get help from others to support more apps in the tool.

So here comes Mackup, the little tool that will sync all your application
configs to Dropbox (or Google Drive, or anything).

And it's [GPL](http://www.gnu.org/licenses/gpl.html), of course.

## What platforms are supported

- macOS
- GNU/Linux

## What's up with the weird name

Mackup is a portmanteau of Mac and Backup. It is simple, short, and easy to
remember, and it corresponds with the whole idea: the simpler – the better!
The `-ng` suffix ("next generation") marks this maintained fork, which
streamlines Mackup down to a single two-way `sync` plus `rm`.

## Architecture

Want to understand how Mackup works internally? Check out the
[Architecture Guide](doc/ARCHITECTURE.md) which includes:

- Visual architecture diagram
- Component breakdown
- Data flow diagrams
- Design decisions
- Extension points for contributors

Perfect for contributors who want to understand the codebase or users
curious about how their configs are managed.

## Where can I find more information

In the [doc](doc) directory.
