harn web
harn web <subcommand> [options]Standalone Next.js dashboard for .harnery/ state. See concepts / web UI for the feature tour.
Subcommands
Section titled “Subcommands”harn web up [--port 4276] [--coord-root <dir>] [--prod] [--no-fetch] [--max-old-space <mb>]harn web build [--no-fetch]harn web start [--port 4276] [--coord-root <dir>] [--no-fetch] [--max-old-space <mb>]harn web performance [--coord-root <dir>] [--since 1h] [--limit 20] [--json]Boot the dashboard. Dev mode by default (HMR, no build needed). With --prod, runs next start (requires a prior web build).
harn web up# → http://localhost:4276
harn web up --port 4000 --coord-root /path/to/some/repo# → http://localhost:4000, reading .harnery/ from /path/to/some/repoProduce the production bundle:
harn web buildRuns next build against harnery/web/. Output lands in harnery/web/.next/.
Start the production server (requires prior build):
harn web build && harn web startMemory
Section titled “Memory”up and start pin a V8 old-space ceiling of 2048 MB by default.
Without it, Next picks its own ceiling at roughly half of system RAM. On a large machine that is a limit a dashboard will never reach, so V8 never feels enough pressure to run a major GC, and a server left up for days settles at a multi-gigabyte working set that is mostly collectable garbage. On one 32 GB machine a dev server sat at 7.9 GB after three days; the same server under the default ceiling held at 1.7 GB, and the production build held at 0.4 GB.
Raise it, lower it, or opt out entirely:
harn web up --max-old-space 4096 # roomier ceilingHARNERY_WEB_MAX_OLD_SPACE=1024 harn web upharn web up --max-old-space 0 # opt out; Next sizes it againPrecedence is flag, then HARNERY_WEB_MAX_OLD_SPACE, then the default. A ceiling you set yourself in NODE_OPTIONS is always left alone.
For a dashboard that stays up, prefer build + start over up: the production server carries no bundler state, no source maps, and no HMR machinery, which is most of the difference.
Performance diagnostics
Section titled “Performance diagnostics”harn web up and harn web start record request timing, event-loop delays,
memory samples, and long garbage-collection pauses to
.harnery/logs/web-performance.jsonl. The recorder runs below Next.js, so it
covers pages, route handlers, React Server Component refreshes, and requests
that spend most of their time in framework compilation.
Query strings, headers, request bodies, and response bodies are never logged. Framework static assets are excluded. The active log rotates at 5 MB and keeps three backups, which bounds the default footprint at about 20 MB.
Run the summary when the dashboard feels slow:
harn web performanceharn web performance --since 30m --limit 10The report ranks routes by maximum and p95 duration, lists individual slow requests, and lists the largest event-loop delays with the requests that overlapped them. It also reports current and peak heap, RSS, external memory, array-buffer memory, garbage-collection counts, total collection time, and the longest pauses. A large request duration with little event-loop delay points toward asynchronous I/O or framework compilation. A large event-loop delay with no matching garbage-collection pause points toward synchronous filesystem or CPU work, or a descheduled process. It is evidence about overlap, not proof that one listed request caused the delay.
The server also prints a short warning when a request crosses 1,000 ms or the event loop is delayed by at least 250 ms. These environment variables tune the recorder without changing the log schema:
| Environment variable | Default | Effect |
|---|---|---|
HARNERY_WEB_SLOW_REQUEST_MS |
1000 |
Slow-request warning threshold |
HARNERY_WEB_EVENT_LOOP_DELAY_MS |
250 |
Event-loop delay warning threshold |
HARNERY_WEB_MEMORY_SAMPLE_MS |
30000 |
Memory and garbage-collection summary interval |
HARNERY_WEB_GC_PAUSE_MS |
100 |
Long garbage-collection warning threshold |
HARNERY_WEB_PERFORMANCE_LOG_MAX_BYTES |
5242880 |
Bytes per log generation |
HARNERY_WEB_PERFORMANCE_LOG_BACKUPS |
3 |
Rotated generations to retain |
Restart the webserver after changing a recorder setting. Diagnostics begin on the first request handled by the restarted process.
Dashboard startup also ensures the optional local resource observer
is running on supported machines. The observer supplies the /resources page
with process CPU deltas and agent process-tree attribution. A failed observer
launch is logged as a warning and never prevents the dashboard from starting.
First-run fetch (npm installs)
Section titled “First-run fetch (npm installs)”The npm package omits the dashboard to keep the CLI lean. When web/ is absent (a plain npm i -g harnery), the first harn web up fetches it:
- Clones the harnery repo at the matching version tag (
v<your version>) into~/.cache/harnery/web/<ref>/. - Installs the web app’s deps there (just
web/; no root install, no browser downloads). - Boots it. Later runs reuse the cache, so only the first launch pays the cost.
| Flag / env | Effect |
|---|---|
--no-fetch |
Skip the fetch; print manual clone steps instead. Works on build / start too. |
HARNERY_WEB_REF=<ref> |
Fetch a specific git ref instead of the version tag (e.g. next, a branch). |
The fetched dashboard matches your installed harnery version, so it stays in sync with the coord schema the CLI writes.
Networking
Section titled “Networking”Localhost-only by default. For cross-device access (phone, second laptop), pair with harn tunnel:
harn web up &harn tunnel up --target 127.0.0.1:4276harn tunnel runs an IP-gated reverse-proxy in front of a Cloudflare quick tunnel; see harn tunnel for the allowlist + setup story.
Coord root resolution
Section titled “Coord root resolution”The dashboard resolves .harnery/ from, in order:
--coord-root <dir>flagHARNERY_COORD_ROOTenv var- Walk up from cwd looking for a
.harnery/directory (up to 8 levels)