all: cull dead code

Mostly from moving builds to use make.
diff --git a/dockerimg/dockerimg.go b/dockerimg/dockerimg.go
index 4cba98f..b8fbd98 100644
--- a/dockerimg/dockerimg.go
+++ b/dockerimg/dockerimg.go
@@ -615,84 +615,6 @@
 	return nil
 }
 
-func buildLinuxSketchBin(ctx context.Context) (string, error) {
-	// Detect if race detector is enabled and use a different cache path
-	raceEnabled := RaceEnabled()
-	cacheSuffix := ""
-	if raceEnabled {
-		cacheSuffix = "-race"
-	}
-
-	homeDir, err := os.UserHomeDir()
-	if err != nil {
-		return "", err
-	}
-
-	linuxGopath := filepath.Join(homeDir, ".cache", "sketch", "linuxgo"+cacheSuffix)
-	if err := os.MkdirAll(linuxGopath, 0o777); err != nil {
-		return "", err
-	}
-
-	// When race detector is enabled, use Docker to build the Linux binary
-	if raceEnabled {
-		return buildLinuxSketchBinWithDocker(ctx, linuxGopath)
-	}
-
-	// Standard non-race build using cross-compilation
-	// Change to directory containing dockerimg.go for module detection
-	_, codeFile, _, _ := runtime.Caller(0)
-	codeDir := filepath.Dir(codeFile)
-	if currentDir, err := os.Getwd(); err != nil {
-		slog.WarnContext(ctx, "could not get current directory", "err", err)
-	} else {
-		if err := os.Chdir(codeDir); err != nil {
-			slog.WarnContext(ctx, "could not change to code directory for module check", "err", err)
-		} else {
-			defer func() {
-				_ = os.Chdir(currentDir)
-			}()
-		}
-	}
-
-	verToInstall := "@latest"
-	if out, err := exec.Command("go", "list", "-m").CombinedOutput(); err != nil {
-		return "", fmt.Errorf("failed to run go list -m: %s: %v", out, err)
-	} else {
-		if strings.TrimSpace(string(out)) == "sketch.dev" {
-			slog.DebugContext(ctx, "built linux agent from currently checked out module")
-			verToInstall = ""
-		}
-	}
-
-	start := time.Now()
-	args := []string{"install"}
-	args = append(args, "sketch.dev/cmd/sketch"+verToInstall)
-
-	cmd := exec.CommandContext(ctx, "go", args...)
-	cmd.Env = append(
-		os.Environ(),
-		"GOOS=linux",
-		"CGO_ENABLED=0",
-		"GOTOOLCHAIN=auto",
-		"GOPATH="+linuxGopath,
-		"GOBIN=",
-	)
-
-	out, err := cmd.CombinedOutput()
-	if err != nil {
-		slog.ErrorContext(ctx, "go", slog.Duration("elapsed", time.Since(start)), slog.String("err", err.Error()), slog.String("path", cmd.Path), slog.String("args", fmt.Sprintf("%v", skribe.Redact(cmd.Args))))
-		return "", fmt.Errorf("failed to build linux sketch binary: %s: %w", out, err)
-	} else {
-		slog.DebugContext(ctx, "go", slog.Duration("elapsed", time.Since(start)), slog.String("path", cmd.Path), slog.String("args", fmt.Sprintf("%v", skribe.Redact(cmd.Args))))
-	}
-
-	if runtime.GOOS != "linux" {
-		return filepath.Join(linuxGopath, "bin", "linux_"+runtime.GOARCH, "sketch"), nil
-	}
-	// If we are already on Linux, there's no extra platform name in the path
-	return filepath.Join(linuxGopath, "bin", "sketch"), nil
-}
-
 func getContainerPort(ctx context.Context, cntrName, cntrPort string) (string, error) {
 	localAddr := ""
 	if out, err := combinedOutput(ctx, "docker", "port", cntrName, cntrPort); err != nil {
@@ -1054,111 +976,6 @@
 	return result
 }
 
-// buildLinuxSketchBinWithDocker builds the Linux sketch binary using Docker when race detector is enabled.
-// This avoids cross-compilation issues with CGO which is required for the race detector.
-// Mounts host Go module cache and build cache for faster subsequent builds.
-func buildLinuxSketchBinWithDocker(ctx context.Context, linuxGopath string) (string, error) {
-	// Find the git repo root
-	currentDir, err := os.Getwd()
-	if err != nil {
-		return "", fmt.Errorf("could not get current directory: %w", err)
-	}
-
-	gitRoot, err := findGitRoot(ctx, currentDir)
-	if err != nil {
-		return "", fmt.Errorf("could not find git root, cannot build with race detector outside a git repo: %w", err)
-	}
-
-	// Get host Go cache directories to mount for faster builds
-	goCacheDir, err := getHostGoCacheDir(ctx)
-	if err != nil {
-		return "", fmt.Errorf("failed to get host GOCACHE: %w", err)
-	}
-	goModCacheDir, err := getHostGoModCacheDir(ctx)
-	if err != nil {
-		return "", fmt.Errorf("failed to get host GOMODCACHE: %w", err)
-	}
-
-	slog.DebugContext(ctx, "building Linux sketch binary with race detector using Docker", "git_root", gitRoot, "gocache", goCacheDir, "gomodcache", goModCacheDir)
-
-	// Use the published Docker image tag
-	imageTag := dockerfileBaseHash()
-	imgName := fmt.Sprintf("%s:%s", dockerImgName, imageTag)
-
-	// Create destination directory for the binary
-	destPath := filepath.Join(linuxGopath, "bin")
-	if err := os.MkdirAll(destPath, 0o777); err != nil {
-		return "", fmt.Errorf("failed to create destination directory: %w", err)
-	}
-	destFile := filepath.Join(destPath, "sketch")
-
-	// Create a unique container name
-	containerID := fmt.Sprintf("sketch-race-build-%d", time.Now().UnixNano())
-
-	// Run a container with the repo mounted and Go caches for faster builds
-	start := time.Now()
-	slog.DebugContext(ctx, "running Docker container to build sketch with race detector")
-
-	// Use explicit output path for clarity
-	runArgs := []string{
-		"run",
-		"--name", containerID,
-		"-v", gitRoot + ":/app",
-		"-v", goCacheDir + ":/root/.cache/go-build",
-		"-v", goModCacheDir + ":/go/pkg/mod",
-		"-w", "/app",
-		imgName,
-		"sh", "-c", "cd /app && mkdir -p /tmp/sketch-out && go build -buildvcs=false -race -o /tmp/sketch-out/sketch sketch.dev/cmd/sketch",
-	}
-
-	out, err := combinedOutput(ctx, "docker", runArgs...)
-	if err != nil {
-		// Print the output to help with debugging
-		slog.ErrorContext(ctx, "docker run for race build failed",
-			slog.String("output", string(out)),
-			slog.String("error", err.Error()))
-		return "", fmt.Errorf("docker run failed: %s: %w", out, err)
-	}
-
-	slog.DebugContext(ctx, "built sketch with race detector in Docker", "elapsed", time.Since(start))
-
-	// Copy the binary from the container using the explicit path
-	out, err = combinedOutput(ctx, "docker", "cp", containerID+":/tmp/sketch-out/sketch", destFile)
-	if err != nil {
-		return "", fmt.Errorf("docker cp failed: %s: %w", out, err)
-	}
-
-	// Clean up the container
-	if out, err := combinedOutput(ctx, "docker", "rm", containerID); err != nil {
-		slog.WarnContext(ctx, "failed to remove container", "container", containerID, "error", err, "output", string(out))
-	}
-
-	// Make the binary executable
-	if err := os.Chmod(destFile, 0o755); err != nil {
-		return "", fmt.Errorf("failed to make binary executable: %w", err)
-	}
-
-	return destFile, nil
-}
-
-// getHostGoCacheDir returns the host's GOCACHE directory
-func getHostGoCacheDir(ctx context.Context) (string, error) {
-	out, err := exec.CommandContext(ctx, "go", "env", "GOCACHE").CombinedOutput()
-	if err != nil {
-		return "", fmt.Errorf("failed to get GOCACHE: %s: %w", out, err)
-	}
-	return strings.TrimSpace(string(out)), nil
-}
-
-// getHostGoModCacheDir returns the host's GOMODCACHE directory
-func getHostGoModCacheDir(ctx context.Context) (string, error) {
-	out, err := exec.CommandContext(ctx, "go", "env", "GOMODCACHE").CombinedOutput()
-	if err != nil {
-		return "", fmt.Errorf("failed to get GOMODCACHE: %s: %w", out, err)
-	}
-	return strings.TrimSpace(string(out)), nil
-}
-
 // copyEmbeddedLinuxBinaryToContainer copies the embedded linux binary to the container
 func copyEmbeddedLinuxBinaryToContainer(ctx context.Context, containerName string) error {
 	out, err := combinedOutput(ctx, "docker", "version", "--format", "{{.Server.Arch}}")
diff --git a/dockerimg/dockerimg_test.go b/dockerimg/dockerimg_test.go
index e15a81f..2b98c25 100644
--- a/dockerimg/dockerimg_test.go
+++ b/dockerimg/dockerimg_test.go
@@ -37,34 +37,6 @@
 	}
 }
 
-// TestGetHostGoCacheDirs tests that we can get the host Go cache directories
-func TestGetHostGoCacheDirs(t *testing.T) {
-	if !RaceEnabled() {
-		t.Skip("Race detector not enabled, skipping test")
-	}
-
-	ctx := context.Background()
-
-	goCacheDir, err := getHostGoCacheDir(ctx)
-	if err != nil {
-		t.Fatalf("getHostGoCacheDir failed: %v", err)
-	}
-	if goCacheDir == "" {
-		t.Error("GOCACHE is empty")
-	}
-
-	goModCacheDir, err := getHostGoModCacheDir(ctx)
-	if err != nil {
-		t.Fatalf("getHostGoModCacheDir failed: %v", err)
-	}
-	if goModCacheDir == "" {
-		t.Error("GOMODCACHE is empty")
-	}
-
-	t.Logf("GOCACHE: %s", goCacheDir)
-	t.Logf("GOMODCACHE: %s", goModCacheDir)
-}
-
 // TestCreateCacheKey tests the cache key generation
 func TestCreateCacheKey(t *testing.T) {
 	key1 := createCacheKey("image1", "/path1")
diff --git a/dockerimg/racedetector.go b/dockerimg/racedetector.go
deleted file mode 100644
index 6bcb754..0000000
--- a/dockerimg/racedetector.go
+++ /dev/null
@@ -1,10 +0,0 @@
-//go:build !race
-
-// Package dockerimg provides functionality for creating and managing Docker images.
-package dockerimg
-
-// RaceEnabled returns whether the race detector is enabled.
-// This function will always return false when compiled without the race detector.
-func RaceEnabled() bool {
-	return false
-}
diff --git a/dockerimg/racedetector_race.go b/dockerimg/racedetector_race.go
deleted file mode 100644
index 90cd251..0000000
--- a/dockerimg/racedetector_race.go
+++ /dev/null
@@ -1,10 +0,0 @@
-//go:build race
-
-// Package dockerimg provides functionality for creating and managing Docker images.
-package dockerimg
-
-// RaceEnabled returns whether the race detector is enabled.
-// This function will always return true when compiled with the race detector.
-func RaceEnabled() bool {
-	return true
-}
diff --git a/llm/llm.go b/llm/llm.go
index 9718954..3893522 100644
--- a/llm/llm.go
+++ b/llm/llm.go
@@ -263,14 +263,3 @@
 		Text: text,
 	}}
 }
-
-// ImageContent creates an image content for tool results.
-// MediaType should be "image/jpeg" or "image/png"
-func ImageContent(text string, mediaType string, base64Data string) []Content {
-	return []Content{{
-		Type:      ContentTypeText,
-		Text:      text,
-		MediaType: mediaType,
-		Data:      base64Data,
-	}}
-}
diff --git a/webui/esbuild.go b/webui/esbuild.go
index 1588f06..9c0f41c 100644
--- a/webui/esbuild.go
+++ b/webui/esbuild.go
@@ -103,11 +103,6 @@
 	return nil
 }
 
-func ZipPath() (string, error) {
-	_, hashZip, err := zipPath()
-	return hashZip, err
-}
-
 // TODO: This path being /root/.cache/sketch/webui/skui-....zip means that the Dockerfile
 // in createdockerfile.go needs to create the parent directory. Ideally we bundle the built webui
 // into the binary and avoid this altogether.
diff --git a/webui/memfs.go b/webui/memfs.go
deleted file mode 100644
index 5431862..0000000
--- a/webui/memfs.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package webui
-
-import (
-	"bytes"
-	"fmt"
-	"io/fs"
-	"time"
-)
-
-// memFS implements fs.FS in-memory.
-type memFS struct {
-	m map[string][]byte
-}
-
-func (m memFS) Open(name string) (fs.File, error) {
-	b, found := m.m[name]
-	if !found {
-		return nil, fmt.Errorf("esbuild.memFS(%q): %w", name, fs.ErrNotExist)
-	}
-	return &memFile{name: name, Reader: *bytes.NewReader(b)}, nil
-}
-
-func (m memFS) ReadFile(name string) ([]byte, error) {
-	b, found := m.m[name]
-	if !found {
-		return nil, fmt.Errorf("esbuild.memFS.ReadFile(%q): %w", name, fs.ErrNotExist)
-	}
-	return append(make([]byte, 0, len(b)), b...), nil
-}
-
-// memFile implements fs.File in-memory.
-type memFile struct {
-	// embedding is very important here because need more than
-	// Read, we need Seek to make http.ServeContent happy.
-	bytes.Reader
-	name string
-}
-
-func (f *memFile) Stat() (fs.FileInfo, error) { return &memFileInfo{f: f}, nil }
-func (f *memFile) Close() error               { return nil }
-
-var start = time.Now()
-
-type memFileInfo struct {
-	f *memFile
-}
-
-func (i memFileInfo) Name() string       { return i.f.name }
-func (i memFileInfo) Size() int64        { return i.f.Reader.Size() }
-func (i memFileInfo) Mode() fs.FileMode  { return 0o444 }
-func (i memFileInfo) ModTime() time.Time { return start }
-func (i memFileInfo) IsDir() bool        { return false }
-func (i memFileInfo) Sys() any           { return nil }