Propose a change
Name Last commit message Last updated
bin Publish 0.23.12 1d ago
dev-skills Publish 0.23.11 1d ago
hooks Publish 0.23.2 4d ago
publish-skills Publish 0.8.1 18d ago
screenshots Publish 0.8.0 18d ago
skills Publish 0.19.0 4d ago
src Publish 0.23.12 1d ago
tools Publish 0.23.7 3d ago
build.sh Publish 0.4.1 27d ago
Cargo.lock Publish 0.23.12 1d ago
Cargo.toml Publish 0.23.12 1d ago
install.sh Publish 0.8.1 18d ago
LICENSE Publish 0.4.3 26d ago
package.json Publish 0.23.12 1d ago
page.json Publish 0.23.12 1d ago
README.md Publish 0.22.0 4d ago
SKILL.md Publish 0.23.12 1d ago
uninstall.sh Publish 0.4.0 27d ago
VERSION Publish 0.23.12 1d ago

adom-shotlog

See the shots your AI never showed you.

Your AI screenshots your app constantly while it builds and tests, but it is text-centric, so those shots get buried in tool output and you never actually see them. adom-shotlog is the fix: a tiny Rust CLI plus server where any AI thread drops each screenshot into a channel, and you watch them stream into a live, newest-first gallery, on whatever surface you are using: a Hydrogen webview, a pup window, your native browser, or your phone.

Install

adompkg install adom/adom-shotlog

The CLI installs as adom-shotlog (with a back-compat shotlog alias).

One central broker, many AI threads

There is one shotlog server per container, and the same binary is both the server and the CLI. adom-shotlog serve spawns the broker on port 8820; inject, open, viewers, and channels are CLI verbs that talk to it.

Every AI thread in the container simply runs adom-shotlog inject, which posts to that one local server. So the server is a central broker: it owns every channel, tracks every viewer (which surface, and whether it is actually on-screen), and manages all the viewer surfaces. Many threads can be sending you shots at once, each into its own channel, and the broker keeps a live view/tab for each. Run adom-shotlog channels to see the whole picture: every channel, its shot count, when it last updated, and who is watching right now.

Disk stays bounded automatically: each channel keeps its newest 200 shots on disk (SHOTLOG_MAX_SHOTS), older files are deleted as new ones arrive, and channels idle for 30 days are pruned entirely (SHOTLOG_RETENTION_DAYS, 0 disables).

The read-hook: every screenshot any AI reads, captured automatically

shotlog ships a Claude Code PostToolUse(Read) hook (hooks/shotlog-on-read.sh). Once installed, whenever ANY AI thread reads an image file to analyze it, the hook automatically injects that exact image into the shared read-captures channel. You see every screenshot every AI looked at, deterministically, with zero AI cooperation required. It is the purest form of the shotlog mission: the AI cannot forget to show you what it saw.

adom-shotlog install deploys the hook and registers it in ~/.claude/settings.json (surgically, never touching your other hooks), and every serve startup re-verifies both, healing them if missing, so the pipeline cannot silently rot. The hook also self-heals the broker if it is not running.

Related guarantees: the broker is single-instance per port (a second serve detects the healthy broker and defers gracefully, warning if versions differ), and read-captures stays disk-bounded by the retention policy.

It adapts to your surface

shotlog notices which surface is watching a channel and behaves accordingly. It never steals your OS foreground.

Webview (the default in Hydrogen): a slim 20% right-side panel

The nicest setup, and the default when you run inside Hydrogen: a ~20%-wide webview panel pinned to the right of your workspace. Open it that way:

adom-shotlog open -c my-project --skinny        # a ~20% right-side column
  • It auto-updates live over a WebSocket: the moment any thread injects a shot, the card appears at the top of that channel, no refresh, no polling.
  • One panel, shotlog's own tabs: the viewer is a single app that manages a tab per channel itself (read-captures pinned first as the global auto-capture feed). New shots flash their tab orange, show an unseen badge, and (by default) auto-switch to the updated channel - all inside the app, no workspace tab juggling.
  • If a shot lands in a channel with nobody watching, the broker auto-opens the slim 20% webview for it, so a shot is never logged invisibly. (Opt out with SHOTLOG_NO_FORCE_OPEN=1.)
  • The layout is fully fluid at that skinny width: the header wraps to rows, the child-window thumbnails reflow, and the outer page never shows a horizontal scrollbar.

Phone

Ask your AI to shotlog the whole thing, and it hands you one URL. Open that URL on your phone and watch every step stream in as it happens, then scroll back through the whole run whenever you want.

adom-shotlog on a phone

The layout adapts to the narrow screen, and while the tab is backgrounded the page title shows a ● N unseen-shots badge so you know something arrived. Combined with /remote-control, you can kick off real work from anywhere and keep vibe-coding from the passenger seat.

Pup and plain browser

Pup is the full-browser canvas: zooming a card uses nearly the whole screen, so fine text is readable (the skinny webview can never zoom past its panel width). Or just click the Pup button in the viewer header: every webview shows it, and it switches that channel to a full pup window (the pup view shows a Webview button to switch back). The button checks whether pup is available first; if Adom Desktop isn't installed it tells you how to get it (pup is a default bridge that auto-installs with Adom Desktop). Your AI can do the same switch with one command: shotlog open -c <ch> --pup --swap (opens a tab in the shared shotlog pup window and closes the webview tab). shotlog leaves your foreground alone; the gentle cue is an automatic orange taskbar flash on updates. In any plain browser tab, the same live gallery and unseen-shots title badge apply.

Is a human actually seeing it?

An AI injecting shots into a channel nobody is watching is worse than useless, because it thinks it showed you something. So shotlog answers this in the inject response and lets a thread gate on it:

adom-shotlog viewers -c my-project   # exit 0 = a human has it on-screen, 4 = open but backgrounded, 3 = nobody

The signal is authoritative: each viewer holds a WebSocket open and reports its surface (webview, pup, mobile, browser) and whether it is actually on-screen (Page Visibility) versus a background tab.

It refuses to log a shot blind

adom-shotlog always records the original capture resolution, so the gallery never shows a mystery size. It shows 1400x788, orig 1920x1080. Resizing before inject is expected (oversized images crash AI vision analysis), so most screenshot tools hand back a shrunk copy. shotlog just requires the original size to travel with it, via --orig-w/--orig-h, --orig-file, --native, or --meta.

Killer feature: a whole parent + child-window array in one card

A window capture is often not one image. A window with a dropdown, an autofill list, a confirm bubble, or a native dialog open is really a parent window with child windows: separate owned windows that a plain screenshot of the main window misses entirely.

Adom Desktop captures them for you. desktop_screenshot_window {hwnd} returns the parent image PLUS every child window in a screenshots[] array (with ownedPopupCount), each carrying its own hwnd, title, kind, rect, and coordMap. Pass that whole response to shotlog with --meta:

adom-shotlog inject -c checkout -d "checkout form, autofill dropdown + confirm dialog open" primary.png --meta ad-response.json

shotlog renders the entire array on one card, no zoom needed:

A parent window plus its child windows, shown inline

  • a +N child windows badge on the card,
  • a child windows row directly under the parent shot, every child window inline as its own thumbnail (labeled kind, title, WxH),
  • an ⓘ meta chip that reveals the coordMap panel inline (shotId, screenRect, dpiScale, imageToScreen, screen resolution), copyable as JSON.

So one desktop_screenshot_window call, one --meta inject, and you see the whole window story: the form, the dropdown it opened, and the dialog it raised, all in a single card. Child-window PNGs are stored beside the parent and are excluded from the gallery as standalone shots. Plain single-image injects (no --meta) are unchanged; child windows are purely additive.

CLI reference

Command Description
adom-shotlog inject Inject a screenshot into a channel (records the original resolution; --meta adds child windows; reports whether a human is watching)
adom-shotlog open Open the gallery as a Hydrogen webview tab (--skinny for the 20% right panel)
adom-shotlog viewers Is a human watching a channel? Exit 0 / 4 / 3, plus connected surfaces
adom-shotlog channels Overview of every channel: shots, last activity, and who is watching
adom-shotlog serve Start the HTTP server / broker (port 8820)
adom-shotlog health Check if the server is running
adom-shotlog install Install the skill, bash completions, and the shotlog alias

Skill pack

Installing adom-shotlog also deploys its bundled skills (see the Skills tab):

  • adom-shotlog-surfacing (user): surfacing a shot gently per surface, never stealing foreground.
  • adom-shotlog-child-windows (user): capturing a parent window plus its child windows via --meta.
  • adom-shotlog-dev (dev): build/deploy, the central-broker architecture, and the layout rules (ralph-test the skinny view, no outer-html scrollbars, pretty scrollbars).
  • adom-shotlog-publishing (publish): publishing this package to wiki.adom.inc.

Dependencies

Dependency Required? Why
adom-cli For the webview adom-shotlog open adds the gallery as a Hydrogen webview tab and the broker manages it.
adom-desktop Optional AI agents use it to capture screenshots (and child-window arrays) that get injected. Humans can Ctrl+V paste instead.

No adompkg package dependencies. adom-shotlog is a self-contained Rust binary.