-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·354 lines (308 loc) · 9.52 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·354 lines (308 loc) · 9.52 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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
#!/usr/bin/env bash
# lazygit-sidecar installer.
#
# Modes:
# ./install.sh Interactive install wizard (default).
# ./install.sh --core Install lazygit (brew) + copy binary.
# ./install.sh --agent-deck Install tmux hook + ad() zsh alias.
# ./install.sh --all --core then --agent-deck.
# ./install.sh --uninstall Interactive uninstall wizard.
# ./install.sh --uninstall-core Remove the binary only.
# ./install.sh --uninstall-agent-deck Remove tmux hook + ad() alias.
# ./install.sh --help Show usage.
#
# Marker-scoped: nothing outside installer-added blocks gets touched.
set -uo pipefail
REPO_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
BIN_SRC="$REPO_DIR/bin/lazygit-sidecar"
BIN_DEST_DIR="$HOME/.local/bin"
BIN_DEST="$BIN_DEST_DIR/lazygit-sidecar"
TMUX_CONF="$HOME/.tmux.conf"
ZSHRC="$HOME/.zshrc"
MARKER_BEGIN="# >>> lazygit-sidecar agent-deck integration BEGIN"
MARKER_END="# <<< lazygit-sidecar agent-deck integration END"
# ---------- tiny helpers ----------
step() {
echo
echo "=============================================================="
echo " $1"
echo "=============================================================="
}
confirm() {
local answer
read -r -p "$1 [y/N]: " answer
[[ "$answer" =~ ^[Yy]$ ]]
}
path_contains() {
case ":$PATH:" in
*":$1:"*) return 0 ;;
*) return 1 ;;
esac
}
tmux_version_ok() {
local ver
ver=$(tmux -V 2>/dev/null | awk '{print $2}')
case "$ver" in
3.0*|2.*|1.*|0.*) return 1 ;;
*) return 0 ;;
esac
}
has_block() { grep -qF "$MARKER_BEGIN" "$1" 2>/dev/null; }
append_block() {
local file="$1" content="$2"
printf '\n%s\n%s\n%s\n' "$MARKER_BEGIN" "$content" "$MARKER_END" >> "$file" \
|| return 1
}
# Remove first complete MARKER_BEGIN..MARKER_END block. Refuses if either
# marker is missing or the order is reversed. Uses cat-redirect so
# symlinked dotfiles keep their symlink target.
remove_block() {
local file="$1"
[ -f "$file" ] || return 0
has_block "$file" || return 0
local begin_line end_line
begin_line=$(grep -nF "$MARKER_BEGIN" "$file" | head -1 | cut -d: -f1)
end_line=$(grep -nF "$MARKER_END" "$file" | head -1 | cut -d: -f1)
if [ -z "$begin_line" ] || [ -z "$end_line" ]; then
echo "warn: $file has BEGIN without END; file unchanged." >&2
return 1
fi
if [ "$end_line" -le "$begin_line" ]; then
echo "warn: markers in $file are out of order; file unchanged." >&2
return 1
fi
local tmp
tmp=$(mktemp) || return 1
if ! sed "${begin_line},${end_line}d" "$file" > "$tmp"; then
rm -f "$tmp"
return 1
fi
cat "$tmp" > "$file" && rm -f "$tmp"
}
# ---------- non-interactive actions ----------
install_core() {
if ! command -v tmux >/dev/null 2>&1; then
echo "error: tmux is not installed. macOS: brew install tmux" >&2
return 1
fi
if ! tmux_version_ok; then
echo "error: tmux 3.1+ required (found $(tmux -V))." >&2
return 1
fi
if command -v lazygit >/dev/null 2>&1; then
echo "lazygit: $(command -v lazygit)"
else
if ! command -v brew >/dev/null 2>&1; then
echo "error: lazygit missing and brew unavailable. Install lazygit manually." >&2
return 1
fi
echo "Installing lazygit via Homebrew..."
brew install lazygit || return 1
fi
mkdir -p "$BIN_DEST_DIR"
install -m 0755 "$BIN_SRC" "$BIN_DEST" || return 1
echo "installed: $BIN_DEST"
if ! path_contains "$BIN_DEST_DIR"; then
cat <<EOF
note: $BIN_DEST_DIR is not on your PATH.
Add this line to ~/.zshrc (or ~/.bashrc):
export PATH="\$HOME/.local/bin:\$PATH"
EOF
fi
}
install_agent_deck() {
if ! command -v lazygit >/dev/null 2>&1; then
echo "error: lazygit not found; run --core first." >&2
return 1
fi
mkdir -p "$BIN_DEST_DIR"
install -m 0755 "$REPO_DIR/bin/lazygit-sidecar-hook" "$BIN_DEST_DIR/lazygit-sidecar-hook" || {
echo "error: failed to install hook script." >&2
return 1
}
echo "installed: $BIN_DEST_DIR/lazygit-sidecar-hook"
local tmux_block
tmux_block="set-hook -g 'client-attached[99]' 'run-shell \"$BIN_DEST_DIR/lazygit-sidecar-hook\"'"
if has_block "$TMUX_CONF"; then
echo "$TMUX_CONF already contains the integration block; skipping tmux part."
else
append_block "$TMUX_CONF" "$tmux_block" || {
echo "error: failed to append to $TMUX_CONF" >&2
return 1
}
echo "appended tmux hook to $TMUX_CONF"
if tmux info >/dev/null 2>&1; then
tmux source-file "$TMUX_CONF" 2>/dev/null && echo "reloaded running tmux server."
fi
fi
local zsh_block='ad() {
command agent-deck launch -c claude "$@"
}'
if has_block "$ZSHRC"; then
echo "$ZSHRC already contains the integration block; skipping zsh part."
else
append_block "$ZSHRC" "$zsh_block" && echo "appended ad() alias to $ZSHRC"
fi
}
uninstall_core() {
if [ -f "$BIN_DEST" ]; then
rm -f "$BIN_DEST" && echo "removed $BIN_DEST"
else
echo "$BIN_DEST not present; nothing to remove."
fi
}
uninstall_agent_deck() {
local did=0
if [ -f "$BIN_DEST_DIR/lazygit-sidecar-hook" ]; then
rm -f "$BIN_DEST_DIR/lazygit-sidecar-hook" && echo "removed $BIN_DEST_DIR/lazygit-sidecar-hook"
did=1
fi
if has_block "$TMUX_CONF"; then
if remove_block "$TMUX_CONF"; then
echo "removed block from $TMUX_CONF"
did=1
if tmux info >/dev/null 2>&1; then
tmux set-hook -gu 'client-attached[99]' 2>/dev/null
fi
fi
fi
if has_block "$ZSHRC"; then
if remove_block "$ZSHRC"; then
echo "removed block from $ZSHRC"
did=1
fi
fi
[ $did -eq 0 ] && echo "no integration blocks found; nothing to remove."
}
# ---------- interactive flow ----------
interactive_install() {
step "Step 1/4: Prerequisites"
cat <<EOF
Checking (read-only):
- tmux (3.1+ required)
- lazygit (will be brew-installed if missing)
- brew (only needed if lazygit is missing)
EOF
confirm "Continue?" || { echo "Aborted."; exit 0; }
if command -v tmux >/dev/null 2>&1; then
echo " OK tmux $(command -v tmux) ($(tmux -V))"
tmux_version_ok || { echo "tmux 3.1+ required. Abort."; exit 1; }
else
echo " -- tmux NOT FOUND"
echo "Install tmux first (macOS: brew install tmux). Abort."
exit 1
fi
if command -v lazygit >/dev/null 2>&1; then
echo " OK lazygit $(command -v lazygit)"
else
echo " !! lazygit will be installed in step 2"
fi
if command -v brew >/dev/null 2>&1; then
echo " OK brew $(command -v brew)"
else
echo " !! brew not found; required only if lazygit is missing"
fi
step "Step 2/4: Install lazygit"
if command -v lazygit >/dev/null 2>&1; then
echo "lazygit already installed; skip."
else
if ! command -v brew >/dev/null 2>&1; then
echo "brew not found; install lazygit manually (https://github.com/jesseduffield/lazygit) then re-run."
exit 1
fi
if confirm "Run: brew install lazygit?"; then
brew install lazygit || { echo "brew install failed."; exit 1; }
else
echo "Cannot continue without lazygit. Abort."
exit 1
fi
fi
step "Step 3/4: Install lazygit-sidecar binary"
cat <<EOF
I will copy:
$BIN_SRC
to:
$BIN_DEST
(with mode 0755). The parent directory will be created if missing.
EOF
if confirm "Install?"; then
mkdir -p "$BIN_DEST_DIR"
install -m 0755 "$BIN_SRC" "$BIN_DEST" || { echo "copy failed."; exit 1; }
echo "installed: $BIN_DEST"
else
echo "Skipped."
fi
if ! path_contains "$BIN_DEST_DIR"; then
cat <<EOF
note: $BIN_DEST_DIR is not on your PATH.
Add this line to ~/.zshrc (or ~/.bashrc):
export PATH="\$HOME/.local/bin:\$PATH"
EOF
fi
step "Step 4/4: agent-deck integration (optional)"
cat <<EOF
Only for agent-deck users. Adds a tmux client-attached hook that
auto-splits every agent-deck session (name prefix 'agentdeck_') so
lazygit appears on the right. Also adds an 'ad' zsh alias.
Skip this step if you do not use agent-deck.
EOF
if confirm "Install agent-deck integration?"; then
install_agent_deck || exit 1
else
echo "Skipped."
fi
step "Done"
cat <<EOF
Installation complete. Test:
lazygit-sidecar zsh
(If PATH was updated, open a new terminal or run: source ~/.zshrc)
Uninstall later with: $0 --uninstall
EOF
}
interactive_uninstall() {
step "Uninstall step 1/2: lazygit-sidecar binary"
if [ -f "$BIN_DEST" ]; then
echo "Will remove: $BIN_DEST"
if confirm "Remove?"; then
rm -f "$BIN_DEST" && echo "removed."
else
echo "Skipped."
fi
else
echo "$BIN_DEST not present; skip."
fi
step "Uninstall step 2/2: agent-deck integration"
if has_block "$TMUX_CONF" || has_block "$ZSHRC"; then
if confirm "Remove integration blocks from ~/.tmux.conf and ~/.zshrc?"; then
uninstall_agent_deck
else
echo "Skipped."
fi
else
echo "No integration blocks found; skip."
fi
step "Done"
cat <<EOF
lazygit stays installed (standalone tool). Remove with:
brew uninstall lazygit
EOF
}
usage() {
sed -n '2,14p' "$0" | sed 's/^# \{0,1\}//'
}
# ---------- dispatch ----------
case "${1:-}" in
"") interactive_install ;;
--core) install_core ;;
--agent-deck) install_agent_deck ;;
--all) install_core && install_agent_deck ;;
--uninstall) interactive_uninstall ;;
--uninstall-core) uninstall_core ;;
--uninstall-agent-deck) uninstall_agent_deck ;;
--help|-h) usage ;;
*)
echo "unknown option: $1" >&2
usage >&2
exit 2
;;
esac