Detailed changes
  
  
    
    @@ -85,14 +85,14 @@ to assist developers in writing, debugging, and understanding code directly from
 
 		app, err := app.New(ctx, conn, cfg)
 		if err != nil {
-			slog.Error(fmt.Sprintf("Failed to create app instance: %v", err))
+			slog.Error("Failed to create app instance", "error", err)
 			return err
 		}
 		defer app.Shutdown()
 
 		prompt, err = maybePrependStdin(prompt)
 		if err != nil {
-			slog.Error(fmt.Sprintf("Failed to read from stdin: %v", err))
+			slog.Error("Failed to read from stdin", "error", err)
 			return err
 		}
 
@@ -114,7 +114,7 @@ to assist developers in writing, debugging, and understanding code directly from
 		go app.Subscribe(program)
 
 		if _, err := program.Run(); err != nil {
-			slog.Error(fmt.Sprintf("TUI run error: %v", err))
+			slog.Error("TUI run error", "error", err)
 			return fmt.Errorf("TUI error: %v", err)
 		}
 		return nil
  
  
  
    
    @@ -227,7 +227,7 @@ func (a *agent) Cancel(sessionID string) {
 	// Cancel regular requests
 	if cancelFunc, exists := a.activeRequests.LoadAndDelete(sessionID); exists {
 		if cancel, ok := cancelFunc.(context.CancelFunc); ok {
-			slog.Info(fmt.Sprintf("Request cancellation initiated for session: %s", sessionID))
+			slog.Info("Request cancellation initiated", "session_id", sessionID)
 			cancel()
 		}
 	}
@@ -235,7 +235,7 @@ func (a *agent) Cancel(sessionID string) {
 	// Also check for summarize requests
 	if cancelFunc, exists := a.activeRequests.LoadAndDelete(sessionID + "-summarize"); exists {
 		if cancel, ok := cancelFunc.(context.CancelFunc); ok {
-			slog.Info(fmt.Sprintf("Summarize cancellation initiated for session: %s", sessionID))
+			slog.Info("Summarize cancellation initiated", "session_id", sessionID)
 			cancel()
 		}
 	}
@@ -365,7 +365,7 @@ func (a *agent) processGeneration(ctx context.Context, sessionID, content string
 			})
 			titleErr := a.generateTitle(context.Background(), sessionID, content)
 			if titleErr != nil && !errors.Is(titleErr, context.Canceled) && !errors.Is(titleErr, context.DeadlineExceeded) {
-				slog.Error(fmt.Sprintf("failed to generate title: %v", titleErr))
+				slog.Error("failed to generate title", "error", titleErr)
 			}
 		}()
 	}
  
  
  
    
    @@ -248,7 +248,7 @@ func (a *anthropicClient) send(ctx context.Context, messages []message.Message,
 				return nil, retryErr
 			}
 			if retry {
-				slog.Warn(fmt.Sprintf("Retrying due to rate limit... attempt %d of %d", attempts, maxRetries))
+				slog.Warn("Retrying due to rate limit", "attempt", attempts, "max_retries", maxRetries)
 				select {
 				case <-ctx.Done():
 					return nil, ctx.Err()
@@ -401,7 +401,7 @@ func (a *anthropicClient) stream(ctx context.Context, messages []message.Message
 				return
 			}
 			if retry {
-				slog.Warn(fmt.Sprintf("Retrying due to rate limit... attempt %d of %d", attempts, maxRetries))
+				slog.Warn("Retrying due to rate limit", "attempt", attempts, "max_retries", maxRetries)
 				select {
 				case <-ctx.Done():
 					// context cancelled
  
  
  
    
    @@ -210,7 +210,7 @@ func (g *geminiClient) send(ctx context.Context, messages []message.Message, too
 				return nil, retryErr
 			}
 			if retry {
-				slog.Warn(fmt.Sprintf("Retrying due to rate limit... attempt %d of %d", attempts, maxRetries))
+				slog.Warn("Retrying due to rate limit", "attempt", attempts, "max_retries", maxRetries)
 				select {
 				case <-ctx.Done():
 					return nil, ctx.Err()
@@ -323,7 +323,7 @@ func (g *geminiClient) stream(ctx context.Context, messages []message.Message, t
 						return
 					}
 					if retry {
-						slog.Warn(fmt.Sprintf("Retrying due to rate limit... attempt %d of %d", attempts, maxRetries))
+						slog.Warn("Retrying due to rate limit", "attempt", attempts, "max_retries", maxRetries)
 						select {
 						case <-ctx.Done():
 							if ctx.Err() != nil {
  
  
  
    
    @@ -222,7 +222,7 @@ func (o *openaiClient) send(ctx context.Context, messages []message.Message, too
 				return nil, retryErr
 			}
 			if retry {
-				slog.Warn(fmt.Sprintf("Retrying due to rate limit... attempt %d of %d", attempts, maxRetries))
+				slog.Warn("Retrying due to rate limit", "attempt", attempts, "max_retries", maxRetries)
 				select {
 				case <-ctx.Done():
 					return nil, ctx.Err()
@@ -395,7 +395,7 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
 				return
 			}
 			if retry {
-				slog.Warn(fmt.Sprintf("Retrying due to rate limit... attempt %d of %d", attempts, maxRetries))
+				slog.Warn("Retrying due to rate limit", "attempt", attempts, "max_retries", maxRetries)
 				select {
 				case <-ctx.Done():
 					// context cancelled
  
  
  
    
    @@ -146,7 +146,7 @@ func globFiles(pattern, searchPath string, limit int) ([]string, bool, error) {
 		if err == nil {
 			return matches, len(matches) >= limit && limit > 0, nil
 		}
-		slog.Warn(fmt.Sprintf("Ripgrep execution failed: %v. Falling back to doublestar.", err))
+		slog.Warn("Ripgrep execution failed, falling back to doublestar", "error", err)
 	}
 
 	return fsext.GlobWithDoubleStar(pattern, searchPath, limit)
  
  
  
    
    @@ -90,7 +90,7 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc
 					slog.Debug("BaseURI", "baseURI", u)
 				}
 			default:
-				slog.Debug("GlobPattern", "unknown type", fmt.Sprintf("%T", v))
+				slog.Debug("GlobPattern unknown type", "type", fmt.Sprintf("%T", v))
 			}
 
 			// Log WatchKind
  
  
  
    
    @@ -1,7 +1,6 @@
 package main
 
 import (
-	"fmt"
 	"log/slog"
 	"net/http"
 	"os"
@@ -23,7 +22,7 @@ func main() {
 		go func() {
 			slog.Info("Serving pprof at localhost:6060")
 			if httpErr := http.ListenAndServe("localhost:6060", nil); httpErr != nil {
-				slog.Error(fmt.Sprintf("Failed to pprof listen: %v", httpErr))
+				slog.Error("Failed to pprof listen", "error", httpErr)
 			}
 		}()
 	}