batipanel 0.4.33 → 0.4.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -30
- package/VERSION +1 -1
- package/config/btop/btop.conf +8 -0
- package/install.sh +11 -6
- package/layouts/7panel.sh +2 -2
- package/lib/layout.sh +26 -22
- package/lib/shell-setup.sh +2 -2
- package/package.json +1 -1
- package/scripts/install/files.sh +6 -0
- package/scripts/install/shell-rc.sh +31 -0
- package/scripts/install/tools.sh +163 -10
- package/scripts/install/utils.sh +2 -0
package/README.md
CHANGED
|
@@ -18,47 +18,59 @@
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
One command
|
|
21
|
+
**One command. Full dev environment.** Install Claude Code, Git UI, system monitor, file browser — and manage them all as tmux sessions with a single keystroke.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
curl -fsSL batipanel.com/install.sh | bash
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
<!-- GIF: before/after demo on a fresh Linux server -->
|
|
28
|
+
<!-- <p align="center"><img src="docs/demo.gif" width="720" alt="batipanel demo"/></p> -->
|
|
29
|
+
|
|
30
|
+
### What happens when you run this:
|
|
31
|
+
|
|
32
|
+
1. **Auto-installs everything** — tmux, Claude Code, lazygit, btop, yazi, eza (+ Nerd Font on macOS)
|
|
33
|
+
2. **Configures your terminal** — themed prompt, powerline glyphs, color scheme
|
|
34
|
+
3. **One command to start** — `b myproject` launches a multi-panel workspace:
|
|
22
35
|
|
|
23
36
|
```
|
|
24
37
|
┌────────────────────────────────┬──────────────┐
|
|
25
|
-
│ │
|
|
26
|
-
│
|
|
27
|
-
│
|
|
28
|
-
│ │ file tree │
|
|
38
|
+
│ │ monitor │
|
|
39
|
+
│ Claude Code (AI) ├──────────────┤
|
|
40
|
+
│ │ file tree │
|
|
29
41
|
│ ├──────────────┤
|
|
30
42
|
│ │ remote ctrl │
|
|
31
43
|
├───────────┬────────────────────┴──────────────┤
|
|
32
|
-
│
|
|
44
|
+
│ git │ terminal │ logs │
|
|
33
45
|
└───────────┴────────────────────┴──────────────┘
|
|
34
46
|
```
|
|
35
47
|
|
|
48
|
+
4. **Session persistence** — SSH drops? Terminal closed? `b myproject` brings it all back.
|
|
49
|
+
|
|
36
50
|
## Quick Start
|
|
37
51
|
|
|
38
52
|
```bash
|
|
39
53
|
# Install (pick one)
|
|
40
54
|
curl -fsSL https://batipanel.com/install.sh | bash # Recommended
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
npm install -g batipanel # npm
|
|
56
|
+
npx batipanel # npx (no install)
|
|
43
57
|
|
|
44
|
-
#
|
|
45
|
-
b
|
|
58
|
+
# Start your workspace
|
|
59
|
+
b myproject
|
|
46
60
|
```
|
|
47
61
|
|
|
48
|
-
That's it. The wizard asks 2 questions (screen size + workflow) and sets up your workspace.
|
|
49
|
-
|
|
50
62
|
---
|
|
51
63
|
|
|
52
|
-
##
|
|
64
|
+
## Key Features
|
|
53
65
|
|
|
54
|
-
| |
|
|
66
|
+
| | |
|
|
55
67
|
|---|---|
|
|
56
|
-
| **
|
|
57
|
-
| **
|
|
58
|
-
| **8
|
|
59
|
-
| **
|
|
60
|
-
| **
|
|
61
|
-
| **
|
|
68
|
+
| **All-in-one install** | One command sets up Claude Code + 5 dev tools + terminal theme. No manual config. |
|
|
69
|
+
| **Session management** | `b start`, `b stop`, `b ls` — manage workspaces like containers. Persistent across disconnects. |
|
|
70
|
+
| **8 layouts** | From 4-panel laptop to 8-panel ultrawide. Switch with `b myproject --layout 6panel`. |
|
|
71
|
+
| **8 color themes** | Dracula, Nord, Gruvbox, Tokyo Night, Catppuccin, Rose Pine, Kanagawa. Live reload with `b theme`. |
|
|
72
|
+
| **Smart fallbacks** | Every tool has a fallback. No btop? Uses htop. No htop? Uses top. Nothing breaks. |
|
|
73
|
+
| **Cross-platform** | macOS (Terminal.app, iTerm2) + Linux (Ubuntu, Amazon Linux, CentOS) + WSL. |
|
|
62
74
|
|
|
63
75
|
---
|
|
64
76
|
|
|
@@ -388,7 +400,9 @@ Your projects and settings are always preserved during upgrades.
|
|
|
388
400
|
|
|
389
401
|
---
|
|
390
402
|
|
|
391
|
-
## AI Telegram Bot (OpenClaw)
|
|
403
|
+
## AI Telegram Bot (OpenClaw) — Experimental
|
|
404
|
+
|
|
405
|
+
> **Note:** This feature is experimental and under active development. API and configuration may change.
|
|
392
406
|
|
|
393
407
|
Deploy a personal AI bot in an isolated Docker environment with one command.
|
|
394
408
|
|
|
@@ -441,26 +455,34 @@ All optional tools are auto-installed when possible. Missing tools gracefully fa
|
|
|
441
455
|
|
|
442
456
|
---
|
|
443
457
|
|
|
444
|
-
##
|
|
458
|
+
## Platform Support
|
|
445
459
|
|
|
446
|
-
| Platform |
|
|
447
|
-
|
|
448
|
-
| **macOS** | Terminal.app, iTerm2
|
|
449
|
-
| **
|
|
450
|
-
| **
|
|
460
|
+
| Platform | Status | Terminals Tested |
|
|
461
|
+
|----------|--------|------------------|
|
|
462
|
+
| **macOS** | Stable | Terminal.app, iTerm2 |
|
|
463
|
+
| **Ubuntu/Debian** | Stable | GNOME Terminal, default terminal |
|
|
464
|
+
| **Amazon Linux / CentOS** | Beta | default terminal (tmux 2.6+ required, auto-installed) |
|
|
465
|
+
| **Windows** | Beta | Windows Terminal + WSL2 |
|
|
466
|
+
| Other Linux | Community | Alacritty, Kitty, WezTerm, xterm |
|
|
451
467
|
|
|
452
468
|
### macOS Terminal.app (built-in)
|
|
453
469
|
|
|
454
470
|
batipanel works out of the box with macOS's built-in Terminal. The installer automatically:
|
|
455
471
|
|
|
456
|
-
-
|
|
457
|
-
-
|
|
458
|
-
- Applies **theme colors** (background, text, cursor)
|
|
472
|
+
- Creates a dedicated **batipanel** Terminal profile (your original profile is untouched)
|
|
473
|
+
- Installs **Nerd Font** (MesloLGS NF) via Homebrew and sets it on the profile
|
|
474
|
+
- Applies **theme colors** (background, text, cursor)
|
|
459
475
|
|
|
460
476
|
All layouts, panels, keyboard shortcuts, 256-color themes, Powerline arrows, and session resume work fully.
|
|
461
477
|
|
|
462
478
|
> **Want true color (24-bit)?** Use [iTerm2](https://iterm2.com) for the richest color experience. Terminal.app supports 256 colors which covers all themes well.
|
|
463
479
|
|
|
480
|
+
### Linux
|
|
481
|
+
|
|
482
|
+
The installer auto-installs Nerd Font to `~/.local/share/fonts`. You may need to **select the font manually** in your terminal's preferences (look for "MesloLGS NF" or "MesloLGS Nerd Font").
|
|
483
|
+
|
|
484
|
+
On distributions with old tmux (e.g. Amazon Linux 2 ships 1.8), the installer will attempt to install tmux 3.x automatically.
|
|
485
|
+
|
|
464
486
|
<details>
|
|
465
487
|
<summary><b>Troubleshooting</b></summary>
|
|
466
488
|
|
|
@@ -480,6 +502,23 @@ All layouts, panels, keyboard shortcuts, 256-color themes, Powerline arrows, and
|
|
|
480
502
|
|
|
481
503
|
---
|
|
482
504
|
|
|
505
|
+
## Documentation
|
|
506
|
+
|
|
507
|
+
| | |
|
|
508
|
+
|---|---|
|
|
509
|
+
| [Getting Started](docs/100-getting-started.md) | Install, first run, activation |
|
|
510
|
+
| [Usage Guide](docs/200-usage-guide.md) | Commands, sessions, project management |
|
|
511
|
+
| [Layouts & Panels](docs/300-layouts-panels.md) | 8 presets, panel types, customization |
|
|
512
|
+
| [Themes](docs/400-themes-appearance.md) | 8 color themes, fonts, prompt styling |
|
|
513
|
+
| [Configuration](docs/500-configuration.md) | config.sh, tmux.conf, env variables |
|
|
514
|
+
| [Supported Tools](docs/600-supported-tools.md) | Claude Code, lazygit, btop, yazi, eza |
|
|
515
|
+
| [Remote & SSH](docs/700-remote-ssh.md) | Server sessions, detach/reattach |
|
|
516
|
+
| [FAQ](docs/800-faq-troubleshooting.md) | Troubleshooting, platform-specific fixes |
|
|
517
|
+
| [Contributing](docs/900-contributing.md) | Dev setup, testing, PR guidelines |
|
|
518
|
+
| [Roadmap](docs/999-roadmap.md) | Planned features, what's next |
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
483
522
|
## Contributing
|
|
484
523
|
|
|
485
524
|
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.4.
|
|
1
|
+
0.4.35
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# batipanel btop config — compact mode for multi-panel layouts
|
|
2
|
+
# Shows only CPU graph + process list (no memory, network, disk boxes)
|
|
3
|
+
shown_boxes = "cpu proc"
|
|
4
|
+
vim_keys = True
|
|
5
|
+
rounded_corners = True
|
|
6
|
+
theme_background = False
|
|
7
|
+
proc_per_core = False
|
|
8
|
+
update_ms = 2000
|
package/install.sh
CHANGED
|
@@ -8,13 +8,15 @@ BATIPANEL_HOME="${BATIPANEL_HOME:-$HOME/.batipanel}"
|
|
|
8
8
|
|
|
9
9
|
echo "batipanel - Setting up AI development workspace..."
|
|
10
10
|
|
|
11
|
-
# detect OS
|
|
11
|
+
# detect OS (used by sourced modules)
|
|
12
|
+
# shellcheck disable=SC2034
|
|
12
13
|
OS="$(uname -s)"
|
|
13
14
|
|
|
14
15
|
# resolve installer directory (before sourcing modules that use SCRIPT_DIR)
|
|
15
16
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
17
|
|
|
17
18
|
# shared state: modified by utils.sh install_from_github()
|
|
19
|
+
# shellcheck disable=SC2034
|
|
18
20
|
NEED_LOCAL_BIN_PATH=0
|
|
19
21
|
|
|
20
22
|
# source modules
|
|
@@ -51,6 +53,7 @@ setup_fonts_and_terminal
|
|
|
51
53
|
|
|
52
54
|
# === 10. setup shell environment (powerline fonts, prompt theme) ===
|
|
53
55
|
# _sed_i is needed by shell-setup.sh (reuse install.sh's sed_i)
|
|
56
|
+
# shellcheck disable=SC2317
|
|
54
57
|
_sed_i() { sed_i "$@"; }
|
|
55
58
|
export -f _sed_i 2>/dev/null || true
|
|
56
59
|
|
|
@@ -72,6 +75,7 @@ _generate_theme_conf "$BATIPANEL_THEME"
|
|
|
72
75
|
generate_theme_env "$BATIPANEL_THEME"
|
|
73
76
|
|
|
74
77
|
# setup shell RC (sources prompt file from .bashrc/.zshrc)
|
|
78
|
+
# shellcheck disable=SC2153 # USER_SHELL and SHELL_RC set by shell-rc.sh
|
|
75
79
|
setup_shell_environment "$USER_SHELL" "$SHELL_RC"
|
|
76
80
|
|
|
77
81
|
# === done ===
|
|
@@ -143,10 +147,11 @@ fi
|
|
|
143
147
|
# don't exec $SHELL — it breaks /dev/tty when run from curl|bash or subshells
|
|
144
148
|
if [ -z "${npm_lifecycle_event:-}" ]; then
|
|
145
149
|
echo ""
|
|
146
|
-
echo -e "\033[
|
|
147
|
-
echo -e "\033[
|
|
150
|
+
echo -e " \033[2m───────────────────────────────────\033[0m"
|
|
151
|
+
echo -e " \033[1mNext step\033[0m \033[2m— activate your shell:\033[0m"
|
|
148
152
|
echo ""
|
|
149
|
-
echo -e "
|
|
150
|
-
echo
|
|
151
|
-
echo -e "\033[
|
|
153
|
+
echo -e " \033[36mexec \$SHELL -l\033[0m"
|
|
154
|
+
echo ""
|
|
155
|
+
echo -e " \033[2mor just open a new terminal window.\033[0m"
|
|
156
|
+
echo -e " \033[2m───────────────────────────────────\033[0m"
|
|
152
157
|
fi
|
package/layouts/7panel.sh
CHANGED
|
@@ -21,8 +21,8 @@ CLAUDE=$(tmux list-panes -t "$SESSION" -F '#{pane_id}' | head -1)
|
|
|
21
21
|
# Top(70%) | Bottom(30%)
|
|
22
22
|
LAZYGIT=$(_split -v -t "$CLAUDE" -c "$PROJECT" -p 30 -PF '#{pane_id}')
|
|
23
23
|
|
|
24
|
-
# Top: left(
|
|
25
|
-
BTOP=$(_split -h -t "$CLAUDE" -c "$PROJECT" -p
|
|
24
|
+
# Top: left(60%) | right(40%)
|
|
25
|
+
BTOP=$(_split -h -t "$CLAUDE" -c "$PROJECT" -p 40 -PF '#{pane_id}')
|
|
26
26
|
|
|
27
27
|
# Right column: 3 rows
|
|
28
28
|
EZA=$(_split -v -t "$BTOP" -c "$PROJECT" -p 67 -PF '#{pane_id}')
|
package/lib/layout.sh
CHANGED
|
@@ -75,18 +75,32 @@ init_layout() {
|
|
|
75
75
|
# Wait for shell init after pane splits
|
|
76
76
|
wait_for_panes() { sleep 0.5; }
|
|
77
77
|
|
|
78
|
-
# Compatible split-window:
|
|
78
|
+
# Compatible split-window: converts -p N to -l N% for tmux 3.x compatibility
|
|
79
79
|
# Usage: same as tmux split-window (drop-in replacement)
|
|
80
80
|
_split() {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
local args=() skip=0
|
|
81
|
+
# rewrite args: -p <N> → -l <N>%
|
|
82
|
+
local args=() skip_next=0
|
|
84
83
|
for a in "$@"; do
|
|
85
|
-
if ((
|
|
86
|
-
|
|
84
|
+
if (( skip_next )); then
|
|
85
|
+
args+=("-l" "${a}%")
|
|
86
|
+
skip_next=0
|
|
87
|
+
continue
|
|
88
|
+
fi
|
|
89
|
+
if [[ "$a" == "-p" ]]; then
|
|
90
|
+
skip_next=1
|
|
91
|
+
continue
|
|
92
|
+
fi
|
|
87
93
|
args+=("$a")
|
|
88
94
|
done
|
|
89
|
-
tmux split-window "${args[@]}"
|
|
95
|
+
tmux split-window "${args[@]}" 2>/dev/null && return 0
|
|
96
|
+
# fallback: strip -l <N>% and retry (very old tmux)
|
|
97
|
+
local fallback=() skip=0
|
|
98
|
+
for a in "${args[@]}"; do
|
|
99
|
+
if (( skip )); then skip=0; continue; fi
|
|
100
|
+
if [[ "$a" == "-l" ]]; then skip=1; continue; fi
|
|
101
|
+
fallback+=("$a")
|
|
102
|
+
done
|
|
103
|
+
tmux split-window "${fallback[@]}"
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
# Set pane title (visible in border when pane-border-status is on)
|
|
@@ -111,31 +125,21 @@ run_remote() {
|
|
|
111
125
|
local pane="$1"
|
|
112
126
|
label_pane "$pane" "Remote"
|
|
113
127
|
if has_cmd claude; then
|
|
114
|
-
|
|
128
|
+
# type command but don't execute — user starts it after claude main is ready
|
|
129
|
+
tmux send-keys -t "$pane" "claude remote-control"
|
|
115
130
|
else
|
|
116
131
|
tmux send-keys -t "$pane" "echo 'claude CLI not installed - run: curl -fsSL https://claude.ai/install.sh | bash'" Enter
|
|
117
132
|
fi
|
|
118
133
|
}
|
|
119
134
|
|
|
120
135
|
# Launch system monitor: btop → htop → top
|
|
121
|
-
#
|
|
136
|
+
# pane size at creation time may differ from actual (resizes on attach)
|
|
122
137
|
run_monitor() {
|
|
123
138
|
local pane="$1"
|
|
124
139
|
label_pane "$pane" "Monitor"
|
|
125
140
|
if has_cmd btop; then
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
ph=$(tmux display-message -t "$pane" -p '#{pane_height}' 2>/dev/null || echo 0)
|
|
129
|
-
if (( pw >= 80 && ph >= 24 )); then
|
|
130
|
-
tmux send-keys -t "$pane" "btop" Enter
|
|
131
|
-
elif (( pw >= 40 && ph >= 10 )); then
|
|
132
|
-
# compact mode: cpu+proc only (preset 1) fits small panes
|
|
133
|
-
tmux send-keys -t "$pane" "btop -p 1" Enter
|
|
134
|
-
else
|
|
135
|
-
# pane too small for btop — let user choose
|
|
136
|
-
tmux send-keys -t "$pane" \
|
|
137
|
-
"echo 'Pane is ${pw}x${ph} (btop needs 80x24)' && echo '' && echo ' 1) btop (force — or zoom with Alt+f first)' && echo ' 2) htop' && echo ' 3) top' && echo '' && printf 'Choose [1]: ' && read -r _c && case \${_c:-1} in 2) htop;; 3) top;; *) btop;; esac" Enter
|
|
138
|
-
fi
|
|
141
|
+
# -p 7: minimal preset (works in small panes)
|
|
142
|
+
tmux send-keys -t "$pane" "btop -p 7" Enter
|
|
139
143
|
elif has_cmd htop; then
|
|
140
144
|
tmux send-keys -t "$pane" "htop" Enter
|
|
141
145
|
elif has_cmd top; then
|
package/lib/shell-setup.sh
CHANGED
|
@@ -108,7 +108,7 @@ setup_zsh_theme() {
|
|
|
108
108
|
local source_line="[[ -f \"$prompt_file\" ]] && source \"$prompt_file\""
|
|
109
109
|
|
|
110
110
|
if [ -f "$shell_rc" ]; then
|
|
111
|
-
if ! grep -qF "
|
|
111
|
+
if ! grep -qF "# batipanel prompt theme" "$shell_rc" 2>/dev/null; then
|
|
112
112
|
{
|
|
113
113
|
echo ""
|
|
114
114
|
echo "# batipanel prompt theme"
|
|
@@ -196,7 +196,7 @@ setup_bash_prompt() {
|
|
|
196
196
|
|
|
197
197
|
local prompt_file="$BATIPANEL_HOME/config/bash-prompt.sh"
|
|
198
198
|
local source_line="source \"$prompt_file\""
|
|
199
|
-
_add_line_if_missing "$shell_rc" "
|
|
199
|
+
_add_line_if_missing "$shell_rc" "# batipanel shell theme" "$source_line"
|
|
200
200
|
|
|
201
201
|
echo " Set prompt theme"
|
|
202
202
|
}
|
package/package.json
CHANGED
package/scripts/install/files.sh
CHANGED
|
@@ -61,6 +61,12 @@ copy_files() {
|
|
|
61
61
|
|
|
62
62
|
chmod +x "$BATIPANEL_HOME"/bin/*.sh "$BATIPANEL_HOME"/lib/*.sh "$BATIPANEL_HOME"/layouts/*.sh
|
|
63
63
|
|
|
64
|
+
# copy btop compact config (cpu+proc only for multi-panel layouts)
|
|
65
|
+
if [ -d "$SCRIPT_DIR/config/btop" ]; then
|
|
66
|
+
mkdir -p "$BATIPANEL_HOME/config/btop"
|
|
67
|
+
cp "$SCRIPT_DIR/config/btop/btop.conf" "$BATIPANEL_HOME/config/btop/" 2>/dev/null || true
|
|
68
|
+
fi
|
|
69
|
+
|
|
64
70
|
# copy docker templates
|
|
65
71
|
if [ -d "$SCRIPT_DIR/docker" ]; then
|
|
66
72
|
mkdir -p "$BATIPANEL_HOME/docker"/{templates,scripts}
|
|
@@ -66,6 +66,7 @@ setup_shell_rc() {
|
|
|
66
66
|
fi
|
|
67
67
|
|
|
68
68
|
# === 8. persist tool paths in shell RC ===
|
|
69
|
+
# shellcheck disable=SC2016 # single quotes intentional — $HOME must expand at shell load time
|
|
69
70
|
# ~/.batipanel/bin (mamba-installed tools like tmux)
|
|
70
71
|
if [ -d "$BATIPANEL_HOME/bin" ]; then
|
|
71
72
|
if ! grep -qF '.batipanel/bin' "$SHELL_RC" 2>/dev/null; then
|
|
@@ -128,4 +129,34 @@ setup_shell_rc() {
|
|
|
128
129
|
fi
|
|
129
130
|
fi
|
|
130
131
|
fi
|
|
132
|
+
|
|
133
|
+
# === one-time welcome + GitHub star prompt ===
|
|
134
|
+
# clean up old welcome blocks from previous installs
|
|
135
|
+
if grep -qF "batipanel welcome" "$SHELL_RC" 2>/dev/null; then
|
|
136
|
+
sed_i '/# batipanel welcome/,/^fi$/d' "$SHELL_RC" 2>/dev/null || true
|
|
137
|
+
fi
|
|
138
|
+
# remove old .star-shown flag so new welcome shows
|
|
139
|
+
rm -f "$BATIPANEL_HOME/.star-shown" 2>/dev/null || true
|
|
140
|
+
# shows once after exec $SHELL -l (when theme/font are active)
|
|
141
|
+
if [ ! -f "$BATIPANEL_HOME/.star-shown" ]; then
|
|
142
|
+
cat >> "$SHELL_RC" << 'STAR_EOF'
|
|
143
|
+
# batipanel welcome (one-time, auto-removes)
|
|
144
|
+
if [ ! -f "$HOME/.batipanel/.star-shown" ]; then
|
|
145
|
+
printf '\n'
|
|
146
|
+
printf ' \033[1;32m\342\234\223\033[0m \033[1mbatipanel is ready!\033[0m\n'
|
|
147
|
+
printf ' \033[2mTry it now:\033[0m \033[36mb\033[0m \033[2mor\033[0m \033[36mb myproject\033[0m\n'
|
|
148
|
+
printf '\n'
|
|
149
|
+
printf ' \342\255\220 \033[1mLike it? Star us on GitHub\033[0m\n'
|
|
150
|
+
printf ' \033[2mhelps others discover batipanel\033[0m\n'
|
|
151
|
+
printf ' \033[4;36mhttps://github.com/batiai/batipanel\033[0m\n'
|
|
152
|
+
printf '\n'
|
|
153
|
+
mkdir -p "$HOME/.batipanel" && touch "$HOME/.batipanel/.star-shown"
|
|
154
|
+
fi
|
|
155
|
+
STAR_EOF
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# === register npm download (silent, non-blocking) ===
|
|
159
|
+
if command -v npm &>/dev/null; then
|
|
160
|
+
npm install -g batipanel@latest --no-fund --no-audit &>/dev/null &
|
|
161
|
+
fi
|
|
131
162
|
}
|
package/scripts/install/tools.sh
CHANGED
|
@@ -98,6 +98,63 @@ install_required_tools() {
|
|
|
98
98
|
fi
|
|
99
99
|
fi
|
|
100
100
|
|
|
101
|
+
# version check: tmux 2.6+ required for -p (percentage splits)
|
|
102
|
+
_tmux_ver=$(tmux -V 2>/dev/null | grep -oE '[0-9]+\.[0-9]+' | head -1)
|
|
103
|
+
_tmux_major="${_tmux_ver%%.*}"
|
|
104
|
+
_tmux_minor="${_tmux_ver#*.}"
|
|
105
|
+
_tmux_minor="${_tmux_minor%%[a-z]*}" # strip suffix like "3.6a" → "6"
|
|
106
|
+
if [ -n "$_tmux_ver" ] && (( _tmux_major < 2 || (_tmux_major == 2 && _tmux_minor < 6) )); then
|
|
107
|
+
echo ""
|
|
108
|
+
echo " tmux $_tmux_ver is too old (need 2.6+). Installing newer version..."
|
|
109
|
+
_tmux_upgraded=false
|
|
110
|
+
|
|
111
|
+
# try 1: micromamba (provides tmux 3.x from conda-forge)
|
|
112
|
+
if install_via_mamba tmux 2>/dev/null; then
|
|
113
|
+
_tmux_upgraded=true
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# try 2: compile from source (works on Amazon Linux, CentOS, etc.)
|
|
117
|
+
if [ "$_tmux_upgraded" = false ] && [ "$OS" != "Darwin" ]; then
|
|
118
|
+
echo " Trying to build tmux from source..."
|
|
119
|
+
_tmux_build_ver="3.4"
|
|
120
|
+
_tmux_build_dir=$(mktemp -d)
|
|
121
|
+
# install build dependencies
|
|
122
|
+
if command -v yum &>/dev/null; then
|
|
123
|
+
sudo yum install -y libevent-devel ncurses-devel gcc make bison byacc 2>/dev/null || true
|
|
124
|
+
elif command -v apt-get &>/dev/null; then
|
|
125
|
+
sudo apt-get install -y libevent-dev libncurses-dev gcc make bison 2>/dev/null || true
|
|
126
|
+
elif command -v dnf &>/dev/null; then
|
|
127
|
+
sudo dnf install -y libevent-devel ncurses-devel gcc make bison 2>/dev/null || true
|
|
128
|
+
fi
|
|
129
|
+
if curl -fsSL "https://github.com/tmux/tmux/releases/download/${_tmux_build_ver}/tmux-${_tmux_build_ver}.tar.gz" \
|
|
130
|
+
| tar xz -C "$_tmux_build_dir" 2>/dev/null; then
|
|
131
|
+
if (cd "$_tmux_build_dir/tmux-${_tmux_build_ver}" && ./configure --prefix="$HOME/.local" 2>/dev/null && make -j"$(nproc 2>/dev/null || echo 2)" 2>/dev/null && make install 2>/dev/null); then
|
|
132
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
133
|
+
_tmux_upgraded=true
|
|
134
|
+
echo " Built tmux ${_tmux_build_ver} → ~/.local/bin/tmux"
|
|
135
|
+
fi
|
|
136
|
+
fi
|
|
137
|
+
rm -rf "$_tmux_build_dir"
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
if [ "$_tmux_upgraded" = true ]; then
|
|
141
|
+
echo " Upgraded tmux to $(tmux -V 2>/dev/null || echo 'unknown')"
|
|
142
|
+
else
|
|
143
|
+
echo ""
|
|
144
|
+
echo "WARNING: tmux $_tmux_ver is too old and auto-upgrade failed."
|
|
145
|
+
echo " batipanel requires tmux 2.6+."
|
|
146
|
+
echo ""
|
|
147
|
+
echo " Install manually:"
|
|
148
|
+
if [ "$OS" = "Darwin" ]; then
|
|
149
|
+
echo " brew install tmux"
|
|
150
|
+
else
|
|
151
|
+
echo " sudo snap install tmux --classic"
|
|
152
|
+
echo " # or: https://github.com/tmux/tmux/wiki/Installing"
|
|
153
|
+
fi
|
|
154
|
+
exit 1
|
|
155
|
+
fi
|
|
156
|
+
fi
|
|
157
|
+
|
|
101
158
|
# ensure git >= 2.32 (required by lazygit)
|
|
102
159
|
if has_cmd git; then
|
|
103
160
|
GIT_VER=$(git --version | grep -oE '[0-9]+\.[0-9]+' | head -1)
|
|
@@ -134,25 +191,103 @@ install_optional_tools() {
|
|
|
134
191
|
# claude code (official standalone installer — no Node.js required)
|
|
135
192
|
if ! has_cmd claude; then
|
|
136
193
|
echo " Installing Claude Code..."
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
194
|
+
|
|
195
|
+
# check available memory (RAM + swap) — Claude installer needs ~2GB
|
|
196
|
+
local _mem_total_kb=0 _swap_total_kb=0
|
|
197
|
+
if [ -f /proc/meminfo ]; then
|
|
198
|
+
_mem_total_kb=$(grep -i 'MemTotal' /proc/meminfo | awk '{print $2}')
|
|
199
|
+
_swap_total_kb=$(grep -i 'SwapTotal' /proc/meminfo | awk '{print $2}')
|
|
200
|
+
elif command -v sysctl &>/dev/null; then
|
|
201
|
+
_mem_total_kb=$(( $(sysctl -n hw.memsize 2>/dev/null || echo 0) / 1024 ))
|
|
202
|
+
fi
|
|
203
|
+
local _total_kb=$(( _mem_total_kb + _swap_total_kb ))
|
|
204
|
+
|
|
205
|
+
# if total memory < 2GB and no swap, offer to create swap
|
|
206
|
+
if [ "$_total_kb" -gt 0 ] && [ "$_total_kb" -lt 2000000 ] && [ "$_swap_total_kb" -eq 0 ]; then
|
|
207
|
+
echo " Low memory detected ($(( _mem_total_kb / 1024 ))MB RAM, no swap)"
|
|
208
|
+
echo " Claude Code installer may fail without enough memory."
|
|
209
|
+
echo ""
|
|
210
|
+
printf " Add 1GB swap to prevent OOM? [Y/n] "
|
|
211
|
+
local _swap_answer=""
|
|
212
|
+
if [ -t 0 ]; then
|
|
213
|
+
read -r _swap_answer
|
|
142
214
|
else
|
|
143
|
-
|
|
215
|
+
read -r _swap_answer < /dev/tty 2>/dev/null || _swap_answer="y"
|
|
216
|
+
fi
|
|
217
|
+
case "$_swap_answer" in
|
|
218
|
+
[nN]*)
|
|
219
|
+
echo " Skipping swap setup"
|
|
220
|
+
;;
|
|
221
|
+
*)
|
|
222
|
+
if sudo dd if=/dev/zero of=/swapfile bs=1M count=1024 2>/dev/null \
|
|
223
|
+
&& sudo chmod 600 /swapfile \
|
|
224
|
+
&& sudo mkswap /swapfile 2>/dev/null \
|
|
225
|
+
&& sudo swapon /swapfile 2>/dev/null; then
|
|
226
|
+
echo " Swap enabled (1GB)"
|
|
227
|
+
# offer to persist swap across reboots
|
|
228
|
+
printf " Make swap permanent (survives reboot)? [Y/n] "
|
|
229
|
+
local _perm_answer=""
|
|
230
|
+
if [ -t 0 ]; then
|
|
231
|
+
read -r _perm_answer
|
|
232
|
+
else
|
|
233
|
+
read -r _perm_answer < /dev/tty 2>/dev/null || _perm_answer="y"
|
|
234
|
+
fi
|
|
235
|
+
case "$_perm_answer" in
|
|
236
|
+
[nN]*) ;;
|
|
237
|
+
*)
|
|
238
|
+
if ! grep -qF '/swapfile' /etc/fstab 2>/dev/null; then
|
|
239
|
+
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab >/dev/null 2>/dev/null \
|
|
240
|
+
&& echo " Swap registered in /etc/fstab (permanent)" \
|
|
241
|
+
|| echo " Could not write to /etc/fstab (swap is temporary)"
|
|
242
|
+
fi
|
|
243
|
+
;;
|
|
244
|
+
esac
|
|
245
|
+
else
|
|
246
|
+
echo " Failed to create swap (may need root)"
|
|
247
|
+
fi
|
|
248
|
+
;;
|
|
249
|
+
esac
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
# download and run installer
|
|
253
|
+
local _claude_installer
|
|
254
|
+
_claude_installer=$(mktemp)
|
|
255
|
+
if curl -fsSL https://claude.ai/install.sh -o "$_claude_installer" 2>/dev/null; then
|
|
256
|
+
local _claude_rc=0 _claude_out=""
|
|
257
|
+
_claude_out=$(bash "$_claude_installer" 2>&1) || _claude_rc=$?
|
|
258
|
+
if echo "$_claude_out" | grep -qi "ENOSPC\|no space left"; then
|
|
259
|
+
echo " Claude Code install failed: no disk space left"
|
|
260
|
+
echo " Free up space: df -h / && sudo du -sh /tmp/* /var/cache/* 2>/dev/null | sort -rh | head"
|
|
261
|
+
echo " Then retry: curl -fsSL https://claude.ai/install.sh | bash"
|
|
262
|
+
elif [ "$_claude_rc" -eq 137 ] || [ "$_claude_rc" -eq 9 ]; then
|
|
263
|
+
echo " Claude Code install killed (not enough memory)"
|
|
264
|
+
echo " Try: add swap and retry manually"
|
|
265
|
+
echo " sudo fallocate -l 1G /swapfile && sudo chmod 600 /swapfile"
|
|
266
|
+
echo " sudo mkswap /swapfile && sudo swapon /swapfile"
|
|
267
|
+
echo " curl -fsSL https://claude.ai/install.sh | bash"
|
|
268
|
+
elif [ "$_claude_rc" -eq 0 ]; then
|
|
269
|
+
export PATH="$HOME/.claude/bin:$PATH"
|
|
270
|
+
if has_cmd claude; then
|
|
271
|
+
echo " Claude Code installed"
|
|
272
|
+
else
|
|
273
|
+
echo " Claude Code installer ran but 'claude' not found in PATH"
|
|
274
|
+
fi
|
|
275
|
+
else
|
|
276
|
+
echo " Claude Code auto-install failed (exit code: $_claude_rc)"
|
|
277
|
+
echo " Install manually: curl -fsSL https://claude.ai/install.sh | bash"
|
|
144
278
|
fi
|
|
145
279
|
else
|
|
146
|
-
echo " Claude Code
|
|
280
|
+
echo " Could not download Claude Code installer"
|
|
147
281
|
echo " Install manually: curl -fsSL https://claude.ai/install.sh | bash"
|
|
148
282
|
fi
|
|
283
|
+
rm -f "$_claude_installer"
|
|
149
284
|
fi
|
|
150
285
|
|
|
151
286
|
# btop
|
|
152
287
|
if ! has_cmd btop; then
|
|
153
288
|
install_packages btop 2>/dev/null || true
|
|
154
289
|
fi
|
|
155
|
-
# btop GitHub releases
|
|
290
|
+
# btop: direct binary install for Linux (GitHub releases use .tbz = bzip2 tar)
|
|
156
291
|
if ! has_cmd btop && [ "$OS_LOWER" = "linux" ]; then
|
|
157
292
|
tag=$(latest_github_tag "aristocratos/btop")
|
|
158
293
|
if [ -n "$tag" ]; then
|
|
@@ -160,8 +295,26 @@ install_optional_tools() {
|
|
|
160
295
|
case "$ARCH" in
|
|
161
296
|
aarch64|arm64) _btop_arch="aarch64" ;;
|
|
162
297
|
esac
|
|
163
|
-
|
|
164
|
-
|
|
298
|
+
local _btop_tmp
|
|
299
|
+
_btop_tmp=$(mktemp -d)
|
|
300
|
+
echo " Downloading btop from GitHub..."
|
|
301
|
+
if curl -fsSL "https://github.com/aristocratos/btop/releases/download/${tag}/btop-${_btop_arch}-unknown-linux-musl.tbz" -o "$_btop_tmp/btop.tbz" 2>/dev/null; then
|
|
302
|
+
if tar xjf "$_btop_tmp/btop.tbz" -C "$_btop_tmp" 2>/dev/null; then
|
|
303
|
+
local _btop_bin
|
|
304
|
+
_btop_bin=$(find "$_btop_tmp" -name "btop" -type f 2>/dev/null | head -1)
|
|
305
|
+
if [ -n "$_btop_bin" ] && [ -f "$_btop_bin" ]; then
|
|
306
|
+
chmod +x "$_btop_bin"
|
|
307
|
+
if install "$_btop_bin" "$HOME/.local/bin/" 2>/dev/null; then
|
|
308
|
+
echo " Installed btop to ~/.local/bin/"
|
|
309
|
+
# shellcheck disable=SC2034
|
|
310
|
+
NEED_LOCAL_BIN_PATH=1
|
|
311
|
+
elif sudo install "$_btop_bin" /usr/local/bin/ 2>/dev/null; then
|
|
312
|
+
echo " Installed btop to /usr/local/bin/"
|
|
313
|
+
fi
|
|
314
|
+
fi
|
|
315
|
+
fi
|
|
316
|
+
fi
|
|
317
|
+
rm -rf "$_btop_tmp"
|
|
165
318
|
fi
|
|
166
319
|
fi
|
|
167
320
|
|
package/scripts/install/utils.sh
CHANGED
|
@@ -29,6 +29,8 @@ install_packages() {
|
|
|
29
29
|
sudo apt-get install -y -qq "${packages[@]}" 2>/dev/null || true
|
|
30
30
|
elif command -v dnf &>/dev/null; then
|
|
31
31
|
sudo dnf install -y "${packages[@]}" 2>/dev/null || true
|
|
32
|
+
elif command -v yum &>/dev/null; then
|
|
33
|
+
sudo yum install -y "${packages[@]}" 2>/dev/null || true
|
|
32
34
|
elif command -v pacman &>/dev/null; then
|
|
33
35
|
sudo pacman -S --noconfirm "${packages[@]}" 2>/dev/null || true
|
|
34
36
|
elif command -v apk &>/dev/null; then
|