diff --git a/loop/server/loophttp.go b/loop/server/loophttp.go
new file mode 100644
index 0000000..0fd7ee1
--- /dev/null
+++ b/loop/server/loophttp.go
@@ -0,0 +1,753 @@
+// Package server provides HTTP server functionality for the sketch loop.
+package server
+
+import (
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"html"
+	"io"
+	"io/fs"
+	"log/slog"
+	"net/http"
+	"net/http/pprof"
+	"os"
+	"os/exec"
+	"strconv"
+	"strings"
+	"sync"
+	"syscall"
+	"time"
+
+	"github.com/creack/pty"
+	"sketch.dev/ant"
+	"sketch.dev/loop"
+	"sketch.dev/loop/webui"
+)
+
+// terminalSession represents a terminal session with its PTY and the event channel
+type terminalSession struct {
+	pty                *os.File
+	eventsClients      map[chan []byte]bool
+	lastEventClientID  int
+	eventsClientsMutex sync.Mutex
+	cmd                *exec.Cmd
+}
+
+// TerminalMessage represents a message sent from the client for terminal resize events
+type TerminalMessage struct {
+	Type string `json:"type"`
+	Cols uint16 `json:"cols"`
+	Rows uint16 `json:"rows"`
+}
+
+// TerminalResponse represents the response for a new terminal creation
+type TerminalResponse struct {
+	SessionID string `json:"sessionId"`
+}
+
+// Server serves sketch HTTP. Server implements http.Handler.
+type Server struct {
+	mux      *http.ServeMux
+	agent    loop.CodingAgent
+	hostname string
+	logFile  *os.File
+	// Mutex to protect terminalSessions
+	ptyMutex         sync.Mutex
+	terminalSessions map[string]*terminalSession
+}
+
+func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	s.mux.ServeHTTP(w, r)
+}
+
+// New creates a new HTTP server.
+func New(agent loop.CodingAgent, logFile *os.File) (*Server, error) {
+	s := &Server{
+		mux:              http.NewServeMux(),
+		agent:            agent,
+		hostname:         getHostname(),
+		logFile:          logFile,
+		terminalSessions: make(map[string]*terminalSession),
+	}
+
+	webBundle, err := webui.Build()
+	if err != nil {
+		return nil, fmt.Errorf("failed to build web bundle, did you run 'go generate sketch.dev/loop/...'?: %w", err)
+	}
+
+	s.mux.HandleFunc("/diff", func(w http.ResponseWriter, r *http.Request) {
+		// Check if a specific commit hash was requested
+		commit := r.URL.Query().Get("commit")
+
+		// Get the diff, optionally for a specific commit
+		var diff string
+		var err error
+		if commit != "" {
+			// Validate the commit hash format
+			if !isValidGitSHA(commit) {
+				http.Error(w, fmt.Sprintf("Invalid git commit SHA format: %s", commit), http.StatusBadRequest)
+				return
+			}
+
+			diff, err = agent.Diff(&commit)
+		} else {
+			diff, err = agent.Diff(nil)
+		}
+
+		if err != nil {
+			http.Error(w, fmt.Sprintf("Error generating diff: %v", err), http.StatusInternalServerError)
+			return
+		}
+
+		w.Header().Set("Content-Type", "text/plain")
+		w.Write([]byte(diff))
+	})
+
+	// Handler for initialization called by host sketch binary when inside docker.
+	s.mux.HandleFunc("/init", func(w http.ResponseWriter, r *http.Request) {
+		defer func() {
+			if err := recover(); err != nil {
+				slog.ErrorContext(r.Context(), "/init panic", slog.Any("recovered_err", err))
+
+				// Return an error response to the client
+				http.Error(w, fmt.Sprintf("panic: %v\n", err), http.StatusInternalServerError)
+			}
+		}()
+
+		if r.Method != "POST" {
+			http.Error(w, "POST required", http.StatusBadRequest)
+			return
+		}
+
+		body, err := io.ReadAll(r.Body)
+		r.Body.Close()
+		if err != nil {
+			http.Error(w, "failed to read request body: "+err.Error(), http.StatusBadRequest)
+			return
+		}
+		m := make(map[string]string)
+		if err := json.Unmarshal(body, &m); err != nil {
+			http.Error(w, "bad request body: "+err.Error(), http.StatusBadRequest)
+			return
+		}
+		hostAddr := m["host_addr"]
+		gitRemoteAddr := m["git_remote_addr"]
+		commit := m["commit"]
+		ini := loop.AgentInit{
+			WorkingDir:    "/app",
+			InDocker:      true,
+			Commit:        commit,
+			GitRemoteAddr: gitRemoteAddr,
+			HostAddr:      hostAddr,
+		}
+		if err := agent.Init(ini); err != nil {
+			http.Error(w, "init failed: "+err.Error(), http.StatusInternalServerError)
+			return
+		}
+		w.Header().Set("Content-Type", "application/json")
+		io.WriteString(w, "{}\n")
+	})
+
+	// Handler for /messages?start=N&end=M (start/end are optional)
+	s.mux.HandleFunc("/messages", func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+
+		// Extract query parameters for range
+		var start, end int
+		var err error
+
+		currentCount := agent.MessageCount()
+
+		startParam := r.URL.Query().Get("start")
+		if startParam != "" {
+			start, err = strconv.Atoi(startParam)
+			if err != nil {
+				http.Error(w, "Invalid 'start' parameter", http.StatusBadRequest)
+				return
+			}
+		}
+
+		endParam := r.URL.Query().Get("end")
+		if endParam != "" {
+			end, err = strconv.Atoi(endParam)
+			if err != nil {
+				http.Error(w, "Invalid 'end' parameter", http.StatusBadRequest)
+				return
+			}
+		} else {
+			end = currentCount
+		}
+
+		if start < 0 || start > end || end > currentCount {
+			http.Error(w, fmt.Sprintf("Invalid range: start %d end %d currentCount %d", start, end, currentCount), http.StatusBadRequest)
+			return
+		}
+
+		start = max(0, start)
+		end = min(agent.MessageCount(), end)
+		messages := agent.Messages(start, end)
+
+		// Create a JSON encoder with indentation for pretty-printing
+		encoder := json.NewEncoder(w)
+		encoder.SetIndent("", "  ") // Two spaces for each indentation level
+
+		err = encoder.Encode(messages)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+		}
+	})
+
+	// Handler for /logs - displays the contents of the log file
+	s.mux.HandleFunc("/logs", func(w http.ResponseWriter, r *http.Request) {
+		if s.logFile == nil {
+			http.Error(w, "log file not set", http.StatusNotFound)
+			return
+		}
+		logContents, err := os.ReadFile(s.logFile.Name())
+		if err != nil {
+			http.Error(w, "error reading log file: "+err.Error(), http.StatusInternalServerError)
+			return
+		}
+		w.Header().Set("Content-Type", "text/html; charset=utf-8")
+		fmt.Fprintf(w, "<!DOCTYPE html>\n<html>\n<head>\n<title>Sketchy Log File</title>\n</head>\n<body>\n")
+		fmt.Fprintf(w, "<pre>%s</pre>\n", html.EscapeString(string(logContents)))
+		fmt.Fprintf(w, "</body>\n</html>")
+	})
+
+	// Handler for /download - downloads both messages and status as a JSON file
+	s.mux.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) {
+		// Set headers for file download
+		w.Header().Set("Content-Type", "application/octet-stream")
+
+		// Generate filename with format: sketch-YYYYMMDD-HHMMSS.json
+		timestamp := time.Now().Format("20060102-150405")
+		filename := fmt.Sprintf("sketch-%s.json", timestamp)
+
+		w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
+
+		// Get all messages
+		messageCount := agent.MessageCount()
+		messages := agent.Messages(0, messageCount)
+
+		// Get status information (usage and other metadata)
+		totalUsage := agent.TotalUsage()
+		hostname := getHostname()
+		workingDir := getWorkingDir()
+
+		// Create a combined structure with all information
+		downloadData := struct {
+			Messages     []loop.AgentMessage `json:"messages"`
+			MessageCount int                 `json:"message_count"`
+			TotalUsage   ant.CumulativeUsage `json:"total_usage"`
+			Hostname     string              `json:"hostname"`
+			WorkingDir   string              `json:"working_dir"`
+			DownloadTime string              `json:"download_time"`
+		}{
+			Messages:     messages,
+			MessageCount: messageCount,
+			TotalUsage:   totalUsage,
+			Hostname:     hostname,
+			WorkingDir:   workingDir,
+			DownloadTime: time.Now().Format(time.RFC3339),
+		}
+
+		// Marshal the JSON with indentation for better readability
+		jsonData, err := json.MarshalIndent(downloadData, "", "  ")
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+		w.Write(jsonData)
+	})
+
+	// The latter doesn't return until the number of messages has changed (from seen
+	// or from when this was called.)
+	s.mux.HandleFunc("/state", func(w http.ResponseWriter, r *http.Request) {
+		pollParam := r.URL.Query().Get("poll")
+		seenParam := r.URL.Query().Get("seen")
+
+		// Get the client's current message count (if provided)
+		clientMessageCount := -1
+		var err error
+		if seenParam != "" {
+			clientMessageCount, err = strconv.Atoi(seenParam)
+			if err != nil {
+				http.Error(w, "Invalid 'seen' parameter", http.StatusBadRequest)
+				return
+			}
+		}
+
+		serverMessageCount := agent.MessageCount()
+
+		// Let lazy clients not have to specify this.
+		if clientMessageCount == -1 {
+			clientMessageCount = serverMessageCount
+		}
+
+		if pollParam == "true" {
+			ch := make(chan string)
+			go func() {
+				// This is your blocking operation
+				agent.WaitForMessageCount(r.Context(), clientMessageCount)
+				close(ch)
+			}()
+			select {
+			case <-r.Context().Done():
+				slog.DebugContext(r.Context(), "abandoned poll request")
+				return
+			case <-time.After(90 * time.Second):
+				// Let the user call /state again to get the latest to limit how long our long polls hang out.
+				slog.DebugContext(r.Context(), "longish poll request")
+				break
+			case <-ch:
+				break
+			}
+		}
+
+		serverMessageCount = agent.MessageCount()
+		totalUsage := agent.TotalUsage()
+
+		w.Header().Set("Content-Type", "application/json")
+
+		state := struct {
+			MessageCount  int                 `json:"message_count"`
+			TotalUsage    ant.CumulativeUsage `json:"total_usage"`
+			Hostname      string              `json:"hostname"`
+			WorkingDir    string              `json:"working_dir"`
+			InitialCommit string              `json:"initial_commit"`
+			Title         string              `json:"title"`
+			OS            string              `json:"os"`
+		}{
+			MessageCount:  serverMessageCount,
+			TotalUsage:    totalUsage,
+			Hostname:      s.hostname,
+			WorkingDir:    getWorkingDir(),
+			InitialCommit: agent.InitialCommit(),
+			Title:         agent.Title(),
+			OS:            agent.OS(),
+		}
+
+		// Create a JSON encoder with indentation for pretty-printing
+		encoder := json.NewEncoder(w)
+		encoder.SetIndent("", "  ") // Two spaces for each indentation level
+
+		err = encoder.Encode(state)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+		}
+	})
+
+	s.mux.Handle("/static/", http.StripPrefix("/static/", http.FileServerFS(webBundle)))
+
+	// Terminal WebSocket handler
+	// Terminal endpoints - predefined terminals 1-9
+	// TODO: The UI doesn't actually know how to use terminals 2-9!
+	s.mux.HandleFunc("/terminal/events/", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != http.MethodGet {
+			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+			return
+		}
+		pathParts := strings.Split(r.URL.Path, "/")
+		if len(pathParts) < 4 {
+			http.Error(w, "Invalid terminal ID", http.StatusBadRequest)
+			return
+		}
+
+		sessionID := pathParts[3]
+		// Validate that the terminal ID is between 1-9
+		if len(sessionID) != 1 || sessionID[0] < '1' || sessionID[0] > '9' {
+			http.Error(w, "Terminal ID must be between 1 and 9", http.StatusBadRequest)
+			return
+		}
+
+		s.handleTerminalEvents(w, r, sessionID)
+	})
+
+	s.mux.HandleFunc("/terminal/input/", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != http.MethodPost {
+			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+			return
+		}
+		pathParts := strings.Split(r.URL.Path, "/")
+		if len(pathParts) < 4 {
+			http.Error(w, "Invalid terminal ID", http.StatusBadRequest)
+			return
+		}
+		sessionID := pathParts[3]
+		s.handleTerminalInput(w, r, sessionID)
+	})
+
+	s.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+		// Serve the timeline.html file directly from the embedded filesystem
+		data, err := fs.ReadFile(webBundle, "timeline.html")
+		if err != nil {
+			http.Error(w, "File not found", http.StatusNotFound)
+			return
+		}
+		w.Header().Set("Content-Type", "text/html")
+		w.Write(data)
+	})
+
+	// Handler for POST /chat
+	s.mux.HandleFunc("/chat", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != http.MethodPost {
+			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+			return
+		}
+
+		// Parse the request body
+		var requestBody struct {
+			Message string `json:"message"`
+		}
+
+		decoder := json.NewDecoder(r.Body)
+		if err := decoder.Decode(&requestBody); err != nil {
+			http.Error(w, "Invalid request body: "+err.Error(), http.StatusBadRequest)
+			return
+		}
+		defer r.Body.Close()
+
+		if requestBody.Message == "" {
+			http.Error(w, "Message cannot be empty", http.StatusBadRequest)
+			return
+		}
+
+		agent.UserMessage(r.Context(), requestBody.Message)
+
+		w.WriteHeader(http.StatusOK)
+	})
+
+	// Handler for /cancel - cancels the current inner loop in progress
+	s.mux.HandleFunc("/cancel", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != http.MethodPost {
+			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+			return
+		}
+
+		// Parse the request body (optional)
+		var requestBody struct {
+			Reason     string `json:"reason"`
+			ToolCallID string `json:"tool_call_id"`
+		}
+
+		decoder := json.NewDecoder(r.Body)
+		if err := decoder.Decode(&requestBody); err != nil && err != io.EOF {
+			http.Error(w, "Invalid request body: "+err.Error(), http.StatusBadRequest)
+			return
+		}
+		defer r.Body.Close()
+
+		cancelReason := "user requested cancellation"
+		if requestBody.Reason != "" {
+			cancelReason = requestBody.Reason
+		}
+
+		if requestBody.ToolCallID != "" {
+			err := agent.CancelToolUse(requestBody.ToolCallID, fmt.Errorf("%s", cancelReason))
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusBadRequest)
+				return
+			}
+			// Return a success response
+			w.Header().Set("Content-Type", "application/json")
+			json.NewEncoder(w).Encode(map[string]string{
+				"status":     "cancelled",
+				"too_use_id": requestBody.ToolCallID,
+				"reason":     cancelReason})
+			return
+		}
+		// Call the CancelInnerLoop method
+		agent.CancelInnerLoop(fmt.Errorf("%s", cancelReason))
+		// Return a success response
+		w.Header().Set("Content-Type", "application/json")
+		json.NewEncoder(w).Encode(map[string]string{"status": "cancelled", "reason": cancelReason})
+	})
+
+	debugMux := initDebugMux()
+	s.mux.HandleFunc("/debug/", func(w http.ResponseWriter, r *http.Request) {
+		debugMux.ServeHTTP(w, r)
+	})
+
+	return s, nil
+}
+
+// Utility functions
+func getHostname() string {
+	hostname, err := os.Hostname()
+	if err != nil {
+		return "unknown"
+	}
+	return hostname
+}
+
+func getWorkingDir() string {
+	wd, err := os.Getwd()
+	if err != nil {
+		return "unknown"
+	}
+	return wd
+}
+
+// createTerminalSession creates a new terminal session with the given ID
+func (s *Server) createTerminalSession(sessionID string) (*terminalSession, error) {
+	// Start a new shell process
+	shellPath := getShellPath()
+	cmd := exec.Command(shellPath)
+
+	// Get working directory from the agent if possible
+	workDir := getWorkingDir()
+	cmd.Dir = workDir
+
+	// Set up environment
+	cmd.Env = append(os.Environ(), "TERM=xterm-256color")
+
+	// Start the command with a pty
+	ptmx, err := pty.Start(cmd)
+	if err != nil {
+		slog.Error("Failed to start pty", "error", err)
+		return nil, err
+	}
+
+	// Create the terminal session
+	session := &terminalSession{
+		pty:           ptmx,
+		eventsClients: make(map[chan []byte]bool),
+		cmd:           cmd,
+	}
+
+	// Start goroutine to read from pty and broadcast to all connected SSE clients
+	go s.readFromPtyAndBroadcast(sessionID, session)
+
+	return session, nil
+} // handleTerminalEvents handles SSE connections for terminal output
+func (s *Server) handleTerminalEvents(w http.ResponseWriter, r *http.Request, sessionID string) {
+	// Check if the session exists, if not, create it
+	s.ptyMutex.Lock()
+	session, exists := s.terminalSessions[sessionID]
+
+	if !exists {
+		// Create a new terminal session
+		var err error
+		session, err = s.createTerminalSession(sessionID)
+		if err != nil {
+			s.ptyMutex.Unlock()
+			http.Error(w, fmt.Sprintf("Failed to create terminal: %v", err), http.StatusInternalServerError)
+			return
+		}
+
+		// Store the new session
+		s.terminalSessions[sessionID] = session
+	}
+	s.ptyMutex.Unlock()
+
+	// Set headers for SSE
+	w.Header().Set("Content-Type", "text/event-stream")
+	w.Header().Set("Cache-Control", "no-cache")
+	w.Header().Set("Connection", "keep-alive")
+	w.Header().Set("Access-Control-Allow-Origin", "*")
+
+	// Create a channel for this client
+	events := make(chan []byte, 4096) // Buffer to prevent blocking
+
+	// Register this client's channel
+	session.eventsClientsMutex.Lock()
+	clientID := session.lastEventClientID + 1
+	session.lastEventClientID = clientID
+	session.eventsClients[events] = true
+	session.eventsClientsMutex.Unlock()
+
+	// When the client disconnects, remove their channel
+	defer func() {
+		session.eventsClientsMutex.Lock()
+		delete(session.eventsClients, events)
+		close(events)
+		session.eventsClientsMutex.Unlock()
+	}()
+
+	// Flush to send headers to client immediately
+	if f, ok := w.(http.Flusher); ok {
+		f.Flush()
+	}
+
+	// Send events to the client as they arrive
+	for {
+		select {
+		case <-r.Context().Done():
+			return
+		case data := <-events:
+			// Format as SSE with base64 encoding
+			fmt.Fprintf(w, "data: %s\n\n", base64.StdEncoding.EncodeToString(data))
+
+			// Flush the data immediately
+			if f, ok := w.(http.Flusher); ok {
+				f.Flush()
+			}
+		}
+	}
+}
+
+// handleTerminalInput processes input to the terminal
+func (s *Server) handleTerminalInput(w http.ResponseWriter, r *http.Request, sessionID string) {
+	// Check if the session exists
+	s.ptyMutex.Lock()
+	session, exists := s.terminalSessions[sessionID]
+	s.ptyMutex.Unlock()
+
+	if !exists {
+		http.Error(w, "Terminal session not found", http.StatusNotFound)
+		return
+	}
+
+	// Read the request body (terminal input or resize command)
+	body, err := io.ReadAll(r.Body)
+	if err != nil {
+		http.Error(w, "Failed to read request body", http.StatusBadRequest)
+		return
+	}
+
+	// Check if it's a resize message
+	if len(body) > 0 && body[0] == '{' {
+		var msg TerminalMessage
+		if err := json.Unmarshal(body, &msg); err == nil && msg.Type == "resize" {
+			if msg.Cols > 0 && msg.Rows > 0 {
+				pty.Setsize(session.pty, &pty.Winsize{
+					Cols: msg.Cols,
+					Rows: msg.Rows,
+				})
+
+				// Respond with success
+				w.WriteHeader(http.StatusOK)
+				return
+			}
+		}
+	}
+
+	// Regular terminal input
+	_, err = session.pty.Write(body)
+	if err != nil {
+		slog.Error("Failed to write to pty", "error", err)
+		http.Error(w, "Failed to write to terminal", http.StatusInternalServerError)
+		return
+	}
+
+	// Respond with success
+	w.WriteHeader(http.StatusOK)
+}
+
+// readFromPtyAndBroadcast reads output from the PTY and broadcasts it to all connected clients
+func (s *Server) readFromPtyAndBroadcast(sessionID string, session *terminalSession) {
+	buf := make([]byte, 4096)
+	defer func() {
+		// Clean up when done
+		s.ptyMutex.Lock()
+		delete(s.terminalSessions, sessionID)
+		s.ptyMutex.Unlock()
+
+		// Close the PTY
+		session.pty.Close()
+
+		// Ensure process is terminated
+		if session.cmd.Process != nil {
+			session.cmd.Process.Signal(syscall.SIGTERM)
+			time.Sleep(100 * time.Millisecond)
+			session.cmd.Process.Kill()
+		}
+
+		// Close all client channels
+		session.eventsClientsMutex.Lock()
+		for ch := range session.eventsClients {
+			delete(session.eventsClients, ch)
+			close(ch)
+		}
+		session.eventsClientsMutex.Unlock()
+	}()
+
+	for {
+		n, err := session.pty.Read(buf)
+		if err != nil {
+			if err != io.EOF {
+				slog.Error("Failed to read from pty", "error", err)
+			}
+			break
+		}
+
+		// Make a copy of the data for each client
+		data := make([]byte, n)
+		copy(data, buf[:n])
+
+		// Broadcast to all connected clients
+		session.eventsClientsMutex.Lock()
+		for ch := range session.eventsClients {
+			// Try to send, but don't block if channel is full
+			select {
+			case ch <- data:
+			default:
+				// Channel is full, drop the message for this client
+			}
+		}
+		session.eventsClientsMutex.Unlock()
+	}
+}
+
+// getShellPath returns the path to the shell to use
+func getShellPath() string {
+	// Try to use the user's preferred shell
+	shell := os.Getenv("SHELL")
+	if shell != "" {
+		return shell
+	}
+
+	// Default to bash on Unix-like systems
+	if _, err := os.Stat("/bin/bash"); err == nil {
+		return "/bin/bash"
+	}
+
+	// Fall back to sh
+	return "/bin/sh"
+}
+
+func initDebugMux() *http.ServeMux {
+	mux := http.NewServeMux()
+	mux.HandleFunc("GET /debug/{$}", func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "text/html; charset=utf-8")
+		fmt.Fprintf(w, `<!doctype html>
+			<html><head><title>sketch debug</title></head><body>
+			<h1>sketch debug</h1>
+			<ul>
+					<li><a href="/debug/pprof/cmdline">pprof/cmdline</a></li>
+					<li><a href="/debug/pprof/profile">pprof/profile</a></li>
+					<li><a href="/debug/pprof/symbol">pprof/symbol</a></li>
+					<li><a href="/debug/pprof/trace">pprof/trace</a></li>
+					<li><a href="/debug/pprof/goroutine?debug=1">pprof/goroutine?debug=1</a></li>
+					<li><a href="/debug/metrics">metrics</a></li>
+			</ul>
+			</body>
+			</html>
+			`)
+	})
+	mux.HandleFunc("GET /debug/pprof/", pprof.Index)
+	mux.HandleFunc("GET /debug/pprof/cmdline", pprof.Cmdline)
+	mux.HandleFunc("GET /debug/pprof/profile", pprof.Profile)
+	mux.HandleFunc("GET /debug/pprof/symbol", pprof.Symbol)
+	mux.HandleFunc("GET /debug/pprof/trace", pprof.Trace)
+	return mux
+}
+
+// isValidGitSHA validates if a string looks like a valid git SHA hash.
+// Git SHAs are hexadecimal strings of at least 4 characters but typically 7, 8, or 40 characters.
+func isValidGitSHA(sha string) bool {
+	// Git SHA must be a hexadecimal string with at least 4 characters
+	if len(sha) < 4 || len(sha) > 40 {
+		return false
+	}
+
+	// Check if the string only contains hexadecimal characters
+	for _, char := range sha {
+		if !(char >= '0' && char <= '9') && !(char >= 'a' && char <= 'f') && !(char >= 'A' && char <= 'F') {
+			return false
+		}
+	}
+
+	return true
+}
