From 26d691c6cd90b9428f9db296c4944c07b2c5a13f Mon Sep 17 00:00:00 2001 From: gaoruilin Date: Tue, 8 Sep 2026 15:18:59 +0900 Subject: [PATCH 1/2] crawl-text: static About section + portfolio backlink on the demo page The Pages demo is a Vite SPA, so the raw HTML that non-JS fetchers see was 93 chars of text. LLM crawlers and answer-engine fetchers generally do not execute JS, which made the landing page effectively blank for them. Add a real "About AgentXRay" section to frontend/index.html, placed after #root so React cannot overwrite it on mount. It is ordinary visible page content, not hidden markup: the page now scrolls past the dashboard to reach it. #root is pinned to one viewport (100dvh) so the dashboard itself looks and behaves exactly as before, and its scroll panes get overscroll-behavior: contain so they no longer drag the page along. Content is drawn from README.md and frontend/public/llms-full.txt: what the tool is, the seven registered log-format adapters with their default directories, the per-turn token/cost/time ledger, the npx install command, and the fact that this deployment runs on synthetic sample logs. No new numbers beyond claims.json. The section footer carries the repo link, the npm package and a link to the portfolio hub at https://alloevil.github.io/projects/. Built text length (frontend/dist/index.html, scripts and styles stripped): 93 -> 2402 chars. --- frontend/index.html | 65 ++++++++++++++++++++++++++++++++++++++++++ frontend/src/index.css | 60 +++++++++++++++++++++++++++++++++++--- 2 files changed, 121 insertions(+), 4 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index dba1577..47991e6 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -39,6 +39,71 @@
+ +
+
+

AgentXRay — read the session logs your AI coding agents already write

+

+ AgentXRay is a local-first web dashboard that reads and visualizes the session logs your AI + coding agents already write to disk, for developers who want to see what those agents + actually did. It is a single Node.js + Express server plus this React UI, pointed at the log + directories your existing agent CLIs already use. It is a reader, not a tracing SDK: there + is nothing to instrument, no API key, no hosted backend, and no data leaves the machine it + runs on. +

+

Agent log formats it reads

+

+ Seven on-disk session-log formats have a registered adapter and are normalized into a single + model, so one interface covers every agent you run: +

+
    +
  • OpenClaw — ~/.openclaw/agents
  • +
  • Codex — ~/.codex/sessions
  • +
  • Claude Code — ~/.claude/projects
  • +
  • OMP (oh-my-pi) — ~/.omp/agent/sessions
  • +
  • DeepSeek Harness — ~/.dsh/sessions
  • +
  • Gemini CLI — ~/.gemini/tmp
  • +
  • Hermes — ~/.hermes/state.db
  • +
+

+ Six of the seven store JSONL; Hermes stores SQLite. The authoritative list is the + PLATFORMS registry in lib/platforms/index.js, and adding a format + takes one adapter file plus one line in that table. +

+

The per-turn ledger

+

+ Each session is replayed as a turn-by-turn transcript. Tool calls are paired with the + results they returned, so any call expands to show its arguments and its output. Token + usage and cost are summed per user turn, and a turn's elapsed time is split into model + inference versus tool execution — so a slow turn tells you whether the model was thinking + or a tool was blocking. Around that sit aggregate analytics over tool calls, error clusters + and token spend, the real human prompts recovered from the logs (including ones from + sessions an agent's own cleanup has already deleted), full-text search across every + platform at once, and a prompt library that installs the keepers as native slash commands. +

+

Install

+

Run it from npm without installing anything, then open the port it prints:

+
npx @alloevil/agent-xray
+# then open http://localhost:3800
+

+ Requires Node.js 22.13 or newer. MIT licensed. This GitHub Pages page is a demo build + running against synthetic sample logs committed in the repository — it contains no real + sessions, so treat it as a UI tour. Run the command above to point it at your own. +

+ +
+
diff --git a/frontend/src/index.css b/frontend/src/index.css index 6db1b21..9254610 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -51,17 +51,69 @@ * { @apply border-border; } - html, - body, - #root { + html { height: 100%; } body { - @apply text-foreground font-sans antialiased overflow-hidden; + min-height: 100%; + } + /* + * The dashboard still owns exactly one viewport; the page scrolls past it to + * reach the static #about section that lives after #root in index.html. + */ + #root { + height: 100vh; + height: 100dvh; + } + /* Keep the dashboard's own scroll panes from dragging the page along. */ + #root * { + overscroll-behavior: contain; + } + body { + @apply text-foreground font-sans antialiased; /* legacy background: two radial glows over --bg */ background: radial-gradient(circle at top left, rgba(31, 111, 235, 0.14), transparent 28%), radial-gradient(circle at bottom right, rgba(35, 134, 54, 0.12), transparent 30%), hsl(var(--background)); + background-attachment: fixed; + } +} + +/* + * Static "About AgentXRay" section. Its markup lives in index.html, after + * #root, so React cannot own it and neither can a component stylesheet. + */ +@layer components { + #about { + @apply border-t border-border px-6 py-10 text-sm leading-relaxed text-muted-foreground; + background: hsl(var(--panel-alt)); + } + #about > div { + @apply mx-auto flex max-w-3xl flex-col gap-4; + } + #about h2 { + @apply text-lg font-semibold text-foreground; + } + #about h3 { + @apply pt-2 text-base font-semibold text-foreground; + } + #about ul { + @apply grid gap-1 sm:grid-cols-2; + } + #about code { + @apply rounded bg-secondary px-1 py-0.5 font-mono text-xs text-foreground; + } + #about pre { + @apply overflow-x-auto rounded border border-border bg-card p-3 font-mono text-xs; + } + #about pre code { + @apply bg-transparent p-0; + } + #about a { + @apply text-primary underline-offset-2 hover:underline; + } + #about footer { + @apply flex flex-wrap gap-x-4 gap-y-1 border-t border-border pt-4; } } From 7cbffa9d3287a86c9e2840695d597f58e2667ee7 Mon Sep 17 00:00:00 2001 From: gaoruilin Date: Tue, 8 Sep 2026 15:35:24 +0900 Subject: [PATCH 2/2] crawl-text: drop overscroll containment, it trapped the wheel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up review question turned up a real defect in my own change. The overscroll-behavior: contain rule was meant to stop the dashboard's scroll panes from dragging the page when they hit their end. It also applies to every other scroll container, including the overflow-hidden layout wrappers, and it blocks the scroll chain even when a pane has nothing to scroll. Measured on the built page at 1440x900, where the sample data does not overflow any pane: wheeling over the centre of the app moved the page 0px with the rule in place, and 1000px with it neutralised. The About section was present, laid out and reachable only by scrollbar or keyboard — that is exactly the present-but-unreachable shape this pass exists to avoid. Default chaining is the honest behaviour: panes scroll normally, and once exhausted the wheel carries on to the page and reveals #about. --- frontend/src/index.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/index.css b/frontend/src/index.css index 9254610..657c7d8 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -60,15 +60,15 @@ /* * The dashboard still owns exactly one viewport; the page scrolls past it to * reach the static #about section that lives after #root in index.html. + * Scroll chaining is left at the default on purpose: `overscroll-behavior: + * contain` on the inner panes blocks the chain even when a pane has nothing + * to scroll, which traps the wheel over most of the dashboard and makes + * #about unreachable by the one gesture a visitor will actually try. */ #root { height: 100vh; height: 100dvh; } - /* Keep the dashboard's own scroll panes from dragging the page along. */ - #root * { - overscroll-behavior: contain; - } body { @apply text-foreground font-sans antialiased; /* legacy background: two radial glows over --bg */