@atercates/claude-deck 0.2.10 → 0.2.11
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/package.json +1 -1
- package/scripts/install.sh +97 -141
package/package.json
CHANGED
package/scripts/install.sh
CHANGED
|
@@ -2,19 +2,18 @@
|
|
|
2
2
|
#
|
|
3
3
|
# ClaudeDeck Installer
|
|
4
4
|
#
|
|
5
|
-
#
|
|
5
|
+
# Install:
|
|
6
6
|
# curl -fsSL https://raw.githubusercontent.com/ATERCATES/claude-deck/main/scripts/install.sh | bash
|
|
7
7
|
#
|
|
8
|
-
# Options:
|
|
9
|
-
# bash install.sh --port 3011 --ssh-host myserver.com --ssh-port 22 -y
|
|
10
|
-
#
|
|
11
8
|
# Update:
|
|
12
|
-
#
|
|
9
|
+
# ~/.claude-deck/install.sh --update
|
|
10
|
+
#
|
|
11
|
+
# Options:
|
|
12
|
+
# --port 3011 --ssh-host myserver.com --ssh-port 22 -y
|
|
13
13
|
#
|
|
14
14
|
|
|
15
15
|
set -e
|
|
16
16
|
|
|
17
|
-
# Colors
|
|
18
17
|
RED='\033[0;31m'
|
|
19
18
|
GREEN='\033[0;32m'
|
|
20
19
|
BLUE='\033[0;34m'
|
|
@@ -29,29 +28,26 @@ log_warn() { echo -e "${YELLOW}==>${NC} $1"; }
|
|
|
29
28
|
log_error() { echo -e "${RED}==>${NC} $1"; }
|
|
30
29
|
|
|
31
30
|
INSTALL_DIR="$HOME/.claude-deck"
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
PKG="@atercates/claude-deck"
|
|
32
|
+
NODE_MIN=24
|
|
34
33
|
|
|
35
|
-
# ─── Parse
|
|
34
|
+
# ─── Parse flags ──────────────────────────────────────────────────────────────
|
|
36
35
|
|
|
37
|
-
FLAG_PORT=""
|
|
38
|
-
|
|
39
|
-
FLAG_SSH_PORT=""
|
|
40
|
-
FLAG_NONINTERACTIVE=false
|
|
41
|
-
FLAG_UPDATE=false
|
|
36
|
+
FLAG_PORT="" FLAG_SSH_HOST="" FLAG_SSH_PORT=""
|
|
37
|
+
FLAG_NONINTERACTIVE=false FLAG_UPDATE=false
|
|
42
38
|
|
|
43
39
|
while [[ $# -gt 0 ]]; do
|
|
44
40
|
case "$1" in
|
|
45
|
-
--port)
|
|
46
|
-
--ssh-host)
|
|
47
|
-
--ssh-port)
|
|
48
|
-
--yes|-y)
|
|
49
|
-
--update|-u)
|
|
50
|
-
*)
|
|
41
|
+
--port) FLAG_PORT="$2"; shift 2 ;;
|
|
42
|
+
--ssh-host) FLAG_SSH_HOST="$2"; shift 2 ;;
|
|
43
|
+
--ssh-port) FLAG_SSH_PORT="$2"; shift 2 ;;
|
|
44
|
+
--yes|-y) FLAG_NONINTERACTIVE=true; shift ;;
|
|
45
|
+
--update|-u) FLAG_UPDATE=true; shift ;;
|
|
46
|
+
*) shift ;;
|
|
51
47
|
esac
|
|
52
48
|
done
|
|
53
49
|
|
|
54
|
-
# ───
|
|
50
|
+
# ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
55
51
|
|
|
56
52
|
ask() {
|
|
57
53
|
local prompt="$1" default="$2" var="$3"
|
|
@@ -68,59 +64,86 @@ ask() {
|
|
|
68
64
|
fi
|
|
69
65
|
}
|
|
70
66
|
|
|
71
|
-
|
|
67
|
+
ensure_node() {
|
|
68
|
+
# Check PATH first, then ~/.n
|
|
69
|
+
[[ -x "$HOME/.n/bin/node" ]] && export PATH="$HOME/.n/bin:$PATH"
|
|
70
|
+
|
|
71
|
+
if command -v node &> /dev/null; then
|
|
72
|
+
local v=$(node --version | sed 's/v//' | cut -d. -f1)
|
|
73
|
+
if [[ "$v" -ge "$NODE_MIN" ]]; then
|
|
74
|
+
log_success "Node.js $(node --version) found"
|
|
75
|
+
return
|
|
76
|
+
fi
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
log_info "Installing Node.js $NODE_MIN..."
|
|
80
|
+
local N_PREFIX="$HOME/.n"
|
|
81
|
+
mkdir -p "$N_PREFIX"
|
|
82
|
+
curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n -o /tmp/n && chmod +x /tmp/n
|
|
83
|
+
N_PREFIX="$N_PREFIX" /tmp/n "$NODE_MIN" && rm -f /tmp/n
|
|
84
|
+
export PATH="$N_PREFIX/bin:$PATH"
|
|
85
|
+
log_success "Node.js $(node --version) installed"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
ensure_pnpm() {
|
|
89
|
+
if command -v pnpm &> /dev/null; then
|
|
90
|
+
log_success "pnpm $(pnpm --version) found"
|
|
91
|
+
else
|
|
92
|
+
log_info "Installing pnpm..."
|
|
93
|
+
npm install -g pnpm > /dev/null 2>&1
|
|
94
|
+
log_success "pnpm $(pnpm --version) installed"
|
|
95
|
+
fi
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
pkg_dir() {
|
|
99
|
+
echo "$INSTALL_DIR/node_modules/$PKG"
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
pkg_version() {
|
|
103
|
+
node -e "console.log(require('$(pkg_dir)/package.json').version)" 2>/dev/null || echo "unknown"
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
# ─── Update ───────────────────────────────────────────────────────────────────
|
|
72
107
|
|
|
73
108
|
if [[ "$FLAG_UPDATE" == true ]]; then
|
|
74
109
|
echo ""
|
|
75
110
|
echo -e "${BOLD} ClaudeDeck Update${NC}"
|
|
76
111
|
echo ""
|
|
77
112
|
|
|
78
|
-
if [[ ! -d "$INSTALL_DIR" ]]; then
|
|
113
|
+
if [[ ! -d "$INSTALL_DIR/node_modules/$PKG" ]]; then
|
|
79
114
|
log_error "ClaudeDeck is not installed. Run without --update first."
|
|
80
115
|
exit 1
|
|
81
116
|
fi
|
|
82
117
|
|
|
83
|
-
|
|
84
|
-
[[ -x "$HOME/.n/bin/node" ]] && export PATH="$HOME/.n/bin:$PATH"
|
|
85
|
-
|
|
118
|
+
ensure_node
|
|
86
119
|
cd "$INSTALL_DIR"
|
|
87
|
-
CURRENT=$(node -e "console.log(require('./node_modules/$PKG_NAME/package.json').version)" 2>/dev/null || echo "unknown")
|
|
88
|
-
log_info "Current version: $CURRENT"
|
|
89
120
|
|
|
90
|
-
|
|
91
|
-
|
|
121
|
+
CURRENT=$(pkg_version)
|
|
122
|
+
log_info "Current version: $CURRENT"
|
|
92
123
|
|
|
93
|
-
|
|
124
|
+
log_info "Updating..."
|
|
125
|
+
pnpm update "$PKG" --latest 2>&1 | tail -3
|
|
94
126
|
|
|
127
|
+
NEW=$(pkg_version)
|
|
95
128
|
if [[ "$CURRENT" == "$NEW" ]]; then
|
|
96
129
|
log_success "Already on latest version ($NEW)"
|
|
97
130
|
else
|
|
98
131
|
log_success "Updated: $CURRENT -> $NEW"
|
|
99
132
|
fi
|
|
100
133
|
|
|
101
|
-
|
|
102
|
-
log_info "Copying source..."
|
|
103
|
-
rsync -a --delete \
|
|
104
|
-
--exclude='node_modules' --exclude='.next' --exclude='.env' --exclude='*.db' --exclude='*.db-journal' \
|
|
105
|
-
"$INSTALL_DIR/node_modules/$PKG_NAME/" "$INSTALL_DIR/app/"
|
|
106
|
-
|
|
107
|
-
cd "$INSTALL_DIR/app"
|
|
134
|
+
cd "$(pkg_dir)"
|
|
108
135
|
log_info "Installing dependencies..."
|
|
109
136
|
pnpm install > /dev/null 2>&1
|
|
110
137
|
|
|
111
138
|
log_info "Building..."
|
|
139
|
+
rm -f .next/build.lock
|
|
112
140
|
pnpm build 2>&1 | tail -5
|
|
113
141
|
|
|
114
|
-
# Restart service if running
|
|
115
142
|
if systemctl is-active --quiet claudedeck 2>/dev/null; then
|
|
116
143
|
log_info "Restarting service..."
|
|
117
144
|
sudo systemctl restart claudedeck
|
|
118
145
|
sleep 2
|
|
119
|
-
|
|
120
|
-
log_success "ClaudeDeck $NEW running"
|
|
121
|
-
else
|
|
122
|
-
log_error "Service failed to start. Check: sudo journalctl -u claudedeck -f"
|
|
123
|
-
fi
|
|
146
|
+
systemctl is-active --quiet claudedeck && log_success "ClaudeDeck $NEW running" || log_error "Failed. Check: sudo journalctl -u claudedeck -f"
|
|
124
147
|
else
|
|
125
148
|
log_success "ClaudeDeck $NEW ready. Start with: sudo systemctl start claudedeck"
|
|
126
149
|
fi
|
|
@@ -129,15 +152,14 @@ if [[ "$FLAG_UPDATE" == true ]]; then
|
|
|
129
152
|
exit 0
|
|
130
153
|
fi
|
|
131
154
|
|
|
132
|
-
# ───
|
|
155
|
+
# ─── Fresh install ────────────────────────────────────────────────────────────
|
|
133
156
|
|
|
134
157
|
echo ""
|
|
135
158
|
echo -e "${BOLD} ClaudeDeck Installer${NC}"
|
|
136
159
|
echo -e "${DIM} Self-hosted web UI for Claude Code sessions${NC}"
|
|
137
160
|
echo ""
|
|
138
161
|
|
|
139
|
-
#
|
|
140
|
-
|
|
162
|
+
# Prerequisites
|
|
141
163
|
log_info "Checking prerequisites..."
|
|
142
164
|
|
|
143
165
|
if ! command -v tmux &> /dev/null; then
|
|
@@ -152,53 +174,10 @@ if ! command -v tmux &> /dev/null; then
|
|
|
152
174
|
fi
|
|
153
175
|
fi
|
|
154
176
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
install_node() {
|
|
158
|
-
log_info "Installing Node.js $NODE_MIN_VERSION..."
|
|
159
|
-
local N_PREFIX="$HOME/.n"
|
|
160
|
-
mkdir -p "$N_PREFIX"
|
|
161
|
-
curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n -o /tmp/n
|
|
162
|
-
chmod +x /tmp/n
|
|
163
|
-
N_PREFIX="$N_PREFIX" /tmp/n "$NODE_MIN_VERSION"
|
|
164
|
-
rm -f /tmp/n
|
|
165
|
-
export PATH="$N_PREFIX/bin:$PATH"
|
|
166
|
-
log_success "Node.js $(node --version) installed"
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
NODE_OK=false
|
|
170
|
-
if command -v node &> /dev/null; then
|
|
171
|
-
NODE_VERSION=$(node --version | sed 's/v//' | cut -d. -f1)
|
|
172
|
-
if [[ "$NODE_VERSION" -ge "$NODE_MIN_VERSION" ]]; then
|
|
173
|
-
NODE_OK=true
|
|
174
|
-
log_success "Node.js $(node --version) found"
|
|
175
|
-
fi
|
|
176
|
-
fi
|
|
177
|
-
|
|
178
|
-
if [[ "$NODE_OK" == false ]] && [[ -x "$HOME/.n/bin/node" ]]; then
|
|
179
|
-
export PATH="$HOME/.n/bin:$PATH"
|
|
180
|
-
NODE_VERSION=$(node --version | sed 's/v//' | cut -d. -f1)
|
|
181
|
-
if [[ "$NODE_VERSION" -ge "$NODE_MIN_VERSION" ]]; then
|
|
182
|
-
NODE_OK=true
|
|
183
|
-
log_success "Node.js $(node --version) found in ~/.n"
|
|
184
|
-
fi
|
|
185
|
-
fi
|
|
186
|
-
|
|
187
|
-
if [[ "$NODE_OK" == false ]]; then
|
|
188
|
-
install_node
|
|
189
|
-
fi
|
|
190
|
-
|
|
191
|
-
# pnpm
|
|
192
|
-
if ! command -v pnpm &> /dev/null; then
|
|
193
|
-
log_info "Installing pnpm..."
|
|
194
|
-
npm install -g pnpm > /dev/null 2>&1
|
|
195
|
-
log_success "pnpm $(pnpm --version) installed"
|
|
196
|
-
else
|
|
197
|
-
log_success "pnpm $(pnpm --version) found"
|
|
198
|
-
fi
|
|
199
|
-
|
|
200
|
-
# ─── Configuration ────────────────────────────────────────────────────────────
|
|
177
|
+
ensure_node
|
|
178
|
+
ensure_pnpm
|
|
201
179
|
|
|
180
|
+
# Configuration
|
|
202
181
|
echo ""
|
|
203
182
|
log_info "Configuration"
|
|
204
183
|
echo ""
|
|
@@ -209,39 +188,26 @@ SSH_PORT="${FLAG_SSH_PORT}"
|
|
|
209
188
|
|
|
210
189
|
ask "Port" "3011" PORT
|
|
211
190
|
ask "SSH host for VS Code remote button (leave empty to skip)" "" SSH_HOST
|
|
212
|
-
|
|
213
|
-
if [[ -n "$SSH_HOST" ]]; then
|
|
214
|
-
ask "SSH port" "22" SSH_PORT
|
|
215
|
-
fi
|
|
216
|
-
|
|
191
|
+
[[ -n "$SSH_HOST" ]] && ask "SSH port" "22" SSH_PORT
|
|
217
192
|
echo ""
|
|
218
193
|
|
|
219
|
-
#
|
|
220
|
-
|
|
194
|
+
# Install package
|
|
221
195
|
mkdir -p "$INSTALL_DIR"
|
|
222
196
|
cd "$INSTALL_DIR"
|
|
223
197
|
|
|
224
|
-
# Initialize pnpm project if first install
|
|
225
198
|
if [[ ! -f "package.json" ]]; then
|
|
226
199
|
echo '{"name":"claude-deck-instance","private":true}' > package.json
|
|
227
200
|
fi
|
|
228
201
|
|
|
229
|
-
log_info "Installing $
|
|
230
|
-
pnpm add "$
|
|
202
|
+
log_info "Installing $PKG from npm..."
|
|
203
|
+
pnpm add "$PKG" 2>&1 | tail -3
|
|
231
204
|
|
|
232
|
-
#
|
|
233
|
-
|
|
234
|
-
rsync -a --delete \
|
|
235
|
-
--exclude='node_modules' --exclude='.next' --exclude='.env' --exclude='*.db' --exclude='*.db-journal' \
|
|
236
|
-
"$INSTALL_DIR/node_modules/$PKG_NAME/" "$INSTALL_DIR/app/"
|
|
205
|
+
# Build inside the package directory
|
|
206
|
+
cd "$(pkg_dir)"
|
|
237
207
|
|
|
238
|
-
cd "$INSTALL_DIR/app"
|
|
239
|
-
|
|
240
|
-
# Dependencies
|
|
241
208
|
log_info "Installing dependencies..."
|
|
242
209
|
pnpm install > /dev/null 2>&1
|
|
243
210
|
|
|
244
|
-
# Approve native builds if needed
|
|
245
211
|
if ! grep -q "onlyBuiltDependencies" package.json 2>/dev/null; then
|
|
246
212
|
node -e "
|
|
247
213
|
const pkg = require('./package.json');
|
|
@@ -252,18 +218,12 @@ if ! grep -q "onlyBuiltDependencies" package.json 2>/dev/null; then
|
|
|
252
218
|
pnpm install > /dev/null 2>&1
|
|
253
219
|
fi
|
|
254
220
|
|
|
255
|
-
#
|
|
221
|
+
# .env
|
|
256
222
|
log_info "Writing .env..."
|
|
257
|
-
|
|
258
|
-
PORT=$PORT
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if [[ -n "$SSH_HOST" ]]; then
|
|
262
|
-
echo "SSH_HOST=$SSH_HOST" >> "$INSTALL_DIR/app/.env"
|
|
263
|
-
fi
|
|
264
|
-
if [[ -n "$SSH_PORT" ]] && [[ "$SSH_PORT" != "22" ]]; then
|
|
265
|
-
echo "SSH_PORT=$SSH_PORT" >> "$INSTALL_DIR/app/.env"
|
|
266
|
-
fi
|
|
223
|
+
ENV_FILE="$(pkg_dir)/.env"
|
|
224
|
+
echo "PORT=$PORT" > "$ENV_FILE"
|
|
225
|
+
[[ -n "$SSH_HOST" ]] && echo "SSH_HOST=$SSH_HOST" >> "$ENV_FILE"
|
|
226
|
+
[[ -n "$SSH_PORT" && "$SSH_PORT" != "22" ]] && echo "SSH_PORT=$SSH_PORT" >> "$ENV_FILE"
|
|
267
227
|
|
|
268
228
|
# Build
|
|
269
229
|
log_info "Building for production (this may take a minute)..."
|
|
@@ -275,13 +235,16 @@ if [[ ! -f "$HOME/.tmux.conf" ]] || ! grep -q "mouse on" "$HOME/.tmux.conf" 2>/d
|
|
|
275
235
|
echo "set -g mouse on" >> "$HOME/.tmux.conf"
|
|
276
236
|
fi
|
|
277
237
|
|
|
278
|
-
#
|
|
238
|
+
# Copy install script for easy updates
|
|
239
|
+
cp "$(pkg_dir)/scripts/install.sh" "$INSTALL_DIR/install.sh" 2>/dev/null || true
|
|
279
240
|
|
|
241
|
+
# ─── Systemd ──────────────────────────────────────────────────────────────────
|
|
242
|
+
|
|
243
|
+
APP_DIR="$(pkg_dir)"
|
|
280
244
|
NODE_BIN=$(which node)
|
|
281
|
-
TSX_BIN="$
|
|
282
|
-
APP_DIR="$INSTALL_DIR/app"
|
|
245
|
+
TSX_BIN="$APP_DIR/node_modules/.bin/tsx"
|
|
283
246
|
|
|
284
|
-
|
|
247
|
+
SERVICE="[Unit]
|
|
285
248
|
Description=ClaudeDeck
|
|
286
249
|
After=network.target
|
|
287
250
|
|
|
@@ -301,40 +264,33 @@ WantedBy=multi-user.target"
|
|
|
301
264
|
INSTALL_SERVICE=false
|
|
302
265
|
if [[ -t 0 ]] && [[ "$FLAG_NONINTERACTIVE" == false ]]; then
|
|
303
266
|
echo ""
|
|
304
|
-
ask "Install as systemd service? (y/n)" "y"
|
|
305
|
-
[[ "$
|
|
267
|
+
ask "Install as systemd service? (y/n)" "y" SVC_ANSWER
|
|
268
|
+
[[ "$SVC_ANSWER" == "y" ]] && INSTALL_SERVICE=true
|
|
306
269
|
else
|
|
307
270
|
INSTALL_SERVICE=true
|
|
308
271
|
fi
|
|
309
272
|
|
|
310
273
|
if [[ "$INSTALL_SERVICE" == true ]]; then
|
|
311
274
|
log_info "Installing systemd service..."
|
|
312
|
-
echo "$
|
|
275
|
+
echo "$SERVICE" | sudo tee /etc/systemd/system/claudedeck.service > /dev/null
|
|
313
276
|
sudo systemctl daemon-reload
|
|
314
277
|
sudo systemctl enable claudedeck > /dev/null 2>&1
|
|
315
278
|
sudo systemctl restart claudedeck
|
|
316
279
|
sleep 2
|
|
317
|
-
|
|
318
|
-
if systemctl is-active --quiet claudedeck; then
|
|
319
|
-
log_success "Service running on port $PORT"
|
|
320
|
-
else
|
|
321
|
-
log_error "Service failed to start. Check: sudo journalctl -u claudedeck -f"
|
|
322
|
-
fi
|
|
280
|
+
systemctl is-active --quiet claudedeck && log_success "Service running on port $PORT" || log_error "Failed. Check: sudo journalctl -u claudedeck -f"
|
|
323
281
|
fi
|
|
324
282
|
|
|
325
283
|
# ─── Done ─────────────────────────────────────────────────────────────────────
|
|
326
284
|
|
|
327
|
-
VERSION=$(
|
|
285
|
+
VERSION=$(pkg_version)
|
|
328
286
|
|
|
329
287
|
echo ""
|
|
330
288
|
echo -e "${GREEN}${BOLD} ClaudeDeck${VERSION:+ v$VERSION} installed!${NC}"
|
|
331
289
|
echo ""
|
|
332
290
|
echo -e " ${BOLD}Local:${NC} http://localhost:$PORT"
|
|
333
|
-
|
|
334
|
-
echo -e " ${BOLD}Remote:${NC} Configure your reverse proxy to point to port $PORT"
|
|
335
|
-
fi
|
|
291
|
+
[[ -n "$SSH_HOST" ]] && echo -e " ${BOLD}Remote:${NC} Configure your reverse proxy to point to port $PORT"
|
|
336
292
|
echo ""
|
|
337
293
|
echo -e " ${DIM}First visit will prompt you to create an account.${NC}"
|
|
338
294
|
echo -e " ${DIM}Manage: sudo systemctl {start|stop|restart|status} claudedeck${NC}"
|
|
339
|
-
echo -e " ${DIM}Update:
|
|
295
|
+
echo -e " ${DIM}Update: ~/.claude-deck/install.sh --update${NC}"
|
|
340
296
|
echo ""
|