-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·139 lines (113 loc) · 4.97 KB
/
install.sh
File metadata and controls
executable file
·139 lines (113 loc) · 4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/bin/bash
set -euo pipefail
REPO="stoutput/cmd-tab-max"
BINARY_NAME="CmdTabMax"
APP_BUNDLE="$HOME/Applications/CmdTabMax.app"
BINARY="$APP_BUNDLE/Contents/MacOS/$BINARY_NAME"
PLIST_LABEL="com.stoutput.cmdtabmax"
PLIST_FILE="$HOME/Library/LaunchAgents/$PLIST_LABEL.plist"
# ── version check ──────────────────────────────────────────────────────────────
echo "Checking latest release..."
LATEST_JSON=$(curl -fsSL "https://api.github.com/repos/$REPO/releases/latest")
LATEST_VERSION=$(echo "$LATEST_JSON" | grep '"tag_name"' | cut -d'"' -f4 | sed 's/^v//')
if [ -f "$PLIST_FILE" ]; then
INSTALLED_VERSION=$(/usr/libexec/PlistBuddy -c "Print :Version" "$PLIST_FILE" 2>/dev/null || echo "")
if [ "$INSTALLED_VERSION" = "$LATEST_VERSION" ]; then
echo "✅ CmdTabMax $LATEST_VERSION is already up to date."
exit 0
fi
fi
if [ -d "$APP_BUNDLE" ]; then FRESH_INSTALL=false; else FRESH_INSTALL=true; fi
# ── download ───────────────────────────────────────────────────────────────────
echo "Downloading v$LATEST_VERSION..."
DOWNLOAD_URL=$(echo "$LATEST_JSON" \
| grep '"browser_download_url"' | grep 'universal\.zip' | cut -d'"' -f4)
if [ -z "$DOWNLOAD_URL" ]; then
echo "Error: could not find a release asset. Check https://github.com/$REPO/releases" >&2
exit 1
fi
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
curl -fsSL "$DOWNLOAD_URL" -o "$TMP/release.zip"
unzip -q "$TMP/release.zip" "$BINARY_NAME" -d "$TMP"
# ── install app bundle ─────────────────────────────────────────────────────────
echo "Installing to $APP_BUNDLE..."
mkdir -p "$APP_BUNDLE/Contents/MacOS"
# Info.plist gives TCC a stable CFBundleIdentifier to track across updates,
# so the accessibility grant survives binary changes.
cat > "$APP_BUNDLE/Contents/Info.plist" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.stoutput.cmdtabmax</string>
<key>CFBundleName</key>
<string>CmdTabMax</string>
<key>CFBundleVersion</key>
<string>$LATEST_VERSION</string>
<key>CFBundleExecutable</key>
<string>$BINARY_NAME</string>
<key>LSUIElement</key>
<true/>
</dict>
</plist>
EOF
cp "$TMP/$BINARY_NAME" "$BINARY"
xattr -dr com.apple.quarantine "$APP_BUNDLE" 2>/dev/null || true
codesign --force --deep --sign - "$APP_BUNDLE" 2>/dev/null || true
# Migrate: remove old bare binary if present from a previous install.
rm -f "/usr/local/bin/$BINARY_NAME" 2>/dev/null || true
# ── install LaunchAgent ────────────────────────────────────────────────────────
mkdir -p "$(dirname "$PLIST_FILE")"
cat > "$PLIST_FILE" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>$PLIST_LABEL</string>
<key>Version</key>
<string>$LATEST_VERSION</string>
<key>ProgramArguments</key>
<array>
<string>$BINARY</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/CmdTabMax.log</string>
<key>StandardErrorPath</key>
<string>/tmp/CmdTabMax.log</string>
</dict>
</plist>
EOF
# ── restart & accessibility ────────────────────────────────────────────────────
echo ""
echo "✅ CmdTabMax $LATEST_VERSION installed."
echo ""
# Each binary update changes the code signature, invalidating the old TCC grant.
# Reset it now so a fresh prompt appears, then wait for the user to grant before
# doing the final restart (a running process can't pick up a new TCC grant).
if [ "$FRESH_INSTALL" = false ]; then
if ! tccutil reset Accessibility "$PLIST_LABEL" 2>/dev/null; then
echo "Please open System Settings → Privacy & Security → Accessibility,"
echo "click − to remove the existing CmdTabMax entry, then continue."
echo ""
fi
fi
open "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"
launchctl bootout "gui/$(id -u)" "$PLIST_FILE" 2>/dev/null || true
sleep 1
launchctl bootstrap "gui/$(id -u)" "$PLIST_FILE"
echo "Grant Accessibility access in System Settings, then press Enter..."
read -r </dev/tty
launchctl bootout "gui/$(id -u)" "$PLIST_FILE" 2>/dev/null || true
sleep 1
launchctl bootstrap "gui/$(id -u)" "$PLIST_FILE"
echo ""
echo "Done! CmdTabMax is running."