Skip to content

feat: expose a library surface and JSON snapshot API for headless con…#133

Merged
graykode merged 3 commits into
graykode:mainfrom
XKHoshizora:feat/web-snapshot-api
Jun 8, 2026
Merged

feat: expose a library surface and JSON snapshot API for headless con…#133
graykode merged 3 commits into
graykode:mainfrom
XKHoshizora:feat/web-snapshot-api

Conversation

@XKHoshizora

@XKHoshizora XKHoshizora commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

What

Make abtop a lib + bin crate so local tools can reuse its data-collection
layer in-process — no re-scanning, no subprocesses, no terminal dependency — and
serialize the same state the TUI shows.

Why

I built abtop-web-ui, a local-first
web dashboard for abtop sessions. It currently depends on a fork because abtop is
binary-only. This PR upstreams the minimal library surface it needs, so it (and
other tools) can depend on abtop directly.

Changes

  • bin → lib: src/main.rs becomes a thin shim calling abtop::run(); the
    logic moves to src/lib.rs (a pure relocation).
  • App::tick_no_summaries(): refresh data without spawning claude --print,
    so headless consumers never spend the user's Claude quota. tick() is now
    tick_no_summaries() + drain_and_retry_summaries() — unchanged for the TUI.
  • src/snapshot.rs: App::to_snapshot(interval_ms) returns a JSON-friendly
    Snapshot DTO. Pure read; never ticks or spawns.
  • #[derive(Serialize)] on the model/host DTO types it serializes.
  • abtop --json: print one snapshot and exit.
  • Rustdoc for the public surface, a README "Library / JSON snapshot" section, and
    snapshot unit tests.

Safety / compatibility

  • The TUI, all existing flags, and output are unchanged.
  • No new dependenciesserde/serde_json are already in the tree.
  • No version bump (left to you).
  • cargo test: 164 passing (158 existing + 6 new) + 1 doctest.
  • Enum wire formats are documented as stable (SessionStatus"Thinking"…,
    chat roles → "user"/"assistant").

Happy to split this (e.g. drop --json, or land the bin→lib split separately),
gate serialization behind a Cargo feature, or adjust naming — whatever fits your
preferences. Thanks for abtop! 🙏

…sumers

abtop is binary-only today. This makes it a lib+bin crate so local tools can
reuse abtop's data-collection layer in-process — without reimplementing session
discovery, shelling out, or depending on the terminal frontend.

What changed:
- Split the entry point: src/main.rs becomes a thin shim that calls
  abtop::run(); all logic moves to src/lib.rs (a pure relocation).
- New App::tick_no_summaries(): refresh monitored data WITHOUT spawning
  `claude --print`, so headless consumers never touch the user's Claude quota.
  tick() is now tick_no_summaries() + drain_and_retry_summaries() — unchanged
  behavior for the TUI.
- New src/snapshot.rs: App::to_snapshot(interval_ms) returns a JSON-friendly
  Snapshot DTO (SessionView / McpServerView / ...). Pure read — never ticks
  or spawns.
- #[derive(Serialize)] on the model/host DTO types it serializes.
- New `abtop --json` flag: print one snapshot and exit.

Notes:
- The TUI, all existing flags, and output are unchanged.
- No new dependencies — serde and serde_json are already in the tree.
- snapshot.rs ships unit tests; all 164 tests + 1 doctest pass.
- Enum wire formats (SessionStatus as "Thinking"/..., chat roles as
  "user"/"assistant") are documented as stable.

Reference consumer: https://github.com/XKHoshizora/abtop-web-ui — a local-first
web dashboard built entirely on this API.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@XKHoshizora XKHoshizora marked this pull request as draft June 6, 2026 15:39
@XKHoshizora XKHoshizora marked this pull request as ready for review June 6, 2026 15:43

@graykode graykode left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security looks clean — no new dependencies or workflow changes, and the existing update shell/network path is only moved into the lib entrypoint.

Two things need fixing before this lands:

  • cargo clippy -- -D warnings fails now that collector is public from src/lib.rs; CodexCollector::new() and OpenCodeCollector::new() trigger clippy::new_without_default (--all-targets also catches ClaudeCollector). Either keep the collector module internal or add/allow the required defaults.
  • the new JSON snapshot exposes prompt-derived summary, chat_messages, full child commands, cwd/config roots, etc., but README privacy still says prompt text is never displayed. Please either remove/gate those fields from --json, or document the JSON privacy surface explicitly so scripts do not accidentally log transcript content.

I verified cargo test passes locally, and cargo run -- --demo --json produces valid JSON.

@graykode graykode left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security still looks clean. pushed a fix for the public collector clippy failures and documented the JSON snapshot privacy surface, with a regression test for the README wording. cargo build, cargo clippy --all-targets -- -D warnings, cargo test, and the demo JSON smoke check all pass locally.

@graykode graykode merged commit 7b9ae4e into graykode:main Jun 8, 2026
7 checks passed
@XKHoshizora

Copy link
Copy Markdown
Contributor Author

Thank you for the fast review — and for fixing both points directly!
The Default impls and the explicit JSON privacy docs are exactly right, and I appreciate you merging it (and shipping v0.4.8 so quickly). 🙏

For context:
abtop-web-ui is the reference consumer of this API — it serves the snapshot only behind a login + TLS and documents the same sensitive-field surface.

Now that this has landed, I wish switch it to depend on upstream abtop directly.

Thanks again for abtop!

XKHoshizora added a commit to XKHoshizora/abtop-web-ui that referenced this pull request Jun 8, 2026
The library API (App::to_snapshot, Snapshot, tick_no_summaries) was merged
upstream in graykode/abtop#133 and released in v0.4.8, so depend on it directly
via a git tag rather than the XKHoshizora/abtop fork.

- Cargo.toml: abtop -> { git = graykode/abtop, tag = v0.4.8 }
- release.yml: drop the fork sibling-checkout step (cargo fetches the git dep)
- README (EN + zh): build-from-source no longer needs a ../abtop sibling clone

Verified: cargo build pulls abtop v0.4.8 from git and links cleanly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants