···2424LOG_DIR="${HOME}/.slopper/logs"
2525LOG_FILE="${LOG_DIR}/slopper-$(date +%Y%m%d).log"
2626WORKSPACE="${SLOPPER_WORKSPACE:-$(pwd)}"
2727+# For OCaml mode, use workspace-local .slopper directory to work with container mount
2828+HISTORY_DIR="${WORKSPACE}/.slopper/history"
2729FORCE_REBUILD=false
2830QUIET=false
2931MODE=""
3032EXEC_PROMPT=""
31333232-# Ensure log directory exists
3434+# Ensure log and history directories exist
3335mkdir -p "${LOG_DIR}"
3636+mkdir -p "${HISTORY_DIR}"
34373538# Logging function
3639log() {
···261264 exit $exit_code
262265}
263266267267+# OCaml mode - interactive shell with history logging and Claude integration
268268+mode_ocaml() {
269269+ log INFO "Running OCaml development mode with history logging"
270270+271271+ check_devcontainer_cli
272272+ ensure_devcontainer
273273+274274+ # Create session ID and file paths
275275+ local session_id="ocaml-$(date +%Y%m%d-%H%M%S)"
276276+ local typescript_file="${HISTORY_DIR}/${session_id}.typescript"
277277+ local clean_log="${HISTORY_DIR}/${session_id}.log"
278278+279279+ log INFO "Starting OCaml development session: $session_id"
280280+ log INFO "Session will be recorded to: $typescript_file"
281281+282282+ # Create session recording script
283283+ local tracker_script=$(mktemp)
284284+ cat > "$tracker_script" << 'EOF'
285285+#!/bin/bash
286286+287287+# OCaml development session with complete recording using script
288288+SESSION_ID="$1"
289289+TYPESCRIPT_FILE="$2"
290290+CLEAN_LOG="$3"
291291+292292+echo "=== OCaml Development Session Started ==="
293293+echo "Session ID: $SESSION_ID"
294294+echo "Timestamp: $(date)"
295295+echo "Workspace: $(pwd)"
296296+echo ""
297297+298298+# Check OCaml installation
299299+if command -v ocaml >/dev/null 2>&1; then
300300+ echo "OCaml version: $(ocaml -version)"
301301+else
302302+ echo "Note: OCaml not found - you may need to install it"
303303+fi
304304+305305+if command -v opam >/dev/null 2>&1; then
306306+ echo "OPAM version: $(opam --version)"
307307+ echo "Current switch: $(opam switch show 2>/dev/null || echo 'none')"
308308+else
309309+ echo "Note: OPAM not found - you may need to install it"
310310+fi
311311+312312+echo ""
313313+echo "OCaml Development Environment Ready!"
314314+echo "- Complete session recording enabled"
315315+echo "- Session ID: $SESSION_ID"
316316+echo "- Type 'exit' when done to process with Claude"
317317+echo ""
318318+319319+# Record the entire interactive session using script
320320+# -f: flush output immediately
321321+# -q: quiet mode (don't show start/stop messages)
322322+script -f -q "$TYPESCRIPT_FILE" -c "bash --login -i"
323323+324324+echo ""
325325+echo "=== OCaml Development Session Ended ==="
326326+echo "Timestamp: $(date)"
327327+328328+# Clean the typescript file to remove colors and control sequences
329329+if command -v col >/dev/null 2>&1; then
330330+ echo "Cleaning session log..."
331331+ cat "$TYPESCRIPT_FILE" | col -b > "$CLEAN_LOG"
332332+ echo "Clean session log saved to: $CLEAN_LOG"
333333+else
334334+ echo "Warning: 'col' command not found, using raw typescript"
335335+ cp "$TYPESCRIPT_FILE" "$CLEAN_LOG"
336336+fi
337337+EOF
338338+339339+ chmod +x "$tracker_script"
340340+341341+ # Ensure the history directory exists in the container first
342342+ npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
343343+ mkdir -p "/home/node/.slopper/history"
344344+345345+ # Copy tracker script to container and run the tracked session
346346+ local container_script="/tmp/tracker_script.sh"
347347+ npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
348348+ bash -c "cat > '$container_script' << 'EOF'
349349+$(cat "$tracker_script")
350350+EOF"
351351+352352+ npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
353353+ chmod +x "$container_script"
354354+355355+ # Run with container paths for the session files
356356+ local container_typescript="/home/node/.slopper/history/${session_id}.typescript"
357357+ local container_clean_log="/home/node/.slopper/history/${session_id}.log"
358358+359359+ npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
360360+ bash "$container_script" "$session_id" "$container_typescript" "$container_clean_log"
361361+362362+ local exit_code=$?
363363+364364+ # Clean up tracker script
365365+ rm -f "$tracker_script"
366366+367367+ log INFO "OCaml session ended. Processing with Claude..."
368368+369369+ # Check if we have session data to process (files are accessible via the mount)
370370+ if [ -f "$clean_log" ] && [ -s "$clean_log" ]; then
371371+ process_ocaml_session_with_claude "$session_id" "$typescript_file" "$clean_log"
372372+ else
373373+ log WARN "No session data captured, skipping Claude processing"
374374+ fi
375375+376376+ stop_devcontainer
377377+378378+ if [ $exit_code -eq 0 ]; then
379379+ log INFO "OCaml development session completed successfully"
380380+ else
381381+ log WARN "OCaml development session ended with exit code: $exit_code"
382382+ fi
383383+384384+ exit $exit_code
385385+}
386386+387387+# Function to process OCaml session with Claude
388388+process_ocaml_session_with_claude() {
389389+ local session_id="$1"
390390+ local typescript_file="$2"
391391+ local clean_log="$3"
392392+393393+ log INFO "Processing OCaml session $session_id with Claude..."
394394+ log DEBUG "Session files - typescript: $typescript_file, clean_log: $clean_log"
395395+396396+ # Check file sizes for debugging
397397+ if [ -f "$clean_log" ]; then
398398+ local log_size=$(wc -l < "$clean_log" 2>/dev/null || echo "0")
399399+ log DEBUG "Clean log file exists with $log_size lines"
400400+ log DEBUG "First few lines of clean log:"
401401+ head -10 "$clean_log" 2>/dev/null | while read line; do
402402+ log DEBUG " $line"
403403+ done
404404+ else
405405+ log WARN "Clean log file does not exist: $clean_log"
406406+ return 1
407407+ fi
408408+409409+ # Check if Claude is available in the devcontainer
410410+ log DEBUG "Checking for Claude CLI in devcontainer..."
411411+ if ! npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- which claude &>/dev/null; then
412412+ log WARN "Claude CLI not found in devcontainer, skipping setup-ocaml script refinement"
413413+ return 0
414414+ fi
415415+ log DEBUG "Claude CLI found in devcontainer"
416416+417417+ # Create analysis prompt (inside container paths)
418418+ local analysis_file="/home/node/.slopper/history/${session_id}.analysis"
419419+ log DEBUG "Creating analysis file: $analysis_file"
420420+ npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
421421+ bash -c "cat > '$analysis_file' << 'EOF'
422422+Please analyze this OCaml development session and help refine the setup-ocaml script.
423423+424424+SESSION DETAILS:
425425+- Session ID: $session_id
426426+- Workspace: /workspace
427427+428428+COMPLETE SESSION RECORDING:
429429+\$(if [ -f \"/home/node/.slopper/history/${session_id}.log\" ]; then cat \"/home/node/.slopper/history/${session_id}.log\"; else echo \"No session recording available\"; fi)
430430+431431+CURRENT setup-ocaml.sh SCRIPT:
432432+\$(cat \"/usr/local/bin/setup-ocaml.sh\")
433433+434434+TASK:
435435+Based on the complete session recording above, please analyze my OCaml development workflow and suggest improvements to the setup-ocaml.sh script. Focus on:
436436+437437+1. Any missing dependencies or tools that were needed during the session
438438+2. Additional opam packages that should be pre-installed
439439+3. Environment setup that could be automated
440440+4. Common development patterns that could be scripted
441441+5. Any pins or specific package versions that were useful
442442+6. Error patterns that suggest missing configurations
443443+444444+The session recording shows everything I typed and all output, so you can see the complete workflow including any errors, installations, or manual setup steps.
445445+446446+Please provide specific, actionable improvements that would make OCaml development setup more efficient. In particular, pay attention to the .devcontainer files.
447447+EOF'"
448448+449449+ log DEBUG "Analysis file created, verifying it exists..."
450450+ npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
451451+ bash -c "if [ -f '$analysis_file' ]; then echo 'Analysis file exists, size:' \$(wc -c < '$analysis_file'); else echo 'Analysis file missing!'; fi" || log WARN "Failed to verify analysis file"
452452+453453+ log INFO "Sending session analysis to Claude..."
454454+455455+ # Run Claude analysis inside the devcontainer
456456+ # Since .slopper/history is bind-mounted, write directly to /workspace/.slopper/history
457457+ local claude_output_container="/workspace/.slopper/history/${session_id}.claude-suggestions"
458458+ local claude_output_host="${HISTORY_DIR}/${session_id}.claude-suggestions"
459459+460460+ log DEBUG "Running Claude with analysis file, output will go to: $claude_output_container (mounted path)"
461461+ log DEBUG "Claude command: cd /workspace && claude -p '$analysis_file' > '$claude_output_container'"
462462+463463+ if npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
464464+ bash -c "cd /workspace && claude --dangerously-skip-permissions -p '$analysis_file' > '$claude_output_container' 2>&1"; then
465465+ log INFO "Claude analysis completed successfully"
466466+467467+ # Check if output file exists and has content (directly on host via mount)
468468+ if [ -f "$claude_output_host" ]; then
469469+ local output_size=$(wc -c < "$claude_output_host" 2>/dev/null || echo "0")
470470+ log DEBUG "Claude output file size: $output_size bytes"
471471+ else
472472+ local output_size=0
473473+ log DEBUG "Claude output file does not exist on host"
474474+ fi
475475+476476+ if [ "$output_size" -gt 0 ]; then
477477+ # Output is already on host via bind mount, just display it
478478+ echo ""
479479+ echo "=== Claude Analysis and Suggestions ==="
480480+ cat "$claude_output_host"
481481+ echo ""
482482+ echo "Analysis saved to: $claude_output_host"
483483+ else
484484+ log WARN "Claude output file is empty or missing"
485485+ log DEBUG "Attempting to show stderr from Claude command..."
486486+ npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
487487+ bash -c "if [ -f '$claude_output_container' ]; then cat '$claude_output_container'; else echo 'Output file does not exist'; fi"
488488+ fi
489489+ else
490490+ local exit_code=$?
491491+ log ERROR "Claude analysis failed with exit code: $exit_code"
492492+493493+ # Try to get error output
494494+ if npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
495495+ test -f "$claude_output_container"; then
496496+ echo "Error output:"
497497+ npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
498498+ cat "$claude_output_container"
499499+ else
500500+ log DEBUG "No error output file found"
501501+ fi
502502+503503+ # Additional debugging - check if Claude is actually available
504504+ log DEBUG "Verifying Claude CLI accessibility:"
505505+ npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
506506+ bash -c "which claude; claude --version 2>&1 || echo 'Claude version check failed'"
507507+ fi
508508+509509+ # Clean up analysis file (but keep it for debugging if Claude failed)
510510+ if [ "$output_size" -gt 0 ] 2>/dev/null; then
511511+ log DEBUG "Cleaning up analysis file (Claude succeeded)"
512512+ npx @devcontainers/cli exec --workspace-folder "${WORKSPACE}" -- \
513513+ rm -f "$analysis_file"
514514+ else
515515+ log DEBUG "Keeping analysis file for debugging (Claude failed or produced no output)"
516516+ log DEBUG "Analysis file preserved at: $analysis_file"
517517+ fi
518518+}
519519+264520# Help function
265521show_help() {
266522 cat << EOF
···273529 -e, --exec PROMPT Execute a single Claude prompt non-interactively
274530 -s, --shell Open interactive shell in devcontainer (default)
275531 -c, --claude Start interactive Claude session
532532+ -o, --ocaml OCaml development mode with history logging
276533277534OPTIONS:
278535 -f, --force Force rebuild devcontainer from scratch
···288545 Development:
289546 ./slopper # Quick shell into dev environment
290547 ./slopper --claude # Interactive Claude coding session
548548+ ./slopper --ocaml # OCaml dev mode with history logging
291549292550 Automation:
293551 ./slopper -e "fix the bug in main.ml" # CI/CD code fixes
···336594 MODE="claude"
337595 shift
338596 ;;
597597+ -o|--ocaml)
598598+ [ -n "$MODE" ] && { log ERROR "Multiple modes specified"; exit 1; }
599599+ MODE="ocaml"
600600+ shift
601601+ ;;
339602 -f|--force)
340603 FORCE_REBUILD=true
341604 shift
···391654 claude)
392655 mode_claude
393656 ;;
657657+ ocaml)
658658+ mode_ocaml
659659+ ;;
394660 *)
395661 log ERROR "Invalid mode: $MODE"
396662 exit 1
397663 ;;
398398-esac664664+esac