sketch: exclude internal processes (headless-chrome) from port monitoring

Add SKETCH_IGNORE_PORTS environment variable to headless-shell browser processes
and modify port monitoring to exclude processes with this variable.

Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: sff3b145df27ee3bek
diff --git a/loop/port_monitor.go b/loop/port_monitor.go
index 7eaa98f..14869da 100644
--- a/loop/port_monitor.go
+++ b/loop/port_monitor.go
@@ -4,7 +4,9 @@
 	"context"
 	"fmt"
 	"log/slog"
+	"os"
 	"sort"
+	"strings"
 	"sync"
 	"time"
 
@@ -178,6 +180,11 @@
 		return
 	}
 
+	// Skip processes with SKETCH_IGNORE_PORTS environment variable
+	if pm.shouldIgnoreProcess(port.Pid) {
+		return
+	}
+
 	// TODO: Structure this so that UI can display it more nicely.
 	content := fmt.Sprintf("Port %s: %s:%d", event, port.Proto, port.Port)
 	if port.Process != "" {
@@ -244,3 +251,28 @@
 	}
 	return removed
 }
+
+// shouldIgnoreProcess checks if a process should be ignored based on its environment variables.
+func (pm *PortMonitor) shouldIgnoreProcess(pid int) bool {
+	if pid <= 0 {
+		return false
+	}
+
+	// Read the process environment from /proc/[pid]/environ
+	envFile := fmt.Sprintf("/proc/%d/environ", pid)
+	envData, err := os.ReadFile(envFile)
+	if err != nil {
+		// If we can't read the environment, don't ignore the process
+		return false
+	}
+
+	// Parse the environment variables (null-separated)
+	envVars := strings.Split(string(envData), "\x00")
+	for _, envVar := range envVars {
+		if envVar == "SKETCH_IGNORE_PORTS=1" {
+			return true
+		}
+	}
+
+	return false
+}