Changes:
- Create Gitea workflow for ai-stack-deployer
- Trigger on main branch (default branch)
- Use oussamadouhou + REGISTRY_TOKEN for authentication
- Build from ./Dockerfile
This enables :latest tag creation via {{is_default_branch}}.
Tags created:
- git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:latest
- git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:<sha>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
202 lines
6.3 KiB
Bash
Executable File
202 lines
6.3 KiB
Bash
Executable File
#!/bin/bash
|
||
# scripts/claude-start.sh
|
||
# Description: Start Claude Code with persistent session management for AI Stack Deployer
|
||
# Usage: ./scripts/claude-start.sh [session-name] [additional-flags]
|
||
|
||
set -e # Exit on error
|
||
set -u # Exit on undefined variable
|
||
|
||
# Configuration
|
||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
cd "$PROJECT_ROOT"
|
||
|
||
# Store sessions in user's home directory, NOT in project root
|
||
SESSION_DIR="$HOME/.claude/sessions/ai-stack-deployer"
|
||
mkdir -p "$SESSION_DIR"
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
MAGENTA='\033[0;35m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Helper functions
|
||
function success() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
function error() {
|
||
echo -e "${RED}❌ $1${NC}"
|
||
exit 1
|
||
}
|
||
|
||
function info() {
|
||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||
}
|
||
|
||
function warning() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
}
|
||
|
||
function header() {
|
||
echo ""
|
||
echo -e "${MAGENTA}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||
echo -e "${MAGENTA}$1${NC}"
|
||
echo -e "${MAGENTA}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||
}
|
||
|
||
# Generate UUID v4
|
||
function generate_uuid() {
|
||
if command -v uuidgen &> /dev/null; then
|
||
uuidgen | tr '[:upper:]' '[:lower:]'
|
||
elif command -v python3 &> /dev/null; then
|
||
python3 -c "import uuid; print(str(uuid.uuid4()))"
|
||
else
|
||
# Fallback: use random + timestamp
|
||
echo "$(date +%s)-$(( RANDOM % 100000 ))-$(( RANDOM % 100000 ))-$(( RANDOM % 100000 ))"
|
||
fi
|
||
}
|
||
|
||
# Get or create session
|
||
function get_or_create_session() {
|
||
local SESSION_NAME="${1:-$(date +%Y%m%d-%H%M)}"
|
||
local SESSION_FILE="$SESSION_DIR/$SESSION_NAME.session"
|
||
|
||
# Check if session exists
|
||
if [ -f "$SESSION_FILE" ]; then
|
||
# Load existing session
|
||
source "$SESSION_FILE"
|
||
|
||
info "Resuming session: ${MAGENTA}$SESSION_NAME${NC}"
|
||
info "Session ID: ${BLUE}$CLAUDE_SESSION_ID${NC}"
|
||
info "Started: $CLAUDE_SESSION_START"
|
||
|
||
# Calculate session age
|
||
if command -v python3 &> /dev/null; then
|
||
SESSION_AGE=$(python3 -c "
|
||
from datetime import datetime
|
||
start = datetime.strptime('$CLAUDE_SESSION_START', '%Y-%m-%d %H:%M:%S')
|
||
age = datetime.now() - start
|
||
days = age.days
|
||
hours = age.seconds // 3600
|
||
print(f'{days}d {hours}h')
|
||
" 2>/dev/null || echo "N/A")
|
||
info "Age: $SESSION_AGE"
|
||
fi
|
||
|
||
# Update last used timestamp
|
||
echo "export CLAUDE_SESSION_LAST_USED=\"$(date +%Y-%m-%d\ %H:%M:%S)\"" >> "$SESSION_FILE"
|
||
else
|
||
# Create new session
|
||
CLAUDE_SESSION_ID=$(generate_uuid)
|
||
CLAUDE_SESSION_NAME="$SESSION_NAME"
|
||
CLAUDE_SESSION_START="$(date +%Y-%m-%d\ %H:%M:%S)"
|
||
CLAUDE_SESSION_LAST_USED="$(date +%Y-%m-%d\ %H:%M:%S)"
|
||
|
||
# Save session
|
||
cat > "$SESSION_FILE" << SESSIONEOF
|
||
# Claude Code Session: $SESSION_NAME
|
||
# Created: $CLAUDE_SESSION_START
|
||
export CLAUDE_SESSION_ID="$CLAUDE_SESSION_ID"
|
||
export CLAUDE_SESSION_NAME="$SESSION_NAME"
|
||
export CLAUDE_SESSION_START="$CLAUDE_SESSION_START"
|
||
export CLAUDE_SESSION_LAST_USED="$CLAUDE_SESSION_LAST_USED"
|
||
export CLAUDE_SESSION_PROJECT="ai-stack-deployer"
|
||
export CLAUDE_SESSION_MCP_GROUP="project_ai_stack_deployer"
|
||
SESSIONEOF
|
||
|
||
success "Created new session: ${MAGENTA}$SESSION_NAME${NC}"
|
||
info "Session ID: ${BLUE}$CLAUDE_SESSION_ID${NC}"
|
||
info "Session file: $SESSION_FILE"
|
||
fi
|
||
|
||
# Export variables
|
||
export CLAUDE_SESSION_ID
|
||
export CLAUDE_SESSION_NAME
|
||
export CLAUDE_SESSION_START
|
||
export CLAUDE_SESSION_LAST_USED
|
||
export CLAUDE_SESSION_PROJECT="ai-stack-deployer"
|
||
export CLAUDE_SESSION_MCP_GROUP="project_ai_stack_deployer"
|
||
}
|
||
|
||
# Main script logic
|
||
function main() {
|
||
local SESSION_NAME="${1:-$(date +%Y%m%d-%H%M)}"
|
||
shift || true # Remove first argument if it exists
|
||
local ADDITIONAL_FLAGS="$@"
|
||
|
||
header "AI Stack Deployer - Claude Code Session Manager"
|
||
|
||
# Get or create session
|
||
get_or_create_session "$SESSION_NAME"
|
||
|
||
# Display helpful information
|
||
echo ""
|
||
info "Starting Claude Code with persistent session..."
|
||
echo ""
|
||
warning "Session Environment Variables:"
|
||
echo " CLAUDE_SESSION_ID=$CLAUDE_SESSION_ID"
|
||
echo " CLAUDE_SESSION_NAME=$CLAUDE_SESSION_NAME"
|
||
echo " CLAUDE_SESSION_PROJECT=$CLAUDE_SESSION_PROJECT"
|
||
echo " CLAUDE_SESSION_MCP_GROUP=$CLAUDE_SESSION_MCP_GROUP"
|
||
echo ""
|
||
info "Permission Mode: ${CLAUDE_PERMISSION_MODE:-bypassPermissions} (set CLAUDE_PERMISSION_MODE to override)"
|
||
|
||
echo ""
|
||
info "Quick Commands:"
|
||
echo " 🔧 Dev server: bun run dev"
|
||
echo " 🚀 MCP server: bun run mcp"
|
||
echo " ✅ Type check: bun run typecheck"
|
||
echo " 🧪 Test clients: bun run src/test-clients.ts"
|
||
echo ""
|
||
|
||
info "Memory Management:"
|
||
echo " 🧠 Search: graphiti-memory_search_memory_facts({query: '...', group_ids: ['project_ai_stack_deployer']})"
|
||
echo " 💾 Store: graphiti-memory_add_memory({name: '...', episode_body: '...', group_id: 'project_ai_stack_deployer'})"
|
||
echo ""
|
||
|
||
# Start Claude Code with session ID
|
||
header "Starting Claude Code"
|
||
echo ""
|
||
|
||
# Build Claude Code command
|
||
CLAUDE_CMD="claude --session-id \"$CLAUDE_SESSION_ID\""
|
||
|
||
# Add permission mode (default: bypassPermissions, override with CLAUDE_PERMISSION_MODE env var)
|
||
PERMISSION_MODE="${CLAUDE_PERMISSION_MODE:-bypassPermissions}"
|
||
CLAUDE_CMD="$CLAUDE_CMD --permission-mode $PERMISSION_MODE"
|
||
|
||
# Add additional flags if provided
|
||
if [ -n "$ADDITIONAL_FLAGS" ]; then
|
||
CLAUDE_CMD="$CLAUDE_CMD $ADDITIONAL_FLAGS"
|
||
fi
|
||
|
||
info "Command: $CLAUDE_CMD"
|
||
echo ""
|
||
|
||
# Execute Claude Code
|
||
eval $CLAUDE_CMD
|
||
|
||
# After Claude Code exits
|
||
echo ""
|
||
header "Session Ended"
|
||
success "Session complete: $CLAUDE_SESSION_NAME"
|
||
info "Session ID: $CLAUDE_SESSION_ID"
|
||
|
||
echo ""
|
||
warning "Don't forget to store your learnings in Graphiti Memory!"
|
||
echo "Example:"
|
||
echo ""
|
||
echo "graphiti-memory_add_memory({"
|
||
echo " name: \"Session: $CLAUDE_SESSION_NAME - $(date +%Y-%m-%d)\","
|
||
echo " episode_body: \"Accomplished: [...]. Decisions: [...]. Issues: [...].\","
|
||
echo " group_id: \"project_ai_stack_deployer\""
|
||
echo "})"
|
||
echo ""
|
||
}
|
||
|
||
# Run main function
|
||
main "$@"
|