Skip to content

Commit a0fbfd2

Browse files
committed
feat: dry-run mode, App Store, Dock Layout, Profile Backup, new tweaks, CI
- add --dry-run, --no-confirm, --log CLI flags with guards across all modules - add Mac App Store installer via mas (appstore.sh, Brewfile.appstore) - add Dock Layout management via dockutil (dock_layout.sh) - add Profile Backup — export/import Brewfile, defaults, dotfiles, editors, iTerm2 - add Nerd Fonts bundle (Brewfile.fonts) - add Keyboard & Text, Screenshots tweaks, Hot Corners interactive setup - add GitHub Actions CI (ShellCheck, bash syntax, Brewfile lint) - expand Dock, Trackpad & Mouse, Misc tweaks - guard .zshrc aliases with command -v, use git pull --rebase in installer - improve common.sh (arch detection, cleanup trap, file logging, auto-confirm) - update README.md and CHANGELOG.md
1 parent f25c9fd commit a0fbfd2

21 files changed

Lines changed: 977 additions & 54 deletions

.github/workflows/ci.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
lint:
11+
name: Lint & Validate
12+
runs-on: macos-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Install ShellCheck
17+
run: brew install shellcheck
18+
19+
- name: ShellCheck
20+
run: |
21+
find . -name "*.sh" -not -path "./.git/*" | while read -r file; do
22+
echo "Checking $file"
23+
shellcheck -x -s bash -e SC2034,SC1091 "$file" || exit 1
24+
done
25+
26+
- name: Bash syntax
27+
run: |
28+
find . -name "*.sh" -not -path "./.git/*" | while read -r file; do
29+
echo "Validating $file"
30+
bash -n "$file" || exit 1
31+
done
32+
33+
- name: Brewfile syntax
34+
run: |
35+
for bf in config/Brewfile.*; do
36+
[ -f "$bf" ] || continue
37+
echo "Validating $bf"
38+
grep -vE '^\s*(#|$|brew |cask |tap |mas )' "$bf" && exit 1 || true
39+
done
40+
41+
- name: Config files exist
42+
run: |
43+
for f in config/Brewfile.dev config/Brewfile.browsers config/Brewfile.utils \
44+
config/Brewfile.media config/Brewfile.comm config/Brewfile.fonts \
45+
config/Brewfile.appstore config/shell/.zshrc config/shell/starship.toml \
46+
config/shell/config.jsonc config/ghostty/config config/vscode/settings.json; do
47+
[ -f "$f" ] && echo "OK: $f" || { echo "MISSING: $f"; exit 1; }
48+
done

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,34 @@
11
# Changelog
22

3+
## 29.03.2
4+
5+
### New
6+
7+
- **CLI flags**`--dry-run`, `--no-confirm`, `--log` for non-destructive preview, unattended runs, and session logging
8+
- **Mac App Store** — install apps via `mas` with multiselect (`apps/appstore.sh`, `config/Brewfile.appstore`)
9+
- **Dock Layout** — set up dock apps, add spacers, reset to default via `dockutil` (`apps/dock_layout.sh`)
10+
- **Profile Backup** — full export/import of Brewfile, macOS defaults, dotfiles, editor settings, iTerm2, dock layout (`apps/profile.sh`)
11+
- **Nerd Fonts** bundle — Fira Code, JetBrains Mono, Meslo, Cascadia Code, Hack, Maple Mono (`config/Brewfile.fonts`)
12+
- **Keyboard & Text** tweaks — key repeat speed, press-and-hold, auto-correct, smart substitutions (`tweaks/keyboard.sh`)
13+
- **Screenshots** tweaks — format, save location, shadow, date in filename (`tweaks/screenshots.sh`)
14+
- **Hot Corners** — interactive corner action picker with current values display
15+
- **GitHub Actions CI** — ShellCheck, bash syntax validation, Brewfile lint, config existence checks
16+
17+
### Improved
18+
19+
- **common.sh** — detect macOS version/arch, cleanup trap, file logging (`_log_file`), auto-confirm mode, smarter Homebrew detection (arm64 + x86), dry-run support in `show_audit_table` and `copy_config`
20+
- **brew.sh** — separate backup submenu (`brewbak_menu`), Fonts bundle, dry-run in `install_bundle` and broken cask fix
21+
- **terminal.sh** — dry-run for iTerm2 export/import, fix sed regex escaping in fastfetch host format
22+
- **macrift.sh** — flag parsing with `--help`, active flags in menu title, Profile Backup in main menu, cleanup moved to common trap
23+
- **tweaks_menu.sh** — added Keyboard & Text, Trackpad & Mouse, Screenshots, Hot Corners entries; "Apply ALL" includes new modules
24+
- **dock.sh** — autohide, tile size, animation speed, minimize effect, auto-rearrange Spaces, static-only mode
25+
- **input.sh** — renamed to "Trackpad & Mouse"; tap-to-click, tracking speed, right-click, drag-windows-anywhere
26+
- **misc.sh** — expand save/print panels, save-to-disk default, disable window animations, boot sound muting via `nvram`
27+
- **.zshrc** — aliases guarded with `command -v` checks so shell loads clean without optional tools
28+
- **install.sh**`git pull --rebase --autostash` for safer updates
29+
30+
---
31+
332
## 29.03
433

534
### Features

README.md

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ Installs to `~/.macrift`, creates a global `macrift` command, and launches autom
4242

4343
| | Feature | What it does |
4444
| :-- | :----------------------- | :---------------------------------------------------------------------- |
45-
| ⚙️ | **System Tweaks** | Dock, Finder, input, misc — 20+ macOS defaults with audit preview |
46-
| 📦 | **Apps & Packages** | 5 Homebrew bundles, .brewbak export/import, SpotX, Spicetify |
45+
| ⚙️ | **System Tweaks** | Dock, Finder, Keyboard, Trackpad, Screenshots, Hot Corners, Misc |
46+
| 📦 | **Apps & Packages** | 7 Homebrew bundles, Mac App Store, Dock Layout, .brewbak backup |
4747
| 🎨 | **Customize** | Terminal, shell, code editor, Spicetify marketplace, wallpapers |
4848
| 🛡️ | **Security & Privacy** | privacy.sexy presets, hostname, encrypted DNS, analytics off |
4949
| 🧹 | **Cleanup** | System cleanup via Mole — caches, logs, leftovers |
50+
| 💾 | **Profile Backup** | Full export/import — Brewfile, defaults, dotfiles, editors, iTerm2 |
5051

5152
<br>
5253

@@ -57,12 +58,15 @@ Installs to `~/.macrift`, creates a global `macrift` command, and launches autom
5758

5859
Every tweak shows a diff table before applying. Choose individually or apply all at once.
5960

60-
| Category | What it does |
61-
| :-------- | :----------------------------------------------------------------------------- |
62-
| Dock | Instant autohide, minimize to app icon, hide recents, dim hidden apps |
63-
| Finder | Show hidden files & extensions, path bar, POSIX title, list view, no .DS_Store |
64-
| Input | Disable auto-correct and auto-capitalize |
65-
| Misc | Disable boot sound, speed up app open dialog |
61+
| Category | What it does |
62+
| :--------------- | :----------------------------------------------------------------------------- |
63+
| Dock | Autohide, tile size, animation speed, minimize effect, Spaces, recents |
64+
| Finder | Show hidden files & extensions, path bar, POSIX title, list view, no .DS_Store |
65+
| Keyboard & Text | Key repeat speed, press-and-hold, auto-correct, smart substitutions |
66+
| Trackpad & Mouse | Tap to click, tracking speed, right-click, drag windows anywhere |
67+
| Screenshots | Format, save location, shadow, date in filename |
68+
| Hot Corners | Interactive corner action picker |
69+
| Misc | Boot sound, app open dialog, save/print panels, window animations |
6670

6771
</details>
6872

@@ -71,13 +75,17 @@ Every tweak shows a diff table before applying. Choose individually or apply all
7175

7276
<br>
7377

74-
**Homebrew Bundles** — multi-select installer with 5 curated Brewfiles:
78+
**Homebrew Bundles** — multi-select installer with 7 curated Brewfiles:
7579

7680
- **Development** — git, gh, lazygit, node, python, go, rust, neovim, fzf, ripgrep, bat, eza, fd...
7781
- **Browsers** — Chrome, Arc, Zen, Ungoogled Chromium
7882
- **Utilities** — Raycast, Alfred, HiddenBar, Keka, AltTab, SoundSource...
7983
- **Media** — IINA, OBS, Spotify, Figma, ImageOptim
8084
- **Communication** — Ayugram, Telegram, Discord, Slack, Zoom
85+
- **Fonts** — Nerd Fonts (Fira Code, JetBrains Mono, Meslo, Cascadia Code, Hack, Maple Mono)
86+
- **App Store** — install Mac App Store apps via `mas`
87+
88+
**Dock Layout** — set up dock apps, add spacers, reset to default via `dockutil`.
8189

8290
Export/import your packages with `.brewbak` backup files.
8391

apps/apps_menu.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@ apps_menu() {
88
local choice
99
choice=$(show_menu "Apps & Packages" \
1010
"Homebrew Bundles" \
11+
"Mac App Store" \
12+
"Dock Layout" \
1113
"Spotify" \
1214
"Back")
1315

1416
case "$choice" in
1517
1) source "$MACRIFT_DIR/apps/brew.sh" && brew_menu ;;
16-
2) source "$MACRIFT_DIR/apps/spotify.sh" && spotify_menu ;;
18+
2) source "$MACRIFT_DIR/apps/appstore.sh" && appstore_menu ;;
19+
3) source "$MACRIFT_DIR/apps/dock_layout.sh" && dock_layout_menu ;;
20+
4) source "$MACRIFT_DIR/apps/spotify.sh" && spotify_menu ;;
1721
0) return ;;
1822
*) ;;
1923
esac

apps/appstore.sh

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#!/usr/bin/env bash
2+
# macrift — Mac App Store installer via mas
3+
4+
appstore_menu() {
5+
while true; do
6+
clear
7+
set_title "macrift > app store"
8+
local choice
9+
choice=$(show_menu "Mac App Store" \
10+
"Install from list" \
11+
"Show installed" \
12+
"Back")
13+
14+
case "$choice" in
15+
1) install_appstore ;;
16+
2) show_installed_apps ;;
17+
0) return ;;
18+
*) ;;
19+
esac
20+
done
21+
}
22+
23+
_ensure_mas() {
24+
if command -v mas &>/dev/null; then
25+
return 0
26+
fi
27+
log_warn "mas (Mac App Store CLI) not found"
28+
if [[ "$MACRIFT_DRY_RUN" == true ]]; then
29+
log_info "Dry run — would install mas"
30+
return 1
31+
fi
32+
if confirm "Install mas via Homebrew?"; then
33+
brew install mas
34+
return 0
35+
fi
36+
return 1
37+
}
38+
39+
install_appstore() {
40+
clear
41+
42+
_ensure_mas || return
43+
44+
local path="$MACRIFT_DIR/config/Brewfile.appstore"
45+
if [[ ! -f "$path" ]]; then
46+
log_err "Brewfile.appstore not found"
47+
return 1
48+
fi
49+
50+
# Get installed app ids
51+
local installed_ids
52+
installed_ids=$(mas list 2>/dev/null | awk '{print $1}')
53+
54+
# Parse mas entries
55+
local new_labels=()
56+
local new_ids=()
57+
local installed_count=0
58+
59+
while IFS= read -r line; do
60+
[[ "$line" =~ ^[[:space:]]*#.*$ || -z "${line// /}" ]] && continue
61+
if [[ "$line" =~ ^mas[[:space:]]+\"([^\"]+)\".*id:[[:space:]]*([0-9]+) ]]; then
62+
local name="${BASH_REMATCH[1]}"
63+
local id="${BASH_REMATCH[2]}"
64+
if echo "$installed_ids" | grep -qxF "$id"; then
65+
installed_count=$((installed_count + 1))
66+
else
67+
new_labels+=("$name")
68+
new_ids+=("$id")
69+
fi
70+
fi
71+
done < "$path"
72+
73+
if [[ $installed_count -gt 0 ]]; then
74+
log_ok "$installed_count already installed"
75+
fi
76+
77+
if [[ ${#new_labels[@]} -eq 0 ]]; then
78+
log_ok "Everything installed"
79+
printf "\n ${DIM}press enter to continue${RESET} "
80+
read -r < /dev/tty || true
81+
return 0
82+
fi
83+
84+
local selected
85+
selected=$(show_multiselect "App Store" "${new_labels[@]}")
86+
87+
if [[ -z "$selected" ]]; then
88+
log_info "Nothing selected"
89+
return 0
90+
fi
91+
92+
printf "\n"
93+
if [[ "$MACRIFT_DRY_RUN" == true ]]; then
94+
log_info "Dry run — would install from App Store:"
95+
for ((i=0; i<${#new_labels[@]}; i++)); do
96+
if echo "$selected" | grep -qxF "${new_labels[$i]}"; then
97+
printf " ${DIM}· %s (id: %s)${RESET}\n" "${new_labels[$i]}" "${new_ids[$i]}"
98+
fi
99+
done
100+
else
101+
for ((i=0; i<${#new_labels[@]}; i++)); do
102+
if echo "$selected" | grep -qxF "${new_labels[$i]}"; then
103+
log_info "Installing ${new_labels[$i]}..."
104+
if mas install "${new_ids[$i]}"; then
105+
log_ok "${new_labels[$i]} installed"
106+
else
107+
log_warn "Failed: ${new_labels[$i]}"
108+
fi
109+
fi
110+
done
111+
fi
112+
113+
printf "\n ${DIM}press enter to continue${RESET} "
114+
read -r < /dev/tty || true
115+
}
116+
117+
show_installed_apps() {
118+
clear
119+
divider "Installed App Store Apps"
120+
121+
_ensure_mas || return
122+
123+
mas list 2>/dev/null | while IFS= read -r line; do
124+
printf " ${DIM}%s${RESET}\n" "$line"
125+
done
126+
127+
printf "\n ${DIM}press enter to continue${RESET} "
128+
read -r < /dev/tty || true
129+
}

apps/brew.sh

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ brew_menu() {
1212
"Utilities" \
1313
"Media" \
1414
"Communication" \
15+
"Fonts (Nerd Fonts)" \
1516
"---" \
1617
"Install ALL bundles" \
17-
"Import from .brewbak" \
18-
"Export to .brewbak" \
18+
"Backup (.brewbak)" \
1919
"Back")
2020

2121
case "$choice" in
@@ -24,9 +24,28 @@ brew_menu() {
2424
3) install_bundle "Brewfile.utils" ;;
2525
4) install_bundle "Brewfile.media" ;;
2626
5) install_bundle "Brewfile.comm" ;;
27-
6) install_all_bundles ;;
28-
7) import_brewbak ;;
29-
8) export_brewbak ;;
27+
6) install_bundle "Brewfile.fonts" ;;
28+
7) install_all_bundles ;;
29+
8) brewbak_menu ;;
30+
0) return ;;
31+
*) ;;
32+
esac
33+
done
34+
}
35+
36+
brewbak_menu() {
37+
while true; do
38+
clear
39+
set_title "macrift > brew > backup"
40+
local choice
41+
choice=$(show_menu "Backup (.brewbak)" \
42+
"Import from .brewbak" \
43+
"Export to .brewbak" \
44+
"Back")
45+
46+
case "$choice" in
47+
1) import_brewbak ;;
48+
2) export_brewbak ;;
3049
0) return ;;
3150
*) ;;
3251
esac
@@ -100,7 +119,9 @@ install_bundle() {
100119
printf "\n"
101120
printf " ${DIM}This will reinstall the apps listed above.${RESET}\n"
102121
printf "\n"
103-
if confirm "Fix them now?"; then
122+
if [[ "$MACRIFT_DRY_RUN" == true ]]; then
123+
log_info "Dry run — would reinstall broken casks"
124+
elif confirm "Fix them now?"; then
104125
printf "\n"
105126
for cask in "${broken_casks[@]}"; do
106127
log_info "Reinstalling $cask..."
@@ -143,6 +164,15 @@ install_bundle() {
143164
fi
144165
done
145166

167+
if [[ "$MACRIFT_DRY_RUN" == true ]]; then
168+
log_info "Dry run — would install:"
169+
while IFS= read -r line; do
170+
printf " ${DIM}· %s${RESET}\n" "$line"
171+
done < "$tmp"
172+
rm -f "$tmp"
173+
return 0
174+
fi
175+
146176
log_info "Installing selected packages..."
147177
if brew bundle --file="$tmp"; then
148178
log_ok "All packages installed"

0 commit comments

Comments
 (0)