You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Starting go-code prints 13 lines of undifferentiated gray text in which the one line that matters is indistinguishable from the twelve that do not. Real output from a failed start:
[go-code] no server at http://127.0.0.1:8080, starting harnessd on port 8080
[go-code] waiting for server to become healthy (pid 9900)...
2026/09/08 06:45:44 loaded model catalog with 15 providers
2026/09/08 06:45:44 provider catalog: 15 files, added 4 providers and 59 models
2026/09/08 06:45:44 note: rates not expressible in USD per million tokens, so excluded from cost totals: kimi-subscription
2026/09/08 06:45:44 pricing resolver wired from model catalog (fallback)
2026/09/08 06:45:44 loaded 4 skill(s)
2026/09/08 06:45:44 embedded cron scheduler started (db: .harness/cron.db)
2026/09/08 06:45:44 delayed callbacks enabled
2026/09/08 06:45:44 callback run persistence enabled: .harness/runs.db
2026/09/08 06:45:44 hot-reload watcher started (interval: 5s, dirs: ...)
2026/09/08 06:45:44 fatal: refusing to start: :8080 listens beyond this machine but no authentication is configured, so anyone who can reach the port could start agent runs with this daemon's credentials. Configure an API key store, or set HARNESS_AUTH_DISABLED=true to accept an open daemon deliberately, or set HARNESS_ADDR=127.0.0.1:8080 to listen locally only
[go-code] ERROR: harnessd (pid 9900) exited before becoming healthy on port 8080. ...
Three separate voices — the wrapper, the daemon's boot log, and a fatal error — share one visual channel with no separation. The single actionable line (fatal:) is buried in the middle, wraps across the full terminal width as an unbroken paragraph, and carries no more emphasis than delayed callbacks enabled.
On success, the boot log is pure noise in front of someone who asked for a TUI. Worse, in TUI mode harnessd inherits stdout, so a daemon log line emitted after the TUI starts rendering can scribble directly into the interface.
This is the first thing every user sees, on every launch, from the project's primary entry point.
Protected path
Entry point: go-code (or go-code "prompt", --server, --resume <id>, or a CLI subcommand) in scripts/go-code.sh.
Current path that must keep working: main resolves the port from HARNESS_ADDR -> health-checks http://127.0.0.1:${port} -> if unhealthy, start_server() spawns harnessd in the background, writes PID_FILE, sets STARTED_BY_US=1, and polls /healthz for up to 10 s -> on success dispatches to harnesscli for the chosen mode -> the stop_server EXIT trap stops the daemon only when the wrapper started it. --server mode deliberately clears the trap and leaves the daemon running.
Failure and recovery behavior that must be preserved exactly:
harnesscli's exit code propagates unchanged through the wrapper, including when the EXIT trap runs (pinned by TestGoCodeScriptPropagatesHarnessCLIExitCode; documented in website/docs/reference/exit-codes.md).
A pre-existing server is never stopped.
A port held by a foreign process relocates to a free port unless HARNESS_ADDR was explicit.
The daemon's failure reason must remain visible to the user — currently by inheriting stdout.
Acceptance contract
Wrapper output is visually distinct from daemon output by severity: informational, warning, and error lines are each recognizable at a glance.
On a successful start, the daemon's boot log does not appear in the terminal. The wrapper reports readiness in a few lines and hands off to the TUI or prompt.
On a failed start, the daemon's log is shown, and the operative line (fatal: / panic: / the last error) is visually emphasized rather than buried mid-block.
No daemon log line can render into the TUI after handoff.
Color is suppressed when output is not a terminal, when NO_COLOR is set (https://no-color.org), or when TERM=dumb. Piping go-code runs | cat yields no escape sequences.
Severity is never conveyed by color alone — the WARN: / ERROR: words remain in the text, so the output stays readable for colorblind users, on monochrome terminals, and in captured logs.
Exit codes, the EXIT trap, port relocation, and --server behavior are unchanged.
The daemon log remains retrievable after a successful start (the user can still investigate), not discarded.
Current architecture and search evidence
Owning file: scripts/go-code.sh. There is no color or output-formatting infrastructure in it today — the entire surface is three one-line helpers at :65-67:
Searches run: grep -n 'tput|\\033|\\e\[|NO_COLOR|isatty|-t 1' scripts/go-code.sh — no matches, confirming nothing to reuse or conflict with. grep -n 'server|stop_server|exec |tui' scripts/go-code.sh — mapped the lifecycle cited under Protected path.
start_server() (:183) spawns with no redirection, so harnessd inherits the wrapper's stdout and stderr. That single fact causes both the boot-log noise and the TUI-scribbling hazard.
Callers/consumers searched: cmd/harnesscli/go_code_script_test.go is the only automated consumer of the script (three tests, stubbing curl/harnessd/harnesscli on PATH). Two of them assert on recorded harnesscli arguments and process exit codes; none assert on the wrapper's human-readable stdout, so the message format is currently unpinned.
Prior art in-repo for the log-capture pattern: scripts/run-bench-smoke.sh:135-141 and scripts/soak.sh:271-277 both redirect harnessd to a LOG_FILE and report the path. This slice should follow that existing convention rather than invent a new one.
Cross-surface impact map
Callers and data flow: start_server() and the three output helpers in scripts/go-code.sh. No Go code changes.
Config/env/defaults: adds recognition of the de-facto standard NO_COLOR and TERM=dumb. No new project config keys. HARNESS_ADDR semantics unchanged.
API/CLI/wire formats/tools: none. No routes, flags, events, or tool signatures change. The wrapper's own --help text gains a line about color/log behavior.
Persistence/schema/cache: a daemon log file under ${TMPDIR:-/tmp}, alongside the existing PID_FILE written there. No project-directory writes, no schema.
Concurrency/lifecycle/cancellation/retries: the background spawn, PID_FILE, health-check loop, and stop_server EXIT trap keep their current structure. Redirection changes where the daemon's file descriptors point, not the process lifecycle. The dead-PID detection inside the health loop must keep working, and must now surface the captured log rather than relying on the user having seen inherited output.
Security/auth/permissions/privacy: the daemon log is written to a temp path readable by its owner; it contains catalog and provider names but no key material (verified against the observed startup output). Create it with restrictive permissions and do not place it in the shared project tree.
TUI/web/macOS/other clients: net improvement for the TUI — capturing the daemon's stream removes the existing hazard of log lines rendering into the interface. macapp/scripts/live-harnessd.sh and live-test.sh manage their own daemons and are untouched. harness-acp connects to an existing daemon and is untouched.
Provider/model/tool catalog: none.
Deployment/observability/runbooks: website/docs/cli/go-code-wrapper.md needs the log-path and color behavior. Observability improves — the daemon log becomes a durable file instead of scrollback.
Compatibility: anyone scraping the wrapper's stdout for the daemon boot log loses it from the terminal, but gains a stable file path. No such consumer exists in-tree (searched). Escape sequences never appear in non-TTY output, so pipelines are unaffected.
Existing tests/fixtures: the three tests in cmd/harnesscli/go_code_script_test.go run the script through exec.Command with no TTY, so color must be off there by construction — a useful built-in guard. Their stub harnessd writes nothing, so redirection cannot break them.
Entry and exit: unchanged commands. The change is what the terminal shows between invocation and handoff.
Target successful start (from 13 lines to 3):
[go-code] starting harnessd on port 8080
[go-code] server ready at http://127.0.0.1:8080
log: /tmp/harnessd.9900.log
Target failed start — daemon log shown, cause emphasized, wrapper's own error last:
[go-code] starting harnessd on port 8080
[go-code] ERROR: harnessd (pid 9900) exited before becoming healthy on port 8080
harnessd said:
... last lines of context, dimmed ...
fatal: refusing to start: :8080 listens beyond this machine but no
authentication is configured, ...
full log: /tmp/harnessd.9900.log
States:
Loading: the existing "waiting for server to become healthy" line, unchanged in meaning.
Success: readiness line plus log path.
Error: the block above. Long daemon messages must be indented rather than left to wrap as an unbroken paragraph against the terminal edge.
Partial: a healthy server that was already running keeps its current "server already running" line, with no log path (the wrapper does not own that daemon and cannot know its log).
Empty: not applicable.
Keyboard, focus, motion: none — non-interactive output. No spinners or animation; they corrupt piped output and add nothing to a sub-second wait.
Light/dark: use only the 8 standard ANSI colors, which terminals remap to their own theme. Do not hardcode 256-color or truecolor values, which can become invisible on a light background.
Accessibility: severity words remain in the text (contract point 6). Color is an enhancement, never the sole signal.
Copy and destructive-action confirmation: no destructive actions. Copy stays lowercase-technical, matching the existing wrapper voice.
Responsive/native behavior: indentation must be a fixed small amount, not computed against $COLUMNS, so output is stable when the terminal is resized or the stream is captured.
Real interaction QA path: run go-code in a normal terminal with a free port and confirm the clean success path and TUI launch; force a failure (occupy the port with a foreign process, or point at a daemon that will refuse to start) and confirm the error block; run go-code runs | cat and confirm no escape sequences; run with NO_COLOR=1 and confirm plain text.
In scope
Color helpers in scripts/go-code.sh with TTY, NO_COLOR, and TERM=dumb detection.
Severity styling for info/warn/die.
Redirecting the wrapper-started harnessd to a log file, following the run-bench-smoke.sh / soak.sh convention.
Showing the captured log, with the operative line emphasized, when startup fails.
Reporting the log path on success.
Tests pinning the non-TTY (no-escape-sequence) contract and the on-failure log surfacing.
website/docs/cli/go-code-wrapper.md and an engineering-log entry.
Out of scope
Colorizing harnessd's own Go log output (cmd/harnessd). That is a separate surface with its own consumers — systemd journals, CI logs, macapp, the benchmark scripts — and must not be changed to serve one wrapper's presentation.
Changing what harnessd logs at startup, or introducing a quiet/verbose level in the daemon.
The TUI's own rendering.
scripts/soak.sh, scripts/smoke-test.sh, scripts/run-bench-smoke.sh — non-interactive, already redirect, no reason to restyle.
Log rotation or cleanup policy for the daemon log beyond writing it to the system temp directory.
Any change to exit codes or the EXIT trap.
Coordination and dependencies
Depends on #1411 / PR #1412, which is in flight and modifies the same start_server() function and the same die call site. This slice must branch from main after #1412 merges, or it will conflict. No other open work touches scripts/go-code.sh.
Test-first plan
All tests go in the existing cmd/harnesscli/go_code_script_test.go, reusing its stub-on-PATH harness.
TestGoCodeScriptEmitsNoAnsiWhenNotATty — run the script via exec.Command (no TTY by construction) and assert the combined output contains no \x1b[ sequence. Red first by adding unconditional color, or by asserting against a deliberately-colored temporary build; the durable value is preventing a later regression that colors unconditionally. This test also implicitly covers NO_COLOR, so add an explicit NO_COLOR=1 case for the documented contract.
TestGoCodeScriptSurfacesHarnessdLogOnStartupFailure — stub harnessd to print a recognizable fatal line and exit non-zero; stub curl to always fail the health check. Assert the wrapper's stderr contains that fatal line and the log path. Red before the change: with redirection added but no surfacing, the fatal text would be captured to a file and lost from the terminal — this test is what proves the fix does not trade one invisibility for another.
Expected failures prove: (1) that styling is conditional rather than unconditional, and (2) that capturing the daemon's output does not hide the reason it died.
False-positive controls: keep all three existing wrapper tests green to prove routing, exit-code propagation, and the loopback bind from #1411 are untouched.
Verification plan
Red: run both new tests before the implementation; record output.
Green: go test ./cmd/harnesscli -run TestGoCodeScript -race -v — five tests.
Targeted: bash -n scripts/go-code.sh, plus shellcheck -S warning scripts/go-code.sh if available in CI.
Integration: bash scripts/run-bench-smoke.sh (key-free, fake provider) to prove sibling scripts and the daemon's own logging are unaffected.
Full regression: go test ./cmd/... ./internal/... (note go build ./... fails on pre-existing benchmarks/terminal_bench/reference_solutions/* fixtures that declare package main with no func main; unrelated to this slice).
Real path, required because this is a presentation change that no unit test can fully judge: run scripts/install.sh, then exercise all four states in a real terminal — clean success into the TUI, forced startup failure, | cat piping, and NO_COLOR=1 — and inspect the rendered result rather than only the exit status. Attach the terminal output to the PR.
Adjacent callers: confirm go-code --server still prints its URL and leaves the daemon running, and that go-code runs still exits 0.
Rollout and rollback
Single PR to main; users pick it up on the next brew install --HEAD or ./scripts/install.sh. No migration, no persisted state beyond a temp log file, no coordination with a running service.
Rollback trigger: escape sequences appearing in piped or captured output, or a startup failure whose cause is no longer visible in the terminal. Rollback is reverting the commit; nothing to repair, since the daemon log file is disposable and the previous behavior returns immediately.
Documentation and handoff
website/docs/cli/go-code-wrapper.md: the daemon log path, that the boot log no longer prints on success, and the NO_COLOR / non-TTY behavior.
docs/logs/engineering-log.md: entry recording the symptom (unreadable startup output, actionable line buried), the cause (no severity distinction, and the daemon inheriting stdout), and the fix.
No runbook covers wrapper startup presentation, so none needs updating.
Definition of done
Both new tests written first and observed failing
Success path reduced to a few lines; boot log no longer printed on success
Failure path shows the daemon log with the operative line emphasized and the full log path
No escape sequences when not a TTY, when NO_COLOR is set, or when TERM=dumb
Severity still readable without color
Exit codes, EXIT trap, port relocation, and --server behavior unchanged and proven
All five wrapper tests green under -race; bench smoke green
Real terminal QA done across success, failure, piped, and NO_COLOR states, with output attached to the PR
Work type
Feature slice
Change class
User-facing feature
Why this matters
Starting
go-codeprints 13 lines of undifferentiated gray text in which the one line that matters is indistinguishable from the twelve that do not. Real output from a failed start:Three separate voices — the wrapper, the daemon's boot log, and a fatal error — share one visual channel with no separation. The single actionable line (
fatal:) is buried in the middle, wraps across the full terminal width as an unbroken paragraph, and carries no more emphasis thandelayed callbacks enabled.Two distinct costs:
go-codecannot start — wrapper binds harnessd to :PORT and the bind guard refuses it #1411 I watched a second, unrelated failure (callback workspace is already owned) scroll past in the same undifferentiated block and it took a re-read to spot.harnessdinherits stdout, so a daemon log line emitted after the TUI starts rendering can scribble directly into the interface.This is the first thing every user sees, on every launch, from the project's primary entry point.
Protected path
Entry point:
go-code(orgo-code "prompt",--server,--resume <id>, or a CLI subcommand) inscripts/go-code.sh.Current path that must keep working:
mainresolves the port fromHARNESS_ADDR-> health-checkshttp://127.0.0.1:${port}-> if unhealthy,start_server()spawnsharnessdin the background, writesPID_FILE, setsSTARTED_BY_US=1, and polls/healthzfor up to 10 s -> on success dispatches toharnessclifor the chosen mode -> thestop_serverEXIT trap stops the daemon only when the wrapper started it.--servermode deliberately clears the trap and leaves the daemon running.Failure and recovery behavior that must be preserved exactly:
harnesscli's exit code propagates unchanged through the wrapper, including when the EXIT trap runs (pinned byTestGoCodeScriptPropagatesHarnessCLIExitCode; documented inwebsite/docs/reference/exit-codes.md).HARNESS_ADDRwas explicit.Acceptance contract
fatal:/panic:/ the last error) is visually emphasized rather than buried mid-block.NO_COLORis set (https://no-color.org), or whenTERM=dumb. Pipinggo-code runs | catyields no escape sequences.WARN:/ERROR:words remain in the text, so the output stays readable for colorblind users, on monochrome terminals, and in captured logs.--serverbehavior are unchanged.Current architecture and search evidence
Owning file:
scripts/go-code.sh. There is no color or output-formatting infrastructure in it today — the entire surface is three one-line helpers at:65-67:Searches run:
grep -n 'tput|\\033|\\e\[|NO_COLOR|isatty|-t 1' scripts/go-code.sh— no matches, confirming nothing to reuse or conflict with.grep -n 'server|stop_server|exec |tui' scripts/go-code.sh— mapped the lifecycle cited under Protected path.start_server()(:183) spawns with no redirection, soharnessdinherits the wrapper's stdout and stderr. That single fact causes both the boot-log noise and the TUI-scribbling hazard.Callers/consumers searched:
cmd/harnesscli/go_code_script_test.gois the only automated consumer of the script (three tests, stubbingcurl/harnessd/harnessclionPATH). Two of them assert on recordedharnesscliarguments and process exit codes; none assert on the wrapper's human-readable stdout, so the message format is currently unpinned.Prior art in-repo for the log-capture pattern:
scripts/run-bench-smoke.sh:135-141andscripts/soak.sh:271-277both redirectharnessdto aLOG_FILEand report the path. This slice should follow that existing convention rather than invent a new one.Cross-surface impact map
Callers and data flow:
start_server()and the three output helpers inscripts/go-code.sh. No Go code changes.Config/env/defaults: adds recognition of the de-facto standard
NO_COLORandTERM=dumb. No new project config keys.HARNESS_ADDRsemantics unchanged.API/CLI/wire formats/tools: none. No routes, flags, events, or tool signatures change. The wrapper's own
--helptext gains a line about color/log behavior.Persistence/schema/cache: a daemon log file under
${TMPDIR:-/tmp}, alongside the existingPID_FILEwritten there. No project-directory writes, no schema.Concurrency/lifecycle/cancellation/retries: the background spawn,
PID_FILE, health-check loop, andstop_serverEXIT trap keep their current structure. Redirection changes where the daemon's file descriptors point, not the process lifecycle. The dead-PID detection inside the health loop must keep working, and must now surface the captured log rather than relying on the user having seen inherited output.Security/auth/permissions/privacy: the daemon log is written to a temp path readable by its owner; it contains catalog and provider names but no key material (verified against the observed startup output). Create it with restrictive permissions and do not place it in the shared project tree.
TUI/web/macOS/other clients: net improvement for the TUI — capturing the daemon's stream removes the existing hazard of log lines rendering into the interface.
macapp/scripts/live-harnessd.shandlive-test.shmanage their own daemons and are untouched.harness-acpconnects to an existing daemon and is untouched.Provider/model/tool catalog: none.
Deployment/observability/runbooks:
website/docs/cli/go-code-wrapper.mdneeds the log-path and color behavior. Observability improves — the daemon log becomes a durable file instead of scrollback.Compatibility: anyone scraping the wrapper's stdout for the daemon boot log loses it from the terminal, but gains a stable file path. No such consumer exists in-tree (searched). Escape sequences never appear in non-TTY output, so pipelines are unaffected.
Existing tests/fixtures: the three tests in
cmd/harnesscli/go_code_script_test.gorun the script throughexec.Commandwith no TTY, so color must be off there by construction — a useful built-in guard. Their stubharnessdwrites nothing, so redirection cannot break them.Documentation:
website/docs/cli/go-code-wrapper.md,docs/logs/engineering-log.md.Product and UX contract
Entry and exit: unchanged commands. The change is what the terminal shows between invocation and handoff.
Target successful start (from 13 lines to 3):
Target failed start — daemon log shown, cause emphasized, wrapper's own error last:
States:
Keyboard, focus, motion: none — non-interactive output. No spinners or animation; they corrupt piped output and add nothing to a sub-second wait.
Light/dark: use only the 8 standard ANSI colors, which terminals remap to their own theme. Do not hardcode 256-color or truecolor values, which can become invisible on a light background.
Accessibility: severity words remain in the text (contract point 6). Color is an enhancement, never the sole signal.
Copy and destructive-action confirmation: no destructive actions. Copy stays lowercase-technical, matching the existing wrapper voice.
Responsive/native behavior: indentation must be a fixed small amount, not computed against
$COLUMNS, so output is stable when the terminal is resized or the stream is captured.Real interaction QA path: run
go-codein a normal terminal with a free port and confirm the clean success path and TUI launch; force a failure (occupy the port with a foreign process, or point at a daemon that will refuse to start) and confirm the error block; rungo-code runs | catand confirm no escape sequences; run withNO_COLOR=1and confirm plain text.In scope
scripts/go-code.shwith TTY,NO_COLOR, andTERM=dumbdetection.info/warn/die.harnessdto a log file, following therun-bench-smoke.sh/soak.shconvention.website/docs/cli/go-code-wrapper.mdand an engineering-log entry.Out of scope
harnessd's own Gologoutput (cmd/harnessd). That is a separate surface with its own consumers — systemd journals, CI logs,macapp, the benchmark scripts — and must not be changed to serve one wrapper's presentation.harnessdlogs at startup, or introducing a quiet/verbose level in the daemon.scripts/soak.sh,scripts/smoke-test.sh,scripts/run-bench-smoke.sh— non-interactive, already redirect, no reason to restyle.Coordination and dependencies
Depends on #1411 / PR #1412, which is in flight and modifies the same
start_server()function and the samediecall site. This slice must branch frommainafter #1412 merges, or it will conflict. No other open work touchesscripts/go-code.sh.Test-first plan
All tests go in the existing
cmd/harnesscli/go_code_script_test.go, reusing its stub-on-PATH harness.TestGoCodeScriptEmitsNoAnsiWhenNotATty— run the script viaexec.Command(no TTY by construction) and assert the combined output contains no\x1b[sequence. Red first by adding unconditional color, or by asserting against a deliberately-colored temporary build; the durable value is preventing a later regression that colors unconditionally. This test also implicitly coversNO_COLOR, so add an explicitNO_COLOR=1case for the documented contract.TestGoCodeScriptSurfacesHarnessdLogOnStartupFailure— stubharnessdto print a recognizable fatal line and exit non-zero; stubcurlto always fail the health check. Assert the wrapper's stderr contains that fatal line and the log path. Red before the change: with redirection added but no surfacing, the fatal text would be captured to a file and lost from the terminal — this test is what proves the fix does not trade one invisibility for another.Expected failures prove: (1) that styling is conditional rather than unconditional, and (2) that capturing the daemon's output does not hide the reason it died.
False-positive controls: keep all three existing wrapper tests green to prove routing, exit-code propagation, and the loopback bind from #1411 are untouched.
Verification plan
go test ./cmd/harnesscli -run TestGoCodeScript -race -v— five tests.bash -n scripts/go-code.sh, plusshellcheck -S warning scripts/go-code.shif available in CI.bash scripts/run-bench-smoke.sh(key-free, fake provider) to prove sibling scripts and the daemon's own logging are unaffected.go test ./cmd/... ./internal/...(notego build ./...fails on pre-existingbenchmarks/terminal_bench/reference_solutions/*fixtures that declarepackage mainwith nofunc main; unrelated to this slice).scripts/install.sh, then exercise all four states in a real terminal — clean success into the TUI, forced startup failure,| catpiping, andNO_COLOR=1— and inspect the rendered result rather than only the exit status. Attach the terminal output to the PR.go-code --serverstill prints its URL and leaves the daemon running, and thatgo-code runsstill exits 0.Rollout and rollback
Single PR to
main; users pick it up on the nextbrew install --HEADor./scripts/install.sh. No migration, no persisted state beyond a temp log file, no coordination with a running service.Rollback trigger: escape sequences appearing in piped or captured output, or a startup failure whose cause is no longer visible in the terminal. Rollback is reverting the commit; nothing to repair, since the daemon log file is disposable and the previous behavior returns immediately.
Documentation and handoff
website/docs/cli/go-code-wrapper.md: the daemon log path, that the boot log no longer prints on success, and theNO_COLOR/ non-TTY behavior.docs/logs/engineering-log.md: entry recording the symptom (unreadable startup output, actionable line buried), the cause (no severity distinction, and the daemon inheriting stdout), and the fix.Definition of done
NO_COLORis set, or whenTERM=dumb--serverbehavior unchanged and proven-race; bench smoke greenNO_COLORstates, with output attached to the PR