OpenAdapt Capture
[!IMPORTANT] Status: Experimental. OpenAdapt Capture records native mouse, keyboard, and screen activity into a time-aligned local capture session. Its current product role is the optional cross-platform desktop recorder used by
openadapt-flow.The OpenAdapt product is the demonstration compiler,
openadapt-flow, installed via theOpenAdaptlauncher (pip install openadapt): it compiles a demonstrated GUI workflow into a deterministic, locally executable program. Healthy runs make no model calls, and it halts instead of guessing when verification fails. Lifecycle labels for every repository are in the repository lifecycle registry.
Cross-platform local desktop recording: native mouse, keyboard, and screen activity captured into a time-aligned local session that the compiler turns into deterministic replay input. Local-first by default; a raw capture never leaves the machine unless you run an explicit opt-in command.
Start with the OpenAdapt documentation if you want to record, compile, verify, and replay a workflow.
The OpenAdapt stack
OpenAdapt is a governed demonstration compiler: record a workflow once, compile the recording into a deterministic program, and replay that program with zero model calls on the healthy path. When the live screen does not match what was demonstrated it halts instead of guessing, using identity gates and independent effect verification. Every substrate is first-class: web and desktop recording are validated, RDP and Windows replay are early, and Citrix is exploratory.
| Package | Role |
|---|---|
openadapt |
Launcher and installer (pip install openadapt) |
openadapt-flow |
Records, compiles, verifies, and replays workflows |
openadapt-capture |
Cross-platform local desktop recording (this package) |
openadapt-types |
Canonical action and UI-state schema |
openadapt-grounding |
Local OCR text-anchoring plus optional model grounding |
openadapt-privacy |
PHI/PII detection and redaction |
Documentation for the whole stack lives at docs.openadapt.ai.
Where it fits
| Recording path | Current implementation |
|---|---|
| Windows and RDP demonstrations | openadapt-capture records native input and action-gated screen video; openadapt-flow converts the session into compiler input. |
| Browser demonstrations | openadapt-flow records its Playwright browser directly. It does not require this package. |
| Chrome extension in this repository | Experimental DOM-capture code for development; it is not the supported web recorder or governed replay path. |
The browser path stays inside openadapt-flow because the compiler needs
ordered before/after frames, page state, secret-field redaction, and events in
its own recording format. The extension captures useful DOM context, but it
does not provide that end-to-end contract.
Use it with OpenAdapt
Install the compiler with the optional native recorder:
pip install "openadapt-flow[capture]"
Record a desktop demonstration, then compile it:
openadapt-flow record --backend windows --out recording --task "Describe the workflow"
# Perform the workflow, then press Ctrl-C.
openadapt-flow compile recording --out bundle --name my-workflow
Use --backend rdp when recording inside the RDP client pixel space. Replay
setup and substrate-specific requirements are documented in the
openadapt-flow desktop recording guide.
Use it as a library
Install the capture package directly:
pip install openadapt-capture
Record from the command line:
capture record ./my-capture --description "Describe the workflow"
# Press Ctrl-C to stop.
capture info ./my-capture
Or inspect processed actions in Python:
from openadapt_capture import CaptureSession
with CaptureSession.load("./my-capture") as capture:
for action in capture.actions():
print(action.timestamp, action.type, action.x, action.y)
frame = action.screenshot
A capture normally contains:
my-capture/
├── recording.db
├── oa_recording-*.mp4
└── profiling.json
Video remains the default evidence format. Capture streams in-memory RGB frames
directly to a separately provisioned FFmpeg executable while recording. Missing
integer PTS slots reuse the preceding frame, so encoding is deterministic and
independent of scheduler or queue latency. A compact MP4 metadata box retains
the logical capture-frame timestamps used by nearest-frame extraction. Capture
then verifies and atomically promotes the MP4; no intermediate screenshot
sequence is written. Capture never downloads, bundles, or links FFmpeg/PyAV. Set
OPENADAPT_FFMPEG_PATH, pass Recorder(ffmpeg_path=...), use Desktop's
user-data ffmpeg.json provision manifest, or place ffmpeg and ffprobe on
PATH. Recording performs a real encode-and-decode probe and refuses before
input listeners start if the selected executable, codec, or PNG verification
path is unavailable. A minimal managed runtime must provide raw-video input
through a pipe, the selected video encoder, MP4 demuxing/muxing, PNG
decoding/encoding, the image2pipe muxer, and the select video filter;
Desktop provisions and probes that exact closure.
Window-scoped recording
Status: implemented and unit-proven on all CI platforms; live-validated
end to end on macOS (frames, translated coordinates, bounds timeline, and
video verified against a real window on a real display). Windows uses a
Win32 + mss region grab and is exercised by the same unit suite; its live
smoke test awaits an interactive Windows desktop. Not yet validated against
a Parallels/Citrix client window specifically.
By default the recorder captures the full screen. Window-scoped mode records
ONE window in that window's own pixel space. This is the mode built for
remote-display demonstrations (Parallels, Citrix Workspace, Microsoft Remote
Desktop), where openadapt-flow's rdp_window replay drives the client
window's pixels directly. Recording scoped to the same window removes the
full-screen-vs-window coordinate mismatch at the source:
from openadapt_capture import Recorder
with Recorder(
"./my-capture",
task_description="Demonstrate the workflow",
window={"owner": "Parallels", "title": None}, # substring match
) as recorder:
input("Perform the task, then press Enter...")
owner matches the application (macOS: window owner name; Windows: process
executable name) and title optionally disambiguates among its windows; both
are case-insensitive substrings, mirroring how openadapt-flow's
remote-display backend identifies the same window at replay time. The
selectors can also be set via config/environment
(RECORD_WINDOW_OWNER / RECORD_WINDOW_TITLE).
In this mode:
- Frames are the target window's pixels. macOS captures the window's own
buffer (
CGWindowListCreateImage, the identical call flow's replay uses); Windows grabs the window's screen region, so keep the window unoccluded. - Input coordinates are translated at capture time into the captured
frame's pixel space (
pixel = (global_point - window_origin) * scale, the exact inverse of the replay mapping). Input outside the window records out-of-range coordinates rather than being silently clamped. - The window scoping is persisted: the recording's config JSON carries the
target, resolved window, initial bounds, scale, and viewport
(
CaptureSession.window_capture), and the window is re-resolved every frame with bounds changes recorded as window events, a bounds timeline converters can use to be exact even when the window moves. - Fail-loud guarantees: recording refuses to start if the window cannot be resolved and captured; input arriving before the first frame is discarded with a warning instead of being recorded in the wrong coordinate space; a mid-recording window resize skips unencodable video frames loudly (screenshots and the bounds timeline stay exact), so avoid resizing the target during a demonstration.
Note for converters: window-mode coordinates are already in captured-frame
pixels (coordinate_space == "window_pixels"); do not rescale them by
pixel_ratio.
Data and privacy boundary
A raw capture can contain everything visible on screen and everything typed, including credentials, personal data, or protected health information. Keep the entire capture directory inside its approved local boundary and apply an appropriate retention policy.
Capture does not upload a session by default. The sharing command, remote
transcription, and profiling transfer are explicit opt-in operations. Installing
the privacy extra alone does not automatically scrub a recording.
The current desktop-to-Flow conversion has no field geometry for reliable
secret redaction and no live UIA locator. openadapt-flow therefore refuses its
desktop --secret option, and converted desktop workflows rely on retained
visual evidence unless a separate structural recording path arms them. Review
the desktop guide before recording sensitive workflows.
The experimental Chrome extension can observe pages across its configured host permissions and can emit DOM text and keyboard events to a local WebSocket. Treat it as development code; do not deploy it in a sensitive browser profile.
Current limitations
- Native recording requires a visible user session plus the operating system's screen-recording and input-monitoring permissions.
- Desktop capture records pixels and coordinates, not a structural accessibility locator for each demonstrated target.
- The Flow adapter rejects unsupported input such as drag, non-left-click, and modifier-chord actions instead of silently compiling an incomplete workflow.
- Browser-extension installation, security hardening, and compiler integration are not part of the current product path.
See the organization-wide
repository lifecycle registry
and openadapt-flow product status
for the evidence behind current maturity labels.
Optional extras
| Extra | Adds |
|---|---|
transcribe-fast |
Local faster-whisper transcription |
transcribe |
Local openai-whisper transcription |
privacy |
openadapt-privacy dependency for explicit integrations; no automatic scrubbing |
share |
Explicit Magic Wormhole transfer |
all |
All optional dependencies |
Development
uv sync --dev
uv run pytest -m "not slow"
Slow native-capture tests require a visible session and operating-system permissions:
uv run pytest -m slow
License
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file openadapt_capture-1.0.4.tar.gz.
File metadata
- Download URL: openadapt_capture-1.0.4.tar.gz
- Upload date:
- Size: 12.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
990b93ed81f58c55ae0b5ee2dd09bcf1714740e7d995768d119ca742fb2ce9fc
|
|
| MD5 |
477a1617ea6808ba107926a19d7710b8
|
|
| BLAKE2b-256 |
9eb7d7002739f0eca1bcdaa748c4e47154b8c0c785387ae3f1f584d13f8062e1
|
Provenance
The following attestation bundles were made for openadapt_capture-1.0.4.tar.gz:
Publisher:
release.yml on OpenAdaptAI/openadapt-capture
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openadapt_capture-1.0.4.tar.gz -
Subject digest:
990b93ed81f58c55ae0b5ee2dd09bcf1714740e7d995768d119ca742fb2ce9fc - Sigstore transparency entry: 2229976236
- Sigstore integration time:
-
Permalink:
OpenAdaptAI/openadapt-capture@c11969b7efd2eaaf9981d853fbe62d2bdaddd953 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/OpenAdaptAI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c11969b7efd2eaaf9981d853fbe62d2bdaddd953 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file openadapt_capture-1.0.4-py3-none-any.whl.
File metadata
- Download URL: openadapt_capture-1.0.4-py3-none-any.whl
- Upload date:
- Size: 185.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a5e93317e054f5faef6dd88ce9a50878770b16cffca97e21d59e6c171b4c6808
|
|
| MD5 |
06860f81bf8745aec0b9605d901c871c
|
|
| BLAKE2b-256 |
253931677da3654aae8671c80abcca51ac805bf3331e62d95aa1c825a274dfb1
|
Provenance
The following attestation bundles were made for openadapt_capture-1.0.4-py3-none-any.whl:
Publisher:
release.yml on OpenAdaptAI/openadapt-capture
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openadapt_capture-1.0.4-py3-none-any.whl -
Subject digest:
a5e93317e054f5faef6dd88ce9a50878770b16cffca97e21d59e6c171b4c6808 - Sigstore transparency entry: 2229977147
- Sigstore integration time:
-
Permalink:
OpenAdaptAI/openadapt-capture@c11969b7efd2eaaf9981d853fbe62d2bdaddd953 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/OpenAdaptAI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c11969b7efd2eaaf9981d853fbe62d2bdaddd953 -
Trigger Event:
workflow_dispatch
-
Statement type: