sketch: Propagate host vs. runtime OS/WorkingDir/Hostname

If you have a bunch of sketch sessions, you need to know where they were
launched. The container hostnames (some random thing) and working dirs (always /app)
aren't very helpful, so we want to keep around both. I've updated the UI
to show them as well.

This commit chooses "Host" and "Runtime" as the names of the "Outside"
and "Inside" sketch. I'm open to suggestions for better names.

Co-Authored-By: sketch, but it did a so-so job
diff --git a/loop/agent.go b/loop/agent.go
index a14d244..2bd0776 100644
--- a/loop/agent.go
+++ b/loop/agent.go
@@ -73,6 +73,10 @@
 
 	// OS returns the operating system of the client.
 	OS() string
+	HostOS() string
+	HostHostname() string
+	HostWorkingDir() string
+	GitOrigin() string
 }
 
 type CodingAgentMessageType string
@@ -235,6 +239,12 @@
 	originalBudget ant.Budget
 	title          string
 	codereview     *claudetool.CodeReviewer
+	// Host information
+	hostHostname   string
+	hostOS         string
+	hostWorkingDir string
+	// URL of the git remote 'origin' if it exists
+	gitOrigin string
 
 	// Time when the current turn started (reset at the beginning of InnerLoop)
 	startOfTurn time.Time
@@ -284,6 +294,26 @@
 	return a.config.ClientGOOS
 }
 
+// HostOS returns the operating system of the host.
+func (a *Agent) HostOS() string {
+	return a.hostOS
+}
+
+// HostHostname returns the hostname of the host.
+func (a *Agent) HostHostname() string {
+	return a.hostHostname
+}
+
+// HostWorkingDir returns the working directory on the host.
+func (a *Agent) HostWorkingDir() string {
+	return a.hostWorkingDir
+}
+
+// GitOrigin returns the URL of the git remote 'origin' if it exists.
+func (a *Agent) GitOrigin() string {
+	return a.gitOrigin
+}
+
 // SetTitle sets the title of the conversation.
 func (a *Agent) SetTitle(title string) {
 	a.mu.Lock()
@@ -411,6 +441,10 @@
 	ClientGOOS       string
 	ClientGOARCH     string
 	UseAnthropicEdit bool
+	// Host information
+	HostHostname   string
+	HostOS         string
+	HostWorkingDir string
 }
 
 // NewAgent creates a new Agent.
@@ -424,6 +458,9 @@
 		startedAt:      time.Now(),
 		originalBudget: config.Budget,
 		seenCommits:    make(map[string]bool),
+		hostHostname:   config.HostHostname,
+		hostOS:         config.HostOS,
+		hostWorkingDir: config.HostWorkingDir,
 	}
 	return agent
 }
@@ -488,6 +525,8 @@
 			return fmt.Errorf("Agent.Init: claudetool.NewCodeReviewer: %w", err)
 		}
 		a.codereview = codereview
+
+		a.gitOrigin = getGitOrigin(ctx, ini.WorkingDir)
 	}
 	a.lastHEAD = a.initialCommit
 	a.convo = a.initConvo()
@@ -1133,3 +1172,16 @@
 
 	return true
 }
+
+// getGitOrigin returns the URL of the git remote 'origin' if it exists
+func getGitOrigin(ctx context.Context, dir string) string {
+	cmd := exec.CommandContext(ctx, "git", "config", "--get", "remote.origin.url")
+	cmd.Dir = dir
+	stderr := new(strings.Builder)
+	cmd.Stderr = stderr
+	out, err := cmd.Output()
+	if err != nil {
+		return ""
+	}
+	return strings.TrimSpace(string(out))
+}