-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathentrypoint.sh
More file actions
126 lines (107 loc) · 4.29 KB
/
Copy pathentrypoint.sh
File metadata and controls
126 lines (107 loc) · 4.29 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
#!/bin/bash
set -e
SOURCE_IMAGE="/usr/local/share/mz5-source"
SOURCE_DATA="/data/source"
CLAUDE_DATA="/data/.claude"
SSH_DATA="/data/.ssh"
# --- Setup symlinks for ALL users that might run Claude Code ---
# The server runs as 'app' but Claude Code runs as root.
setup_user_symlinks() {
local user_home="$1"
local user_name="$2"
echo "entrypoint: setting up symlinks for $user_name (home=$user_home)"
# Claude Code data
if [ -d "$user_home/.claude" ] && [ ! -L "$user_home/.claude" ]; then
echo "entrypoint: merging $user_name ephemeral .claude into persistent volume"
cp -an "$user_home/.claude/." "$CLAUDE_DATA/" 2>/dev/null || true
rm -rf "$user_home/.claude"
fi
ln -sfn "$CLAUDE_DATA" "$user_home/.claude"
# SSH keys
if [ -d "$SSH_DATA" ]; then
if [ -d "$user_home/.ssh" ] && [ ! -L "$user_home/.ssh" ]; then
rm -rf "$user_home/.ssh"
fi
ln -sfn "$SSH_DATA" "$user_home/.ssh"
fi
}
# --- Source code persistence ---
if [ ! -d "$SOURCE_DATA/.git" ]; then
echo "entrypoint: first boot — copying source to persistent volume"
cp -a "$SOURCE_IMAGE" "$SOURCE_DATA"
fi
git config --global --add safe.directory "$SOURCE_DATA"
# --- Ensure persistent dirs exist ---
mkdir -p "$CLAUDE_DATA"
mkdir -p "$SSH_DATA"
# --- Symlinks for root (Claude Code runs as root) ---
setup_user_symlinks "/root" "root"
# --- Symlinks for app user (server runs as app) ---
setup_user_symlinks "/home/app" "app"
# --- Project-level .claude persistence ---
PROJECT_CLAUDE="$SOURCE_DATA/.claude"
CLAUDE_PROJECT_DATA="/data/.claude-project"
if [ ! -d "$CLAUDE_PROJECT_DATA" ]; then
if [ -d "$PROJECT_CLAUDE" ] && [ ! -L "$PROJECT_CLAUDE" ]; then
mv "$PROJECT_CLAUDE" "$CLAUDE_PROJECT_DATA"
else
mkdir -p "$CLAUDE_PROJECT_DATA"
fi
fi
if [ -d "$PROJECT_CLAUDE" ] && [ ! -L "$PROJECT_CLAUDE" ]; then
rm -rf "$PROJECT_CLAUDE"
fi
ln -sfn "$CLAUDE_PROJECT_DATA" "$PROJECT_CLAUDE"
# --- Session helper script ---
# Creates /data/bin/m — a single command to resume or start a tmux+claude session.
# Survives SSH disconnects (tmux) and machine restarts (claude --continue).
mkdir -p /data/bin
cat > /data/bin/m << 'SCRIPT'
#!/bin/bash
SESSION="mind"
WORKDIR="/data/source"
# If already inside the tmux session, just run claude
if [ "$TMUX" ] && [ "$(tmux display-message -p '#S')" = "$SESSION" ]; then
cd "$WORKDIR"
exec claude --continue "$@"
fi
# If tmux session exists, attach to it
if tmux has-session -t "$SESSION" 2>/dev/null; then
echo "Attaching to existing session..."
exec tmux attach -t "$SESSION"
fi
# No session — start a new tmux session with claude --continue
echo "Starting new session (resuming last conversation)..."
exec tmux new-session -s "$SESSION" -c "$WORKDIR" "claude --continue $*; bash"
SCRIPT
chmod +x /data/bin/m
# Add /data/bin to PATH for all users
if ! grep -q '/data/bin' /etc/profile 2>/dev/null; then
echo 'export PATH="/data/bin:$PATH"' >> /etc/profile
fi
echo "entrypoint: source=$SOURCE_DATA, claude=$CLAUDE_DATA, ssh=$SSH_DATA"
# --- Ensure go is in PATH for mind's preflight check ---
ln -sf /usr/local/go/bin/go /usr/local/bin/go 2>/dev/null || true
# --- Build from /data/source if newer than installed binaries ---
# The persistent volume has the latest code; Docker image binaries may be stale.
# Compare latest git commit time against server binary.
if [ -f "$SOURCE_DATA/go.mod" ]; then
LATEST_SRC=$(cd "$SOURCE_DATA" && git log -1 --format=%ct 2>/dev/null || echo 0)
SERVER_MOD=$(stat -c %Y /usr/local/bin/server 2>/dev/null || echo 0)
if [ "$LATEST_SRC" -gt "$SERVER_MOD" ]; then
echo "entrypoint: source is newer than binaries, rebuilding..."
cd "$SOURCE_DATA"
if /usr/local/go/bin/go build -o /usr/local/bin/server ./cmd/server && \
/usr/local/go/bin/go build -o /usr/local/bin/mind ./cmd/mind && \
/usr/local/go/bin/go build -o /usr/local/bin/eg ./cmd/eg; then
echo "entrypoint: rebuild complete"
else
echo "entrypoint: rebuild failed, using Docker image binaries"
fi
fi
fi
# --- Start server (mind runs in-process) ---
# Server and mind share the same process and event bus.
# No separate mind process or watchdog needed.
echo "entrypoint: starting server (mind runs in-process)"
exec "$@"