Adom Shotlog
Public Made by Adomby adom
See the shots your AI never showed you, and know it actually SAW them. adom-shotlog streams every screenshot the AI gathers into a live gallery (webview/pup/browser/phone), reports whether a human is
| Name | Last updated |
|---|---|
| bin | 1d ago |
| dev-skills | 1d ago |
| hooks | 4d ago |
| publish-skills | 18d ago |
| screenshots | 18d ago |
| skills | 4d ago |
| src | 1d ago |
| tools | 3d ago |
| build.sh | 27d ago |
| Cargo.lock | 1d ago |
| Cargo.toml | 1d ago |
| install.sh | 18d ago |
| LICENSE | 26d ago |
| package.json | 1d ago |
| page.json | 1d ago |
| README.md | 4d ago |
| SKILL.md | 1d ago |
| uninstall.sh | 27d ago |
| VERSION | 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.

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 +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.