11#! /bin/bash
2+ # ============================================================
3+ # ComfyUI + Claude Code Setup on Google Colab
4+ # With Google Drive persistence for both ComfyUI and Claude Code
5+ # ============================================================
26
37set -e
48
@@ -10,72 +14,150 @@ checkfolder() {
1014 test -d $@ 2>&1 > /dev/null
1115}
1216
17+ safe_symlink () {
18+ local src=$1
19+ local dst=$2
20+
21+ mkdir -p " $src "
22+
23+ if [ -L " $dst " ]; then
24+ if [ " $( readlink " $dst " ) " = " $src " ]; then
25+ return 0
26+ fi
27+ rm " $dst "
28+ elif [ -e " $dst " ]; then
29+ rm -rf " $dst "
30+ fi
31+
32+ ln -s " $src " " $dst "
33+ }
34+
35+ # ---------- Check CUDA GPU is available ----------
36+ if ! checkinstall nvidia-smi; then
37+ echo " ✗ Error: nvidia-smi not found. No NVIDIA GPU detected." >&2
38+ echo " In Colab: Runtime → Change runtime type → select a GPU (T4/L4/A100)" >&2
39+ exit 1
40+ fi
41+
42+ if ! nvidia-smi > /dev/null 2>&1 ; then
43+ echo " ✗ Error: nvidia-smi failed. GPU not accessible." >&2
44+ echo " In Colab: Runtime → Change runtime type → select a GPU (T4/L4/A100)" >&2
45+ exit 1
46+ fi
47+
48+ GPU_NAME=$( nvidia-smi --query-gpu=name --format=csv,noheader 2> /dev/null | head -1)
49+ echo " ✓ GPU detected: $GPU_NAME " >&2
50+
51+ # ---------- Check Drive is mounted ----------
1352if ! checkfolder /content/drive/MyDrive; then
14- echo " Google Drive not mounted. Please mount Google Drive in the Colab interface." >&2
15- echo " from google.colab import drive" >&2
16- echo " drive.mount('/content/drive')" >&2
53+ echo " ✗ Error: Google Drive not mounted." >&2
54+ echo " Run this in a Python cell first:" >&2
55+ echo " from google.colab import drive" >&2
56+ echo " drive.mount('/content/drive')" >&2
1757 exit 1
1858fi
1959
2060mkdir -p /content
2161
22- # Install ComfyUI
62+ # ---------- Install ComfyUI ----------
2363if ! checkfolder /content/ComfyUI; then
64+ echo " Installing ComfyUI..." >&2
2465 git clone --depth 1 https://github.com/comfyanonymous/ComfyUI.git /content/ComfyUI
2566 git clone --depth 1 https://github.com/ltdrdata/ComfyUI-Manager /content/ComfyUI/custom_nodes/comfyui-manager
2667 cd /content/ComfyUI
27- pip install -r requirements.txt 2>&1 > /dev/null
68+ pip install -r requirements.txt --no-deps 2>&1 > /dev/null
69+ pip install -r custom_nodes/comfyui-manager/requirements.txt 2>&1 > /dev/null
70+ fi
71+
72+ # ---------- Verify PyTorch CUDA works ----------
73+ if ! python -c " import torch; assert torch.cuda.is_available()" 2> /dev/null; then
74+ echo " ✗ Error: PyTorch cannot access CUDA." >&2
75+ PYTORCH_VERSION=$( python -c " import torch; print(torch.__version__)" 2> /dev/null || echo " unknown" )
76+ echo " PyTorch version: $PYTORCH_VERSION " >&2
77+ echo " Likely cause: torch got downgraded to CPU-only version during pip install." >&2
78+ echo " Fix:" >&2
79+ echo " pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121" >&2
80+ exit 1
2881fi
82+ echo " ✓ PyTorch CUDA verified" >&2
2983
30- # Install Cloudflared
84+ # ---------- Install Cloudflared ----------
3185if ! checkinstall cloudflared; then
3286 rm -f /tmp/cloudflared.deb
3387 wget -q -O /tmp/cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb 2>&1 > /dev/null
3488 DEBIAN_FRONTEND=noninteractive apt-get install -qq -y /tmp/cloudflared.deb 2>&1 > /dev/null
3589 rm -f /tmp/cloudflared.deb
3690fi
3791
38- # Install Claude Code
92+ # ---------- Install Claude Code ----------
3993if ! checkinstall claude; then
4094 npm i -g @anthropic-ai/claude-code 2>&1 > /dev/null
4195fi
4296
43- # Install PM2
97+ # ---------- Install PM2 ----------
4498if ! checkinstall pm2; then
4599 npm i -g pm2 2>&1 > /dev/null
46100fi
47101
102+ # ---------- Drive persistence setup ----------
48103USERDATA_DIR=/content/drive/MyDrive/ComfyUI
49104mkdir -p $USERDATA_DIR
50105cd $USERDATA_DIR
51106
52- mkdir -p $USERDATA_DIR /claude
53- ln -sf $USERDATA_DIR /claude ~ /.claude
54-
55- mkdir -p $USERDATA_DIR /user
56- rm -rf /content/ComfyUI/user
57- ln -sf $USERDATA_DIR /user /content/ComfyUI/user
58-
59- mkdir -p $USERDATA_DIR /input
60- rm -rf /content/ComfyUI/input
61- ln -sf $USERDATA_DIR /input /content/ComfyUI/input
62-
63- mkdir -p $USERDATA_DIR /output
64- rm -rf /content/ComfyUI/output
65- ln -sf $USERDATA_DIR /output /content/ComfyUI/output
66-
67- mkdir -p $USERDATA_DIR /workflows
68- rm -rf /content/ComfyUI/workflows
69- ln -sf $USERDATA_DIR /workflows /content/ComfyUI/workflows
70-
71- mkdir -p $USERDATA_DIR /models
72- rm -rf /content/ComfyUI/models
73- ln -sf $USERDATA_DIR /models /content/ComfyUI/models
74-
107+ # Claude Code: ~/.claude/ directory (credentials, projects, todos)
108+ # Migrate pre-existing local dir into Drive on first run
109+ if [ -d " $HOME /.claude" ] && [ ! -L " $HOME /.claude" ]; then
110+ if [ -z " $( ls -A $USERDATA_DIR /claude 2> /dev/null) " ]; then
111+ mv $HOME /.claude/* $USERDATA_DIR /claude/ 2> /dev/null || true
112+ mv $HOME /.claude/.* $USERDATA_DIR /claude/ 2> /dev/null || true
113+ fi
114+ rm -rf $HOME /.claude
115+ fi
116+ safe_symlink $USERDATA_DIR /claude $HOME /.claude
117+
118+ # Claude Code: ~/.claude.json file (MCP servers, project trust, onboarding state)
119+ # Migrate pre-existing local file into Drive on first run
120+ if [ -f " $HOME /.claude.json" ] && [ ! -L " $HOME /.claude.json" ]; then
121+ if [ ! -f " $USERDATA_DIR /claude.json" ]; then
122+ mv " $HOME /.claude.json" " $USERDATA_DIR /claude.json"
123+ else
124+ rm -f " $HOME /.claude.json"
125+ fi
126+ fi
127+ touch " $USERDATA_DIR /claude.json"
128+ ln -sf " $USERDATA_DIR /claude.json" " $HOME /.claude.json"
129+
130+ # ComfyUI user data (settings, saved workflows live under user/default/workflows)
131+ safe_symlink $USERDATA_DIR /user /content/ComfyUI/user
132+
133+ # ComfyUI input/output folders
134+ safe_symlink $USERDATA_DIR /input /content/ComfyUI/input
135+ safe_symlink $USERDATA_DIR /output /content/ComfyUI/output
136+
137+ # Models: use extra_model_paths.yaml instead of full symlink
138+ mkdir -p $USERDATA_DIR /models/{checkpoints,loras,vae,clip,controlnet,upscale_models,embeddings}
139+
140+ cat > /content/ComfyUI/extra_model_paths.yaml << EOF
141+ drive:
142+ base_path: $USERDATA_DIR /models
143+ checkpoints: checkpoints/
144+ loras: loras/
145+ vae: vae/
146+ clip: clip/
147+ controlnet: controlnet/
148+ upscale_models: upscale_models/
149+ embeddings: embeddings/
150+ EOF
151+
152+ # ---------- Start ComfyUI ----------
75153cd /content/ComfyUI
76154pm2 delete comfyui > /dev/null 2>&1 || true
77155
78- pm2 start " python main.py --port 8188 --listen 0.0.0.0" --name comfyui --cwd /content/ComfyUI > /dev/null 2>&1
156+ pm2 start " python main.py --port 8188 --listen 0.0.0.0" \
157+ --name comfyui \
158+ --cwd /content/ComfyUI \
159+ > /dev/null 2>&1
160+
79161echo " - Waiting for ComfyUI to start..." >&2
80162COMFYUI_STARTED=false
81163for i in {1..60}; do
@@ -94,9 +176,34 @@ if [ "$COMFYUI_STARTED" = false ]; then
94176 exit 1
95177fi
96178
179+ # ---------- Summary ----------
97180echo " " >&2
98181echo " ========================= ComfyUI =========================" >&2
99182echo " ComfyUI is running at http://localhost:8188" >&2
100183echo " " >&2
101- echo " Run 'pm2 list' to list the processes." >&2
102- echo " Run 'pm2 logs comfyui --lines 1000' to see the ComfyUI logs." >&2
184+ echo " To access from Colab, run in a Python cell:" >&2
185+ echo " from google.colab import output" >&2
186+ echo " output.serve_kernel_port_as_iframe(8188, height=1200)" >&2
187+ echo " " >&2
188+ echo " Drive persistence:" >&2
189+ echo " $USERDATA_DIR /claude/ — Claude Code credentials, history" >&2
190+ echo " $USERDATA_DIR /claude.json — Claude Code MCP & settings" >&2
191+ echo " $USERDATA_DIR /user/ — ComfyUI settings & workflows" >&2
192+ echo " $USERDATA_DIR /input/ — Input images" >&2
193+ echo " $USERDATA_DIR /output/ — Generated images" >&2
194+ echo " $USERDATA_DIR /models/ — Checkpoints, LoRAs, VAE, etc" >&2
195+ echo " " >&2
196+ echo " ========================= Claude Code =========================" >&2
197+ if [ -f " $HOME /.claude/.credentials.json" ]; then
198+ echo " ✓ Already logged in (restored from Drive)" >&2
199+ echo " Run: claude" >&2
200+ else
201+ echo " 🔑 First-time setup — log in once:" >&2
202+ echo " claude login" >&2
203+ echo " After login, all future Colab runners will auto-restore the session." >&2
204+ fi
205+ echo " " >&2
206+ echo " Process management:" >&2
207+ echo " pm2 list — List processes" >&2
208+ echo " pm2 logs comfyui --lines 100 — ComfyUI logs" >&2
209+ echo " pm2 restart comfyui — Restart ComfyUI" >&2
0 commit comments