Update README for clarity and structure
- Revised the introduction to emphasize the workflow of the `ssr` tool. - Reformatted the backup and restore commands into a table for better readability. - Enhanced the documentation on installation and configuration steps. - Clarified the requirements section and streamlined the installation instructions. - Added a quick reference section for CLI commands to improve user accessibility.
This commit is contained in:
@@ -1,24 +1,25 @@
|
|||||||
# ssr — System Sync & Restore for macOS
|
# ssr — System Sync & Restore for macOS
|
||||||
|
|
||||||
Reproducible macOS setup in one command. `ssr` snapshots your Homebrew bundle and application configs to a cloud drive on a schedule, and can rebuild a fresh Mac from that snapshot.
|
Reproducible macOS setup in one workflow: snapshot your Homebrew bundle and application configs to a cloud drive on a schedule, then rebuild a fresh Mac from that snapshot.
|
||||||
|
|
||||||
- **Backup** (`ssr sync`): dumps `Brewfile` and runs `mackup backup` to the configured cloud directory (copy-based; no symlinks).
|
| Action | Command |
|
||||||
- **Restore** (`ssr restore`): installs Homebrew, replays the `Brewfile`, runs `mackup restore`, applies macOS defaults.
|
|--------|---------|
|
||||||
- **Legacy Mackup symlinks**: if a previous install used `mackup link`, run `ssr mackup unlink` once before relying on copy-based sync.
|
| Backup | `ssr sync` — Brewfile + Mackup copy to cloud (no symlinks by default) |
|
||||||
- **Scheduled sync**: native macOS `launchd` agent (daily by default).
|
| Restore | `ssr restore` — Homebrew, Brewfile, Mackup, macOS defaults |
|
||||||
- **Cloud storage**: iCloud Drive, Dropbox, Google Drive, OneDrive, or any custom path — selectable via config.
|
| Schedule | `ssr schedule on` — daily `launchd` job |
|
||||||
- **No secrets**: all state lives in your cloud drive; the repo only contains code and config templates.
|
| Legacy Mackup symlinks | Run `ssr mackup unlink` once if you previously used `mackup link` |
|
||||||
|
|
||||||
> Successor to the original `system_sync.sh` / `system_restore.sh`. Same intent, modernized tooling, modular, idempotent, scheduled by default.
|
**Full documentation (configuration tables, pref snapshots, logs, security, migration):**
|
||||||
|
**[Wiki → https://git.surke.de/osurke/system-sync-restore/wiki](https://git.surke.de/osurke/system-sync-restore/wiki)**
|
||||||
|
|
||||||
|
> Successor to `system_sync.sh` / `system_restore.sh`. Same intent, modernized modular tooling.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- macOS (Apple Silicon or Intel)
|
- macOS (Apple Silicon or Intel), Bash 3.2+, network for Homebrew bootstrap
|
||||||
- Bash 3.2+ (preinstalled)
|
- A cloud folder you control (iCloud is the default provider)
|
||||||
- Network access for the initial Homebrew install
|
|
||||||
- A cloud drive folder you control (iCloud Drive is the default)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -30,13 +31,7 @@ cd ~/.ssr
|
|||||||
./install.sh
|
./install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
`install.sh` will:
|
Symlinks `ssr` into `~/.local/bin` (override with `SSR_PREFIX`), seeds `~/.config/ssr/ssr.conf`, optionally enables daily sync. If `~/.local/bin` is not on `PATH`:
|
||||||
|
|
||||||
1. Symlink `bin/ssr` into `~/.local/bin` (override with `SSR_PREFIX`).
|
|
||||||
2. Seed `~/.config/ssr/ssr.conf` from `config/ssr.conf.example` (chmod 600).
|
|
||||||
3. Optionally enable the scheduled daily sync.
|
|
||||||
|
|
||||||
If `~/.local/bin` is not on your `PATH`, add it to your shell rc:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export PATH="$HOME/.local/bin:$PATH"
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
@@ -44,302 +39,49 @@ export PATH="$HOME/.local/bin:$PATH"
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## CLI (quick reference)
|
||||||
|
|
||||||
```text
|
```text
|
||||||
ssr install First-time install: link binary, seed config, schedule sync
|
ssr install Link binary, seed config, optional schedule
|
||||||
ssr sync One-shot backup → cloud
|
ssr sync Backup → cloud
|
||||||
ssr restore [Brewfile] Restore the machine; Brewfile defaults to the cloud copy
|
ssr restore [Brewfile] Restore; Brewfile defaults to cloud copy
|
||||||
ssr update [--dry-run] Pull latest ssr code, refresh launchd if needed
|
ssr update [--dry-run] Git pull + launchd refresh when needed
|
||||||
ssr schedule on|off Enable/disable the daily launchd job
|
ssr schedule on|off Daily launchd job
|
||||||
ssr config show|edit Show or edit the active config
|
ssr config show|edit Config file
|
||||||
ssr completions install Install zsh/bash/fish tab-completion
|
ssr completions install zsh / bash / fish
|
||||||
ssr status Show config, cloud target, last sync, schedule state
|
ssr status Summary
|
||||||
ssr version Print version
|
ssr version
|
||||||
```
|
```
|
||||||
|
|
||||||
### First backup
|
**New machine:** clone → `./install.sh` → `ssr restore`. Details: [Quick-start](https://git.surke.de/osurke/system-sync-restore/wiki/Quick-start), [Backup-structure-and-sync](https://git.surke.de/osurke/system-sync-restore/wiki/Backup-structure-and-sync).
|
||||||
|
|
||||||
```bash
|
|
||||||
ssr sync
|
|
||||||
```
|
|
||||||
|
|
||||||
Output structure in the cloud drive:
|
|
||||||
|
|
||||||
```
|
|
||||||
<cloud root>/
|
|
||||||
├── BACKUP/
|
|
||||||
│ └── <hostname> - <hardware-uuid>/
|
|
||||||
│ ├── Brewfile
|
|
||||||
│ ├── Brewfile.bak
|
|
||||||
│ ├── unmanaged-apps.md # apps installed manually (not brew/MAS)
|
|
||||||
│ └── macos-prefs/ # pref-domain snapshots
|
|
||||||
│ ├── com.apple.dock.plist
|
|
||||||
│ ├── com.apple.finder.plist
|
|
||||||
│ └── …
|
|
||||||
└── Mackup/
|
|
||||||
└── … (managed by mackup)
|
|
||||||
```
|
|
||||||
|
|
||||||
During each sync the unmanaged-apps scan compares every `.app` bundle in `/Applications` (and `~/Applications`) against:
|
|
||||||
|
|
||||||
1. **Mac App Store** — bundle contains `Contents/_MASReceipt/receipt`
|
|
||||||
2. **Homebrew Cask** — bundle filename matches the `.app` artifact of any installed cask
|
|
||||||
|
|
||||||
Anything not matched is written to `unmanaged-apps.md` (Markdown table, one row per app, with version, bundle id and a best-effort installer link) and printed to the sync log as a warning. Disable with `SSR_SCAN_UNMANAGED_APPS=false`.
|
|
||||||
|
|
||||||
Link selection for each app uses, in order:
|
|
||||||
|
|
||||||
1. **Sparkle feed** — `SUFeedURL` from the bundle's `Info.plist` → linked vendor homepage.
|
|
||||||
2. **Known vendor map** — bundle-id prefix maps to the official download page (Adobe, Microsoft, Docker, Cursor, Anthropic, JetBrains, GitKraken, Signal, Zoom, etc.).
|
|
||||||
3. **Web search** — DuckDuckGo query for `<App name> macOS download`.
|
|
||||||
|
|
||||||
### macOS preferences snapshot
|
|
||||||
|
|
||||||
`ssr sync` also snapshots the live state of a curated set of macOS preference domains, writing one plist per domain to `<backup_dir>/macos-prefs/`. During `ssr restore` these are replayed **after** `config/macos-defaults.sh`, so the snapshot is the last writer.
|
|
||||||
|
|
||||||
Default domains:
|
|
||||||
|
|
||||||
| Domain | What it covers |
|
|
||||||
|---|---|
|
|
||||||
| `com.apple.dock` | Dock position, app layout, hot corners |
|
|
||||||
| `com.apple.finder` | View options, sidebar, path bar |
|
|
||||||
| `com.apple.symbolichotkeys` | Global keyboard shortcuts (Spotlight, Mission Control, Screenshots…) |
|
|
||||||
| `com.apple.HIToolbox` | Input sources / keyboard layouts |
|
|
||||||
| `com.apple.spaces` | Spaces / Mission Control layout |
|
|
||||||
| `com.apple.menuextra.clock` | Menu-bar clock format |
|
|
||||||
| `NSGlobalDomain` | Global UI prefs, key-repeat speed, sound, language |
|
|
||||||
|
|
||||||
**Conflict resolution during restore**
|
|
||||||
|
|
||||||
When a snapshot domain overlaps with a domain that `config/macos-defaults.sh` also writes to, `ssr restore` warns and asks interactively:
|
|
||||||
|
|
||||||
```
|
|
||||||
[WARN] Pref-snapshot overlaps with declarative defaults for 2 domain(s):
|
|
||||||
com.apple.dock, com.apple.finder
|
|
||||||
|
|
||||||
Domain `com.apple.dock`:
|
|
||||||
Snapshot from last sync (2026-05-11T17:30:00+0200) will OVERRIDE values
|
|
||||||
set by macos-defaults.sh.
|
|
||||||
[A]ccept snapshot / [r]eject (keep declarative)? [A/r]:
|
|
||||||
```
|
|
||||||
|
|
||||||
Default = `Accept` (press Enter). Reply `r` to keep the declarative value for that domain. In non-interactive contexts (launchd, CI) the decision falls back to `SSR_PREFS_CONFLICT_DEFAULT` (default `accept`). Set `SSR_ASSUME_YES=true` to skip all prompts.
|
|
||||||
|
|
||||||
Extend the domain set in `~/.config/ssr/ssr.conf`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
SSR_MACOS_PREF_DOMAINS_EXTRA="com.apple.universalaccess com.apple.Spotlight"
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Mackup overlap:** if you also configure mackup to sync `com.apple.dock` or similar domains, two mechanisms will compete. Pick one.
|
|
||||||
|
|
||||||
### Restore on a new machine
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://git.surke.de/osurke/system-sync-restore.git ~/.ssr
|
|
||||||
cd ~/.ssr && ./install.sh
|
|
||||||
ssr restore
|
|
||||||
```
|
|
||||||
|
|
||||||
By default `ssr restore` picks the Brewfile from `<cloud>/BACKUP/<host> - <uuid>/Brewfile`. To restore from a different machine's snapshot, pass an explicit path:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssr restore "$HOME/Library/Mobile Documents/com~apple~CloudDocs/BACKUP/oldhost - ABCD-1234/Brewfile"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Configuration
|
## Wiki index
|
||||||
|
|
||||||
Config lives in `~/.config/ssr/ssr.conf` (override with `--config` or `$SSR_CONFIG`). The file is sourced by bash but only recognised `KEY=VALUE` lines are accepted; anything else causes `ssr` to abort.
|
| Topic | Wiki |
|
||||||
|
|--------|------|
|
||||||
| Key | Default | Purpose |
|
| Install & first steps | [Quick-start](https://git.surke.de/osurke/system-sync-restore/wiki/Quick-start) |
|
||||||
|-----|---------|---------|
|
| Command list | [Commands](https://git.surke.de/osurke/system-sync-restore/wiki/Commands) |
|
||||||
| `SSR_CLOUD_PROVIDER` | `icloud` | `icloud`\|`dropbox`\|`googledrive`\|`onedrive`\|`custom` |
|
| Cloud layout, unmanaged apps, macOS pref snapshots | [Backup-structure-and-sync](https://git.surke.de/osurke/system-sync-restore/wiki/Backup-structure-and-sync) |
|
||||||
| `SSR_CLOUD_PATH` | — | Absolute path; only used when provider is `custom` |
|
| `ssr.conf` and cloud paths | [Configuration-reference](https://git.surke.de/osurke/system-sync-restore/wiki/Configuration-reference) |
|
||||||
| `SSR_BACKUP_SUBDIR` | `BACKUP` | Subfolder for per-host backups |
|
| launchd, logs, `ssr update` | [Scheduling-logging-and-updates](https://git.surke.de/osurke/system-sync-restore/wiki/Scheduling-logging-and-updates) |
|
||||||
| `SSR_MACKUP_SUBDIR` | `Mackup` | Subfolder used by mackup |
|
| Tab completions | [Shell-completions](https://git.surke.de/osurke/system-sync-restore/wiki/Shell-completions) |
|
||||||
| `SSR_BREW_UPGRADE` | `true` | Run `brew upgrade` during sync |
|
| Security, uninstall, legacy scripts | [Security-Uninstall-and-Migration](https://git.surke.de/osurke/system-sync-restore/wiki/Security-Uninstall-and-Migration) |
|
||||||
| `SSR_BREW_CLEANUP` | `true` | Run `brew cleanup` after sync |
|
| Repo tree | [Repository-layout](https://git.surke.de/osurke/system-sync-restore/wiki/Repository-layout) |
|
||||||
| `SSR_SCAN_UNMANAGED_APPS` | `true` | List `.app` bundles not from brew/MAS during sync |
|
|
||||||
| `SSR_APP_DIRS` | `/Applications:~/Applications` | Colon-separated dirs scanned for unmanaged apps |
|
|
||||||
| `SSR_SNAPSHOT_MACOS_PREFS` | `true` | Snapshot macOS pref domains during sync |
|
|
||||||
| `SSR_MACOS_PREF_DOMAINS` | _(see below)_ | Full override of snapshotted domains (space-separated) |
|
|
||||||
| `SSR_MACOS_PREF_DOMAINS_EXTRA` | — | Extra domains appended to the default set |
|
|
||||||
| `SSR_PREFS_CONFLICT_DEFAULT` | `accept` | Non-TTY conflict resolution: `accept` or `reject` |
|
|
||||||
| `SSR_ASSUME_YES` | `false` | Auto-accept all pref-snapshot conflicts on restore |
|
|
||||||
| `SSR_DISABLE_GATEKEEPER` | `false` | Run `spctl --global-disable` during restore (security trade-off) |
|
|
||||||
| `SSR_OPEN_CASKS` | `false` | Open every installed cask after restore for first-run config |
|
|
||||||
| `SSR_MACOS_DEFAULTS` | repo's `config/macos-defaults.sh` | Override path to your own defaults script |
|
|
||||||
| `SSR_LAUNCHD_LABEL` | `de.surke.ssr.sync` | launchd job label |
|
|
||||||
| `SSR_SCHEDULE_HOUR` | `9` | Daily run hour (0–23, local time) |
|
|
||||||
| `SSR_SCHEDULE_MINUTE` | `0` | Daily run minute |
|
|
||||||
| `SSR_PREFIX` | `$HOME/.local/bin` | Install prefix for the `ssr` symlink |
|
|
||||||
| `SSR_STATE_DIR` | `$HOME/.local/state/ssr` | Internal state directory |
|
|
||||||
| `SSR_LOG_DIR` | `$HOME/.local/state/ssr/logs` | launchd log directory |
|
|
||||||
|
|
||||||
### Cloud provider paths resolved automatically
|
|
||||||
|
|
||||||
| Provider | Resolved root |
|
|
||||||
|----------|---------------|
|
|
||||||
| `icloud` | `~/Library/Mobile Documents/com~apple~CloudDocs` |
|
|
||||||
| `dropbox` | `~/Library/CloudStorage/Dropbox*` (fallback `~/Dropbox`) |
|
|
||||||
| `googledrive` | `~/Library/CloudStorage/GoogleDrive-*` |
|
|
||||||
| `onedrive` | `~/Library/CloudStorage/OneDrive-*` |
|
|
||||||
| `custom` | Value of `SSR_CLOUD_PATH` |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Shell completions
|
## Contributing docs
|
||||||
|
|
||||||
`ssr install` offers to install completions automatically. To do it manually later:
|
Edit the **wiki** repository (`System-Sync-Restore.wiki`) for user-facing guides; keep this README as the short landing page and link hub. Example clone:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ssr completions install # detects $SHELL
|
git clone https://git.surke.de/osurke/system-sync-restore.wiki.git
|
||||||
ssr completions install --shell all # zsh + bash + fish
|
|
||||||
ssr completions status # show what's wired up
|
|
||||||
ssr completions uninstall --shell all
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Targets (user-scoped, no sudo):
|
|
||||||
|
|
||||||
| Shell | Path |
|
|
||||||
|-------|------|
|
|
||||||
| zsh | `~/.zsh/completions/_ssr` |
|
|
||||||
| bash | `~/.local/share/bash-completion/completions/ssr` |
|
|
||||||
| fish | `~/.config/fish/completions/ssr.fish` |
|
|
||||||
|
|
||||||
For zsh, ensure `~/.zsh/completions` is on `$fpath` (the installer prints the snippet for `~/.zshrc` if it isn't already). For bash, you need [`bash-completion@2`](https://github.com/scop/bash-completion) sourced from your shell rc — Homebrew install path is also printed. Fish needs no extra setup.
|
|
||||||
|
|
||||||
After installation, open a fresh shell or `exec $SHELL` and `ssr <TAB>` lists the available commands.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Scheduled sync
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssr schedule on # write & load ~/Library/LaunchAgents/<label>.plist
|
|
||||||
ssr schedule off # unload & remove
|
|
||||||
ssr schedule status # check
|
|
||||||
```
|
|
||||||
|
|
||||||
Logs land in `$SSR_LOG_DIR/sync.out.log` and `sync.err.log`. Tail them:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
tail -f ~/.local/state/ssr/logs/sync.err.log
|
|
||||||
```
|
|
||||||
|
|
||||||
Show launchd-level details:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
launchctl list | grep ssr
|
|
||||||
log show --predicate 'process == "ssr"' --last 1h
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Updating
|
|
||||||
|
|
||||||
Updates happen on three independent layers:
|
|
||||||
|
|
||||||
**Tool code (this repo).** Self-update via `ssr update`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssr update # git pull --ff-only on the clone, then refresh side-effects
|
|
||||||
ssr update --dry-run # show what would change, don't pull
|
|
||||||
```
|
|
||||||
|
|
||||||
`ssr update` will:
|
|
||||||
|
|
||||||
- Refuse if the working tree is dirty or HEAD is detached.
|
|
||||||
- Fast-forward only — never rewrites history.
|
|
||||||
- Re-render and reload the launchd plist if `launchd/` or `bin/ssr*` changed *and* the schedule is currently active.
|
|
||||||
- Print added config keys when `config/ssr.conf.example` gained new options.
|
|
||||||
|
|
||||||
**Backup data (cloud drive).** Refreshed automatically by the scheduled `ssr sync`. The previous `Brewfile` is preserved as `Brewfile.bak`; deeper history is provided by the cloud provider's built-in version retention (iCloud Drive, Dropbox, …). Trigger an on-demand sync with `ssr sync`.
|
|
||||||
|
|
||||||
**Dependencies (Homebrew, mackup).** `ssr sync` runs `brew upgrade` and `brew cleanup` when `SSR_BREW_UPGRADE=true` / `SSR_BREW_CLEANUP=true` (both default `true`). Set them to `false` in `ssr.conf` to keep snapshots without auto-upgrading installed packages.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Project layout
|
|
||||||
|
|
||||||
```
|
|
||||||
.
|
|
||||||
├── install.sh # Thin wrapper around bin/ssr-install
|
|
||||||
├── bin/
|
|
||||||
│ ├── ssr # CLI dispatcher
|
|
||||||
│ ├── ssr-install # Local install + scheduling
|
|
||||||
│ ├── ssr-update # Self-update (git pull + launchd refresh)
|
|
||||||
│ ├── ssr-sync # Backup to cloud
|
|
||||||
│ ├── ssr-restore # Rebuild a Mac from the backup
|
|
||||||
│ ├── ssr-schedule # launchd on/off/status
|
|
||||||
│ ├── ssr-config # show/edit/path
|
|
||||||
│ ├── ssr-completions # install zsh/bash/fish completions
|
|
||||||
│ └── ssr-status # state summary
|
|
||||||
├── lib/
|
|
||||||
│ ├── common.sh # Logging, validation, config loader
|
|
||||||
│ ├── cloud.sh # Provider abstraction
|
|
||||||
│ ├── brew.sh # Homebrew install + Brewfile ops
|
|
||||||
│ ├── mackup.sh # Mackup install + backup/restore
|
|
||||||
│ ├── apps.sh # Detect unmanaged .app bundles (not brew/MAS)
|
|
||||||
│ ├── macos.sh # macOS-specific actions (Rosetta, defaults, etc.)
|
|
||||||
│ └── macos-prefs.sh # Snapshot/restore macOS pref domains
|
|
||||||
├── config/
|
|
||||||
│ ├── ssr.conf.example # Reference user config
|
|
||||||
│ └── macos-defaults.sh # Default macOS preferences
|
|
||||||
├── completions/
|
|
||||||
│ ├── _ssr # zsh
|
|
||||||
│ ├── ssr.bash # bash
|
|
||||||
│ └── ssr.fish # fish
|
|
||||||
├── launchd/
|
|
||||||
│ └── de.surke.ssr.sync.plist # Template for the scheduled agent
|
|
||||||
├── VERSION
|
|
||||||
├── LICENSE
|
|
||||||
└── README.md
|
|
||||||
```
|
|
||||||
|
|
||||||
All dependencies are inside the repository; the only external requirements are macOS itself and `curl` (for the one-time Homebrew bootstrap).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Security
|
|
||||||
|
|
||||||
- No secrets in this repo. All cloud data lives in the user's cloud drive.
|
|
||||||
- The config file is sourced but **validated**: only `# comments` and `KEY=VALUE` lines are allowed. Foreign content aborts execution.
|
|
||||||
- `chmod 600` is applied to `ssr.conf` and the rendered launchd plist.
|
|
||||||
- `SSR_DISABLE_GATEKEEPER=true` is opt-in only; off by default.
|
|
||||||
- No remote pipes (`curl … | bash`) except Homebrew's own bootstrap during install.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Uninstall
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssr schedule off
|
|
||||||
rm -f ~/.local/bin/ssr
|
|
||||||
rm -rf ~/.config/ssr ~/.local/state/ssr
|
|
||||||
```
|
|
||||||
|
|
||||||
The cloud data is left untouched.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Migration from the legacy scripts
|
|
||||||
|
|
||||||
The old `system_sync.sh` / `system_restore.sh` map onto the new commands:
|
|
||||||
|
|
||||||
| Legacy | New |
|
|
||||||
|--------|-----|
|
|
||||||
| `system_sync.sh` | `ssr sync` |
|
|
||||||
| `system_restore.sh <Brewfile>` | `ssr restore <Brewfile>` |
|
|
||||||
| Manual cron / Lingon entry | `ssr schedule on` |
|
|
||||||
| Hard-coded iCloud path | `SSR_CLOUD_PROVIDER` in `ssr.conf` |
|
|
||||||
| Inline `.macos` block | `config/macos-defaults.sh` (overridable) |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT. See [LICENSE](LICENSE).
|
MIT — see [LICENSE](LICENSE).
|
||||||
|
|||||||
Reference in New Issue
Block a user