@atercates/claude-deck 0.2.1
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/LICENSE +21 -0
- package/README.md +123 -0
- package/app/api/claude/hidden/route.ts +66 -0
- package/app/api/claude/projects/[name]/sessions/route.ts +71 -0
- package/app/api/claude/projects/route.ts +44 -0
- package/app/api/code-search/available/route.ts +12 -0
- package/app/api/code-search/route.ts +47 -0
- package/app/api/dev-servers/[id]/logs/route.ts +23 -0
- package/app/api/dev-servers/[id]/restart/route.ts +20 -0
- package/app/api/dev-servers/[id]/route.ts +51 -0
- package/app/api/dev-servers/[id]/stop/route.ts +20 -0
- package/app/api/dev-servers/detect/route.ts +39 -0
- package/app/api/dev-servers/route.ts +48 -0
- package/app/api/exec/route.ts +60 -0
- package/app/api/files/content/route.ts +76 -0
- package/app/api/files/route.ts +37 -0
- package/app/api/files/upload-temp/route.ts +41 -0
- package/app/api/git/check/route.ts +54 -0
- package/app/api/git/clone/route.ts +99 -0
- package/app/api/git/commit/route.ts +75 -0
- package/app/api/git/discard/route.ts +38 -0
- package/app/api/git/file-content/route.ts +64 -0
- package/app/api/git/history/[hash]/diff/route.ts +38 -0
- package/app/api/git/history/[hash]/route.ts +34 -0
- package/app/api/git/history/route.ts +27 -0
- package/app/api/git/multi-status/route.ts +46 -0
- package/app/api/git/pr/route.ts +164 -0
- package/app/api/git/push/route.ts +64 -0
- package/app/api/git/stage/route.ts +40 -0
- package/app/api/git/status/route.ts +51 -0
- package/app/api/git/unstage/route.ts +46 -0
- package/app/api/groups/[...path]/route.ts +136 -0
- package/app/api/groups/route.ts +93 -0
- package/app/api/orchestrate/spawn/route.ts +45 -0
- package/app/api/orchestrate/workers/[id]/route.ts +89 -0
- package/app/api/orchestrate/workers/route.ts +31 -0
- package/app/api/projects/[id]/detect/route.ts +27 -0
- package/app/api/projects/[id]/dev-servers/[dsId]/route.ts +66 -0
- package/app/api/projects/[id]/dev-servers/route.ts +51 -0
- package/app/api/projects/[id]/repositories/[repoId]/route.ts +67 -0
- package/app/api/projects/[id]/repositories/route.ts +74 -0
- package/app/api/projects/[id]/route.ts +108 -0
- package/app/api/projects/detect/route.ts +33 -0
- package/app/api/projects/route.ts +59 -0
- package/app/api/sessions/[id]/claude-session/route.ts +42 -0
- package/app/api/sessions/[id]/fork/route.ts +74 -0
- package/app/api/sessions/[id]/mcp-config/route.ts +34 -0
- package/app/api/sessions/[id]/messages/route.ts +60 -0
- package/app/api/sessions/[id]/pr/route.ts +188 -0
- package/app/api/sessions/[id]/preview/route.ts +42 -0
- package/app/api/sessions/[id]/route.ts +229 -0
- package/app/api/sessions/[id]/send-keys/route.ts +119 -0
- package/app/api/sessions/[id]/summarize/route.ts +331 -0
- package/app/api/sessions/init-script/route.ts +84 -0
- package/app/api/sessions/route.ts +209 -0
- package/app/api/sessions/status/route.ts +237 -0
- package/app/api/system/route.ts +9 -0
- package/app/api/tmux/kill-all/route.ts +57 -0
- package/app/api/tmux/rename/route.ts +30 -0
- package/app/globals.css +174 -0
- package/app/icon.svg +11 -0
- package/app/layout.tsx +122 -0
- package/app/page.tsx +629 -0
- package/components/ChatMessage.tsx +65 -0
- package/components/ChatView.tsx +276 -0
- package/components/ClaudeProjects/ClaudeProjectCard.tsx +195 -0
- package/components/ClaudeProjects/ClaudeProjectsSection.tsx +89 -0
- package/components/ClaudeProjects/ClaudeSessionCard.tsx +100 -0
- package/components/ClaudeProjects/index.ts +1 -0
- package/components/CodeSearch/CodeSearchResults.tsx +177 -0
- package/components/ConductorPanel.tsx +256 -0
- package/components/DevServers/DevServerCard.tsx +311 -0
- package/components/DevServers/DevServersSection.tsx +91 -0
- package/components/DevServers/ServerLogsModal.tsx +151 -0
- package/components/DevServers/StartServerDialog.tsx +359 -0
- package/components/DevServers/index.ts +4 -0
- package/components/DiffViewer/DiffModal.tsx +151 -0
- package/components/DiffViewer/UnifiedDiff.tsx +185 -0
- package/components/DiffViewer/index.tsx +2 -0
- package/components/DirectoryPicker.tsx +355 -0
- package/components/FileExplorer/FileEditor.tsx +276 -0
- package/components/FileExplorer/FileTabs.tsx +118 -0
- package/components/FileExplorer/FileTree.tsx +214 -0
- package/components/FileExplorer/HtmlRenderer.tsx +16 -0
- package/components/FileExplorer/MarkdownRenderer.tsx +18 -0
- package/components/FileExplorer/index.tsx +520 -0
- package/components/FilePicker.tsx +339 -0
- package/components/FolderPicker.tsx +201 -0
- package/components/GitDrawer/FileEditDialog.tsx +400 -0
- package/components/GitDrawer/index.tsx +464 -0
- package/components/GitPanel/CommitForm.tsx +205 -0
- package/components/GitPanel/CommitHistory.tsx +174 -0
- package/components/GitPanel/CommitItem.tsx +196 -0
- package/components/GitPanel/FileChanges.tsx +414 -0
- package/components/GitPanel/GitPanelTabs.tsx +39 -0
- package/components/GitPanel/index.tsx +817 -0
- package/components/MessageInput.tsx +82 -0
- package/components/NewClaudeSessionDialog.tsx +166 -0
- package/components/NewSessionDialog/AdvancedSettings.tsx +78 -0
- package/components/NewSessionDialog/AgentSelector.tsx +37 -0
- package/components/NewSessionDialog/CreatingOverlay.tsx +94 -0
- package/components/NewSessionDialog/NewSessionDialog.types.ts +136 -0
- package/components/NewSessionDialog/ProjectSelector.tsx +146 -0
- package/components/NewSessionDialog/WorkingDirectoryInput.tsx +55 -0
- package/components/NewSessionDialog/WorktreeSection.tsx +92 -0
- package/components/NewSessionDialog/hooks/useNewSessionForm.ts +370 -0
- package/components/NewSessionDialog/index.tsx +106 -0
- package/components/NotificationSettings.tsx +127 -0
- package/components/PRCreationModal.tsx +272 -0
- package/components/Pane/DesktopTabBar.tsx +353 -0
- package/components/Pane/MobileTabBar.tsx +210 -0
- package/components/Pane/OpenInVSCode.tsx +69 -0
- package/components/Pane/PaneSkeletons.tsx +57 -0
- package/components/Pane/index.tsx +558 -0
- package/components/PaneLayout.tsx +60 -0
- package/components/Projects/DevServersSection.tsx +140 -0
- package/components/Projects/DirectoryField.tsx +92 -0
- package/components/Projects/NewProjectDialog.tsx +188 -0
- package/components/Projects/NewProjectDialog.types.ts +46 -0
- package/components/Projects/ProjectCard.tsx +276 -0
- package/components/Projects/ProjectSettingsDialog.tsx +811 -0
- package/components/Projects/hooks/useNewProjectForm.ts +249 -0
- package/components/Projects/index.ts +3 -0
- package/components/Providers.tsx +49 -0
- package/components/QuickSwitcher.tsx +306 -0
- package/components/SessionList/KillAllConfirm.tsx +46 -0
- package/components/SessionList/SelectionToolbar.tsx +164 -0
- package/components/SessionList/SessionList.types.ts +37 -0
- package/components/SessionList/SessionListHeader.tsx +71 -0
- package/components/SessionList/hooks/useSessionListMutations.ts +269 -0
- package/components/SessionList/index.tsx +189 -0
- package/components/ShellDrawer/index.tsx +106 -0
- package/components/SidebarFooter.tsx +55 -0
- package/components/Terminal/KeybarToggleButton.tsx +45 -0
- package/components/Terminal/ScrollToBottomButton.tsx +32 -0
- package/components/Terminal/SearchBar.tsx +71 -0
- package/components/Terminal/TerminalToolbar.tsx +551 -0
- package/components/Terminal/VirtualKeyboard.tsx +711 -0
- package/components/Terminal/constants.ts +20 -0
- package/components/Terminal/hooks/index.ts +5 -0
- package/components/Terminal/hooks/resize-handlers.ts +140 -0
- package/components/Terminal/hooks/terminal-init.ts +151 -0
- package/components/Terminal/hooks/touch-scroll.ts +155 -0
- package/components/Terminal/hooks/useTerminalConnection.ts +282 -0
- package/components/Terminal/hooks/useTerminalConnection.types.ts +39 -0
- package/components/Terminal/hooks/useTerminalSearch.ts +103 -0
- package/components/Terminal/hooks/websocket-connection.ts +274 -0
- package/components/Terminal/index.tsx +320 -0
- package/components/ThemeToggle.tsx +168 -0
- package/components/TmuxSessions.tsx +132 -0
- package/components/ToolCallDisplay.tsx +71 -0
- package/components/WorkerCard.tsx +245 -0
- package/components/a/ABadge.tsx +115 -0
- package/components/a/AButton.tsx +163 -0
- package/components/a/ADialog.tsx +93 -0
- package/components/a/ADropdownMenu.tsx +279 -0
- package/components/a/AIconButton.tsx +190 -0
- package/components/a/ASheet.tsx +150 -0
- package/components/a/ATooltip.tsx +77 -0
- package/components/a/index.ts +64 -0
- package/components/mobile/SwipeSidebar.tsx +122 -0
- package/components/ui/badge.tsx +41 -0
- package/components/ui/button.tsx +60 -0
- package/components/ui/context-menu.tsx +197 -0
- package/components/ui/dialog.tsx +143 -0
- package/components/ui/dropdown-menu.tsx +257 -0
- package/components/ui/input.tsx +21 -0
- package/components/ui/scroll-area.tsx +52 -0
- package/components/ui/select.tsx +159 -0
- package/components/ui/skeleton.tsx +111 -0
- package/components/ui/switch.tsx +31 -0
- package/components/ui/textarea.tsx +21 -0
- package/components/ui/tooltip.tsx +32 -0
- package/components/views/DesktopView.tsx +244 -0
- package/components/views/MobileView.tsx +110 -0
- package/components/views/types.ts +75 -0
- package/contexts/PaneContext.tsx +336 -0
- package/data/claude/index.ts +9 -0
- package/data/claude/keys.ts +6 -0
- package/data/claude/queries.ts +120 -0
- package/data/claude/useClaudeUpdates.ts +37 -0
- package/data/code-search/index.ts +2 -0
- package/data/code-search/keys.ts +7 -0
- package/data/code-search/queries.ts +61 -0
- package/data/dev-servers/index.ts +8 -0
- package/data/dev-servers/keys.ts +4 -0
- package/data/dev-servers/queries.ts +104 -0
- package/data/files/index.ts +3 -0
- package/data/files/keys.ts +4 -0
- package/data/files/queries.ts +25 -0
- package/data/git/keys.ts +15 -0
- package/data/git/queries.ts +395 -0
- package/data/groups/index.ts +1 -0
- package/data/groups/mutations.ts +95 -0
- package/data/projects/index.ts +10 -0
- package/data/projects/keys.ts +4 -0
- package/data/projects/queries.ts +193 -0
- package/data/repositories/index.ts +7 -0
- package/data/repositories/keys.ts +5 -0
- package/data/repositories/queries.ts +122 -0
- package/data/sessions/index.ts +12 -0
- package/data/sessions/keys.ts +8 -0
- package/data/sessions/queries.ts +218 -0
- package/data/statuses/index.ts +1 -0
- package/data/statuses/queries.ts +69 -0
- package/hooks/useCopyToClipboard.ts +48 -0
- package/hooks/useDevServersManager.ts +73 -0
- package/hooks/useDirectoryBrowser.ts +90 -0
- package/hooks/useDrawerAnimation.ts +27 -0
- package/hooks/useFileDrop.ts +87 -0
- package/hooks/useFileEditor.ts +184 -0
- package/hooks/useGroups.ts +37 -0
- package/hooks/useHomePath.ts +34 -0
- package/hooks/useKeyRepeat.ts +55 -0
- package/hooks/useKeybarVisibility.ts +42 -0
- package/hooks/useNotifications.ts +257 -0
- package/hooks/useProjects.ts +53 -0
- package/hooks/useSessionStatuses.ts +30 -0
- package/hooks/useSessions.ts +86 -0
- package/hooks/useSpeechRecognition.ts +124 -0
- package/hooks/useViewport.ts +32 -0
- package/hooks/useViewportHeight.ts +50 -0
- package/lib/async-operations.ts +35 -0
- package/lib/banner.ts +81 -0
- package/lib/claude/jsonl-cache.ts +86 -0
- package/lib/claude/jsonl-reader.ts +271 -0
- package/lib/claude/process-manager.ts +278 -0
- package/lib/claude/stream-parser.ts +173 -0
- package/lib/claude/types.ts +154 -0
- package/lib/claude/watcher.ts +71 -0
- package/lib/client/session-registry.ts +111 -0
- package/lib/code-search.ts +121 -0
- package/lib/db/index.ts +48 -0
- package/lib/db/migrations.ts +45 -0
- package/lib/db/queries.ts +460 -0
- package/lib/db/schema.ts +114 -0
- package/lib/db/types.ts +92 -0
- package/lib/db.ts +2 -0
- package/lib/dev-servers.ts +509 -0
- package/lib/diff-parser.ts +221 -0
- package/lib/env-setup.ts +285 -0
- package/lib/file-upload.ts +34 -0
- package/lib/file-utils.ts +50 -0
- package/lib/files.ts +207 -0
- package/lib/git-history.ts +294 -0
- package/lib/git-status.ts +391 -0
- package/lib/git.ts +257 -0
- package/lib/mcp-config.ts +81 -0
- package/lib/multi-repo-git.ts +179 -0
- package/lib/notifications.ts +219 -0
- package/lib/orchestration.ts +448 -0
- package/lib/panes.ts +232 -0
- package/lib/ports.ts +97 -0
- package/lib/pr-generation.ts +307 -0
- package/lib/pr.ts +234 -0
- package/lib/projects.ts +578 -0
- package/lib/providers/registry.ts +70 -0
- package/lib/providers.ts +121 -0
- package/lib/query-client.ts +14 -0
- package/lib/rangeSelectionUtils.ts +65 -0
- package/lib/status-detector.ts +375 -0
- package/lib/terminal-themes.ts +265 -0
- package/lib/theme-config.ts +327 -0
- package/lib/utils.ts +6 -0
- package/lib/worktrees.ts +262 -0
- package/mcp/orchestration-server.ts +438 -0
- package/package.json +139 -0
- package/postcss.config.mjs +7 -0
- package/public/icon.svg +10 -0
- package/public/icons/icon-128x128.png +0 -0
- package/public/icons/icon-144x144.png +0 -0
- package/public/icons/icon-152x152.png +0 -0
- package/public/icons/icon-192x192.png +0 -0
- package/public/icons/icon-384x384.png +0 -0
- package/public/icons/icon-512x512.png +0 -0
- package/public/icons/icon-72x72.png +0 -0
- package/public/icons/icon-96x96.png +0 -0
- package/public/manifest.json +61 -0
- package/public/sw.js +64 -0
- package/scripts/agent-os +91 -0
- package/scripts/install.sh +48 -0
- package/scripts/lib/ai-clis.sh +132 -0
- package/scripts/lib/commands.sh +487 -0
- package/scripts/lib/common.sh +89 -0
- package/scripts/lib/prerequisites.sh +462 -0
- package/scripts/setup.sh +134 -0
- package/server.ts +155 -0
- package/stores/fileOpen.ts +26 -0
- package/stores/index.ts +1 -0
- package/stores/initialPrompt.ts +24 -0
- package/stores/sessionSelection.ts +48 -0
- package/styles/themes.css +603 -0
- package/tsconfig.json +33 -0
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Command implementations for claude-deck
|
|
3
|
+
|
|
4
|
+
cmd_install() {
|
|
5
|
+
local use_local=false
|
|
6
|
+
[[ "${1:-}" == "--local" ]] && use_local=true
|
|
7
|
+
|
|
8
|
+
log_info "Installing ClaudeDeck..."
|
|
9
|
+
echo ""
|
|
10
|
+
|
|
11
|
+
# Check and install prerequisites
|
|
12
|
+
check_and_install_prerequisites
|
|
13
|
+
|
|
14
|
+
# Prompt for AI CLI installation
|
|
15
|
+
prompt_ai_cli_install
|
|
16
|
+
|
|
17
|
+
# Create directory structure
|
|
18
|
+
mkdir -p "$AGENT_OS_HOME"
|
|
19
|
+
|
|
20
|
+
# Clone, copy local, or update repo
|
|
21
|
+
if [[ -d "$REPO_DIR" ]]; then
|
|
22
|
+
if [[ "$use_local" == true ]]; then
|
|
23
|
+
log_info "Updating from local source..."
|
|
24
|
+
rsync -a --delete --exclude='.git' --exclude='node_modules' --exclude='.next' --exclude='*.db*' "$LOCAL_REPO/" "$REPO_DIR/"
|
|
25
|
+
else
|
|
26
|
+
log_info "Repository already exists, pulling latest..."
|
|
27
|
+
cd "$REPO_DIR"
|
|
28
|
+
git pull --ff-only
|
|
29
|
+
fi
|
|
30
|
+
cd "$REPO_DIR"
|
|
31
|
+
else
|
|
32
|
+
if [[ "$use_local" == true ]]; then
|
|
33
|
+
log_info "Copying from local source..."
|
|
34
|
+
rsync -a --exclude='.git' --exclude='node_modules' --exclude='.next' --exclude='*.db*' "$LOCAL_REPO/" "$REPO_DIR/"
|
|
35
|
+
cd "$REPO_DIR"
|
|
36
|
+
git init
|
|
37
|
+
else
|
|
38
|
+
log_info "Cloning repository..."
|
|
39
|
+
git clone "$REPO_URL" "$REPO_DIR"
|
|
40
|
+
cd "$REPO_DIR"
|
|
41
|
+
fi
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Install dependencies
|
|
45
|
+
log_info "Installing dependencies..."
|
|
46
|
+
npm install --legacy-peer-deps
|
|
47
|
+
|
|
48
|
+
# Build for production
|
|
49
|
+
log_info "Building for production..."
|
|
50
|
+
npm run build
|
|
51
|
+
|
|
52
|
+
# Create CLI symlink (prefer ~/.local/bin to avoid sudo)
|
|
53
|
+
log_info "Adding claude-deck to PATH..."
|
|
54
|
+
local bin_dir="$HOME/.local/bin"
|
|
55
|
+
local needs_path_update=false
|
|
56
|
+
|
|
57
|
+
mkdir -p "$bin_dir"
|
|
58
|
+
ln -sf "$REPO_DIR/scripts/claude-deck" "$bin_dir/claude-deck"
|
|
59
|
+
|
|
60
|
+
# Check if ~/.local/bin is in PATH
|
|
61
|
+
if [[ ":$PATH:" != *":$bin_dir:"* ]]; then
|
|
62
|
+
needs_path_update=true
|
|
63
|
+
# Add to shell profile
|
|
64
|
+
local shell_profile=""
|
|
65
|
+
if [[ -f "$HOME/.zshrc" ]]; then
|
|
66
|
+
shell_profile="$HOME/.zshrc"
|
|
67
|
+
elif [[ -f "$HOME/.bashrc" ]]; then
|
|
68
|
+
shell_profile="$HOME/.bashrc"
|
|
69
|
+
elif [[ -f "$HOME/.bash_profile" ]]; then
|
|
70
|
+
shell_profile="$HOME/.bash_profile"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
if [[ -n "$shell_profile" ]]; then
|
|
74
|
+
if ! grep -q 'export PATH="$HOME/.local/bin:$PATH"' "$shell_profile" 2>/dev/null; then
|
|
75
|
+
echo '' >> "$shell_profile"
|
|
76
|
+
echo '# Added by ClaudeDeck' >> "$shell_profile"
|
|
77
|
+
echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$shell_profile"
|
|
78
|
+
fi
|
|
79
|
+
fi
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
echo ""
|
|
83
|
+
log_success "ClaudeDeck installed successfully!"
|
|
84
|
+
echo ""
|
|
85
|
+
|
|
86
|
+
if [[ "$needs_path_update" == true ]]; then
|
|
87
|
+
echo "Note: ~/.local/bin was added to your PATH."
|
|
88
|
+
echo "Run 'source ~/.zshrc' or restart your terminal, then:"
|
|
89
|
+
echo ""
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
echo "Next steps:"
|
|
93
|
+
echo " claude-deck start Start the server"
|
|
94
|
+
echo " claude-deck enable Auto-start on boot"
|
|
95
|
+
echo " claude-deck status Show URLs"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
cmd_start() {
|
|
99
|
+
if is_running; then
|
|
100
|
+
local pid
|
|
101
|
+
pid=$(get_pid)
|
|
102
|
+
log_warn "ClaudeDeck is already running (PID: $pid)"
|
|
103
|
+
return 0
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
if [[ ! -d "$REPO_DIR" ]]; then
|
|
107
|
+
log_error "ClaudeDeck is not installed. Run 'claude-deck install' first."
|
|
108
|
+
exit 1
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
log_info "Starting ClaudeDeck..."
|
|
112
|
+
|
|
113
|
+
cd "$REPO_DIR"
|
|
114
|
+
|
|
115
|
+
# Rotate log if too big (> 10MB)
|
|
116
|
+
if [[ -f "$LOG_FILE" ]]; then
|
|
117
|
+
local size
|
|
118
|
+
size=$(stat -f%z "$LOG_FILE" 2>/dev/null || stat -c%s "$LOG_FILE" 2>/dev/null || echo 0)
|
|
119
|
+
if [[ "$size" -gt 10485760 ]]; then
|
|
120
|
+
mv "$LOG_FILE" "$LOG_FILE.old"
|
|
121
|
+
fi
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Start server in background
|
|
125
|
+
nohup npm start >> "$LOG_FILE" 2>&1 &
|
|
126
|
+
local pid=$!
|
|
127
|
+
echo "$pid" > "$PID_FILE"
|
|
128
|
+
|
|
129
|
+
# Wait and verify
|
|
130
|
+
sleep 2
|
|
131
|
+
if ! ps -p "$pid" &> /dev/null; then
|
|
132
|
+
log_error "Failed to start ClaudeDeck. Check logs: claude-deck logs"
|
|
133
|
+
rm -f "$PID_FILE"
|
|
134
|
+
exit 1
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
log_success "ClaudeDeck started (PID: $pid)"
|
|
138
|
+
echo ""
|
|
139
|
+
echo " Local: http://localhost:$PORT"
|
|
140
|
+
|
|
141
|
+
local ts_ip
|
|
142
|
+
ts_ip=$(get_tailscale_ip)
|
|
143
|
+
if [[ -n "$ts_ip" ]]; then
|
|
144
|
+
echo " Tailscale: http://$ts_ip:$PORT"
|
|
145
|
+
fi
|
|
146
|
+
echo ""
|
|
147
|
+
echo "Run 'claude-deck logs' to view logs"
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
cmd_stop() {
|
|
151
|
+
if ! is_running; then
|
|
152
|
+
log_warn "ClaudeDeck is not running"
|
|
153
|
+
return 0
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
local pid
|
|
157
|
+
pid=$(get_pid)
|
|
158
|
+
log_info "Stopping ClaudeDeck (PID: $pid)..."
|
|
159
|
+
|
|
160
|
+
kill "$pid" 2>/dev/null || true
|
|
161
|
+
|
|
162
|
+
# Wait for graceful shutdown with progress
|
|
163
|
+
local count=0
|
|
164
|
+
printf " Waiting for shutdown"
|
|
165
|
+
while ps -p "$pid" &> /dev/null && [[ $count -lt 10 ]]; do
|
|
166
|
+
printf "."
|
|
167
|
+
sleep 1
|
|
168
|
+
((count++))
|
|
169
|
+
done
|
|
170
|
+
echo ""
|
|
171
|
+
|
|
172
|
+
# Force kill if still running
|
|
173
|
+
if ps -p "$pid" &> /dev/null; then
|
|
174
|
+
log_warn "Force killing..."
|
|
175
|
+
kill -9 "$pid" 2>/dev/null || true
|
|
176
|
+
sleep 1
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
rm -f "$PID_FILE"
|
|
180
|
+
log_success "ClaudeDeck stopped"
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
cmd_restart() {
|
|
184
|
+
cmd_stop
|
|
185
|
+
sleep 1
|
|
186
|
+
cmd_start
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
cmd_run() {
|
|
190
|
+
# Start if not running
|
|
191
|
+
if ! is_running; then
|
|
192
|
+
cmd_start
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# Wait a moment for server to be ready
|
|
196
|
+
sleep 1
|
|
197
|
+
|
|
198
|
+
local url="http://localhost:$PORT"
|
|
199
|
+
log_info "Opening $url..."
|
|
200
|
+
|
|
201
|
+
# Open in browser
|
|
202
|
+
if [[ "$OS" == "macos" ]]; then
|
|
203
|
+
open "$url"
|
|
204
|
+
elif command -v xdg-open &> /dev/null; then
|
|
205
|
+
xdg-open "$url"
|
|
206
|
+
elif command -v wslview &> /dev/null; then
|
|
207
|
+
wslview "$url"
|
|
208
|
+
else
|
|
209
|
+
log_warn "Could not detect browser. Open manually: $url"
|
|
210
|
+
fi
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
cmd_status() {
|
|
214
|
+
echo ""
|
|
215
|
+
if is_running; then
|
|
216
|
+
local pid
|
|
217
|
+
pid=$(get_pid)
|
|
218
|
+
echo -e " Status: ${GREEN}Running${NC} (PID: $pid)"
|
|
219
|
+
echo " Port: $PORT"
|
|
220
|
+
echo " Local: http://localhost:$PORT"
|
|
221
|
+
|
|
222
|
+
local ts_ip
|
|
223
|
+
ts_ip=$(get_tailscale_ip)
|
|
224
|
+
if [[ -n "$ts_ip" ]]; then
|
|
225
|
+
echo " Tailscale: http://$ts_ip:$PORT"
|
|
226
|
+
fi
|
|
227
|
+
|
|
228
|
+
echo " Logs: $LOG_FILE"
|
|
229
|
+
echo " Install: $REPO_DIR"
|
|
230
|
+
else
|
|
231
|
+
echo -e " Status: ${RED}Stopped${NC}"
|
|
232
|
+
|
|
233
|
+
if [[ -d "$REPO_DIR" ]]; then
|
|
234
|
+
echo " Install: $REPO_DIR"
|
|
235
|
+
echo ""
|
|
236
|
+
echo " Run 'claude-deck start' to start the server"
|
|
237
|
+
else
|
|
238
|
+
echo " Install: Not installed"
|
|
239
|
+
echo ""
|
|
240
|
+
echo " Run 'claude-deck install' to install"
|
|
241
|
+
fi
|
|
242
|
+
fi
|
|
243
|
+
echo ""
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
cmd_logs() {
|
|
247
|
+
if [[ ! -f "$LOG_FILE" ]]; then
|
|
248
|
+
log_warn "No log file found"
|
|
249
|
+
exit 1
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
tail -f "$LOG_FILE"
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
cmd_update() {
|
|
256
|
+
if [[ ! -d "$REPO_DIR" ]]; then
|
|
257
|
+
log_error "ClaudeDeck is not installed. Run 'claude-deck install' first."
|
|
258
|
+
exit 1
|
|
259
|
+
fi
|
|
260
|
+
|
|
261
|
+
local was_running=false
|
|
262
|
+
if is_running; then
|
|
263
|
+
was_running=true
|
|
264
|
+
cmd_stop
|
|
265
|
+
fi
|
|
266
|
+
|
|
267
|
+
log_info "Updating ClaudeDeck..."
|
|
268
|
+
|
|
269
|
+
cd "$REPO_DIR"
|
|
270
|
+
|
|
271
|
+
# Fetch and check
|
|
272
|
+
git fetch
|
|
273
|
+
local local_hash remote_hash
|
|
274
|
+
local_hash=$(git rev-parse HEAD)
|
|
275
|
+
remote_hash=$(git rev-parse @{u})
|
|
276
|
+
|
|
277
|
+
if [[ "$local_hash" == "$remote_hash" ]]; then
|
|
278
|
+
log_success "Already up to date"
|
|
279
|
+
else
|
|
280
|
+
log_info "Pulling latest changes..."
|
|
281
|
+
git pull --ff-only
|
|
282
|
+
|
|
283
|
+
log_info "Installing dependencies..."
|
|
284
|
+
npm install --legacy-peer-deps
|
|
285
|
+
|
|
286
|
+
log_info "Rebuilding..."
|
|
287
|
+
npm run build
|
|
288
|
+
|
|
289
|
+
log_success "Update complete!"
|
|
290
|
+
fi
|
|
291
|
+
|
|
292
|
+
if [[ "$was_running" == true ]]; then
|
|
293
|
+
cmd_start
|
|
294
|
+
fi
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
cmd_enable() {
|
|
298
|
+
if [[ ! -d "$REPO_DIR" ]]; then
|
|
299
|
+
log_error "ClaudeDeck is not installed. Run 'claude-deck install' first."
|
|
300
|
+
exit 1
|
|
301
|
+
fi
|
|
302
|
+
|
|
303
|
+
local script_path
|
|
304
|
+
script_path=$(realpath "$0")
|
|
305
|
+
|
|
306
|
+
if [[ "$OS" == "macos" ]]; then
|
|
307
|
+
local plist_path="$HOME/Library/LaunchAgents/com.claude-deck.plist"
|
|
308
|
+
|
|
309
|
+
cat > "$plist_path" << EOF
|
|
310
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
311
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
312
|
+
<plist version="1.0">
|
|
313
|
+
<dict>
|
|
314
|
+
<key>Label</key>
|
|
315
|
+
<string>com.claude-deck</string>
|
|
316
|
+
<key>ProgramArguments</key>
|
|
317
|
+
<array>
|
|
318
|
+
<string>$script_path</string>
|
|
319
|
+
<string>start</string>
|
|
320
|
+
</array>
|
|
321
|
+
<key>RunAtLoad</key>
|
|
322
|
+
<true/>
|
|
323
|
+
<key>KeepAlive</key>
|
|
324
|
+
<false/>
|
|
325
|
+
<key>StandardOutPath</key>
|
|
326
|
+
<string>$LOG_FILE</string>
|
|
327
|
+
<key>StandardErrorPath</key>
|
|
328
|
+
<string>$LOG_FILE</string>
|
|
329
|
+
<key>EnvironmentVariables</key>
|
|
330
|
+
<dict>
|
|
331
|
+
<key>PATH</key>
|
|
332
|
+
<string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
|
|
333
|
+
</dict>
|
|
334
|
+
</dict>
|
|
335
|
+
</plist>
|
|
336
|
+
EOF
|
|
337
|
+
|
|
338
|
+
launchctl load "$plist_path" 2>/dev/null || true
|
|
339
|
+
log_success "Auto-start enabled (launchd)"
|
|
340
|
+
echo " Plist: $plist_path"
|
|
341
|
+
|
|
342
|
+
elif [[ -d /etc/systemd ]]; then
|
|
343
|
+
local service_dir="$HOME/.config/systemd/user"
|
|
344
|
+
local service_path="$service_dir/claude-deck.service"
|
|
345
|
+
|
|
346
|
+
mkdir -p "$service_dir"
|
|
347
|
+
|
|
348
|
+
cat > "$service_path" << EOF
|
|
349
|
+
[Unit]
|
|
350
|
+
Description=ClaudeDeck - AI Coding Session Manager
|
|
351
|
+
After=network.target
|
|
352
|
+
|
|
353
|
+
[Service]
|
|
354
|
+
Type=simple
|
|
355
|
+
ExecStart=$script_path start-foreground
|
|
356
|
+
Restart=on-failure
|
|
357
|
+
RestartSec=10
|
|
358
|
+
Environment=PATH=/usr/local/bin:/usr/bin:/bin
|
|
359
|
+
|
|
360
|
+
[Install]
|
|
361
|
+
WantedBy=default.target
|
|
362
|
+
EOF
|
|
363
|
+
|
|
364
|
+
systemctl --user daemon-reload
|
|
365
|
+
systemctl --user enable claude-deck
|
|
366
|
+
log_success "Auto-start enabled (systemd)"
|
|
367
|
+
echo " Service: $service_path"
|
|
368
|
+
|
|
369
|
+
else
|
|
370
|
+
log_error "Could not detect init system (launchd/systemd)"
|
|
371
|
+
exit 1
|
|
372
|
+
fi
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
cmd_disable() {
|
|
376
|
+
if [[ "$OS" == "macos" ]]; then
|
|
377
|
+
local plist_path="$HOME/Library/LaunchAgents/com.claude-deck.plist"
|
|
378
|
+
|
|
379
|
+
if [[ -f "$plist_path" ]]; then
|
|
380
|
+
launchctl unload "$plist_path" 2>/dev/null || true
|
|
381
|
+
rm -f "$plist_path"
|
|
382
|
+
log_success "Auto-start disabled"
|
|
383
|
+
else
|
|
384
|
+
log_warn "Auto-start was not enabled"
|
|
385
|
+
fi
|
|
386
|
+
|
|
387
|
+
elif [[ -d /etc/systemd ]]; then
|
|
388
|
+
systemctl --user disable claude-deck 2>/dev/null || true
|
|
389
|
+
rm -f "$HOME/.config/systemd/user/claude-deck.service"
|
|
390
|
+
systemctl --user daemon-reload
|
|
391
|
+
log_success "Auto-start disabled"
|
|
392
|
+
|
|
393
|
+
else
|
|
394
|
+
log_error "Could not detect init system"
|
|
395
|
+
exit 1
|
|
396
|
+
fi
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
cmd_uninstall() {
|
|
400
|
+
echo ""
|
|
401
|
+
log_warn "This will remove ClaudeDeck and all its data."
|
|
402
|
+
|
|
403
|
+
if ! prompt_yn "Are you sure?" "n"; then
|
|
404
|
+
log_info "Cancelled"
|
|
405
|
+
exit 0
|
|
406
|
+
fi
|
|
407
|
+
|
|
408
|
+
# Detect if installed via npm (check if script is in node_modules)
|
|
409
|
+
local installed_via_npm=false
|
|
410
|
+
if [[ "$SCRIPT_DIR" == *"node_modules"* ]]; then
|
|
411
|
+
installed_via_npm=true
|
|
412
|
+
fi
|
|
413
|
+
|
|
414
|
+
# Stop if running
|
|
415
|
+
if is_running; then
|
|
416
|
+
cmd_stop
|
|
417
|
+
fi
|
|
418
|
+
|
|
419
|
+
# Disable auto-start
|
|
420
|
+
cmd_disable 2>/dev/null || true
|
|
421
|
+
|
|
422
|
+
# Remove CLI symlink (only for non-npm installs)
|
|
423
|
+
if [[ "$installed_via_npm" == false ]]; then
|
|
424
|
+
if [[ -L "$HOME/.local/bin/claude-deck" ]]; then
|
|
425
|
+
log_info "Removing CLI symlink..."
|
|
426
|
+
rm -f "$HOME/.local/bin/claude-deck"
|
|
427
|
+
elif [[ -L "/usr/local/bin/claude-deck" ]]; then
|
|
428
|
+
# Legacy location
|
|
429
|
+
log_info "Removing CLI symlink..."
|
|
430
|
+
sudo rm -f "/usr/local/bin/claude-deck"
|
|
431
|
+
fi
|
|
432
|
+
fi
|
|
433
|
+
|
|
434
|
+
# Remove installation directory
|
|
435
|
+
if [[ -d "$AGENT_OS_HOME" ]]; then
|
|
436
|
+
log_info "Removing $AGENT_OS_HOME..."
|
|
437
|
+
rm -rf "$AGENT_OS_HOME"
|
|
438
|
+
fi
|
|
439
|
+
|
|
440
|
+
log_success "ClaudeDeck uninstalled"
|
|
441
|
+
|
|
442
|
+
# If installed via npm, provide instructions to remove the global package
|
|
443
|
+
if [[ "$installed_via_npm" == true ]]; then
|
|
444
|
+
echo ""
|
|
445
|
+
log_info "To completely remove the CLI, run:"
|
|
446
|
+
echo " npm uninstall -g @atercates/claude-deck"
|
|
447
|
+
fi
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
cmd_start_foreground() {
|
|
451
|
+
if [[ ! -d "$REPO_DIR" ]]; then
|
|
452
|
+
log_error "ClaudeDeck is not installed."
|
|
453
|
+
exit 1
|
|
454
|
+
fi
|
|
455
|
+
|
|
456
|
+
cd "$REPO_DIR"
|
|
457
|
+
|
|
458
|
+
# Create PID file before exec (PID stays the same after exec)
|
|
459
|
+
echo "$$" > "$PID_FILE"
|
|
460
|
+
|
|
461
|
+
exec npm start
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
cmd_help() {
|
|
465
|
+
echo ""
|
|
466
|
+
echo -e "${BOLD}ClaudeDeck${NC} - Self-hosted AI coding session manager"
|
|
467
|
+
echo ""
|
|
468
|
+
echo "Usage: claude-deck <command>"
|
|
469
|
+
echo ""
|
|
470
|
+
echo "Commands:"
|
|
471
|
+
echo " install Install ClaudeDeck (auto-installs dependencies)"
|
|
472
|
+
echo " run Start server and open in browser"
|
|
473
|
+
echo " start Start the server in background"
|
|
474
|
+
echo " stop Stop the server"
|
|
475
|
+
echo " restart Restart the server"
|
|
476
|
+
echo " status Show server status and URLs"
|
|
477
|
+
echo " logs Tail server logs"
|
|
478
|
+
echo " update Update to latest version"
|
|
479
|
+
echo " enable Enable auto-start on boot"
|
|
480
|
+
echo " disable Disable auto-start"
|
|
481
|
+
echo " uninstall Remove ClaudeDeck completely"
|
|
482
|
+
echo ""
|
|
483
|
+
echo "Environment variables:"
|
|
484
|
+
echo " AGENT_OS_HOME Installation directory (default: ~/.claude-deck)"
|
|
485
|
+
echo " AGENT_OS_PORT Server port (default: 3011)"
|
|
486
|
+
echo ""
|
|
487
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Common utilities for claude-deck scripts
|
|
3
|
+
|
|
4
|
+
# Colors
|
|
5
|
+
RED='\033[0;31m'
|
|
6
|
+
GREEN='\033[0;32m'
|
|
7
|
+
YELLOW='\033[1;33m'
|
|
8
|
+
BLUE='\033[0;34m'
|
|
9
|
+
NC='\033[0m'
|
|
10
|
+
|
|
11
|
+
# Logging
|
|
12
|
+
log_info() { echo -e "${BLUE}==>${NC} $1"; }
|
|
13
|
+
log_success() { echo -e "${GREEN}==>${NC} $1"; }
|
|
14
|
+
log_warn() { echo -e "${YELLOW}==>${NC} $1"; }
|
|
15
|
+
log_error() { echo -e "${RED}==>${NC} $1"; }
|
|
16
|
+
|
|
17
|
+
# OS Detection
|
|
18
|
+
detect_os() {
|
|
19
|
+
case "$(uname -s)" in
|
|
20
|
+
Darwin*)
|
|
21
|
+
echo "macos"
|
|
22
|
+
;;
|
|
23
|
+
Linux*)
|
|
24
|
+
if [[ -f /etc/debian_version ]]; then
|
|
25
|
+
echo "debian"
|
|
26
|
+
elif [[ -f /etc/redhat-release ]]; then
|
|
27
|
+
echo "redhat"
|
|
28
|
+
else
|
|
29
|
+
echo "linux"
|
|
30
|
+
fi
|
|
31
|
+
;;
|
|
32
|
+
*)
|
|
33
|
+
echo "unknown"
|
|
34
|
+
;;
|
|
35
|
+
esac
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# Check if running interactively
|
|
39
|
+
is_interactive() {
|
|
40
|
+
[[ -t 0 ]] && [[ -t 1 ]]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# Prompt for yes/no
|
|
44
|
+
prompt_yn() {
|
|
45
|
+
local prompt="$1"
|
|
46
|
+
local default="${2:-y}"
|
|
47
|
+
|
|
48
|
+
if ! is_interactive; then
|
|
49
|
+
[[ "$default" == "y" ]]
|
|
50
|
+
return
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
local yn_prompt
|
|
54
|
+
if [[ "$default" == "y" ]]; then
|
|
55
|
+
yn_prompt="[Y/n]"
|
|
56
|
+
else
|
|
57
|
+
yn_prompt="[y/N]"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
read -p "$prompt $yn_prompt " -r response
|
|
61
|
+
response="${response:-$default}"
|
|
62
|
+
|
|
63
|
+
[[ "$response" =~ ^[Yy] ]]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# Process management helpers
|
|
67
|
+
get_pid() {
|
|
68
|
+
local pid_file="$AGENT_OS_HOME/claude-deck.pid"
|
|
69
|
+
if [[ -f "$pid_file" ]]; then
|
|
70
|
+
local pid
|
|
71
|
+
pid=$(cat "$pid_file")
|
|
72
|
+
if kill -0 "$pid" 2>/dev/null; then
|
|
73
|
+
echo "$pid"
|
|
74
|
+
return 0
|
|
75
|
+
fi
|
|
76
|
+
fi
|
|
77
|
+
return 1
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
is_running() {
|
|
81
|
+
get_pid &>/dev/null
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# Get Tailscale IP if available
|
|
85
|
+
get_tailscale_ip() {
|
|
86
|
+
if command -v tailscale &> /dev/null; then
|
|
87
|
+
tailscale ip -4 2>/dev/null | head -1
|
|
88
|
+
fi
|
|
89
|
+
}
|