Skip to main content

clicked

ci

Prove what one browser interaction actually did -- every network request it made, and optionally what changed on a local backing store.

receipt proves what a shell command touched. custody proves what an AI agent's tool call touched. clicked proves what a click touched -- the same "verified execution, not just self-report" idea, one layer up: a browser-automation test that asserts "clicking Save sends the right request" is trusting the test's own assumption unless something independently recorded what the browser actually sent.

from clicked import capture

with capture(page, task="click save button") as c:
    page.click("#save")
    page.wait_for_timeout(200)

print(c.to_dict())
{
  "providence_version": 1,
  "tool": "clicked",
  "payload": {
    "task": "click save button",
    "seconds": 0.324,
    "requests": [
      {"url": "http://127.0.0.1:60672/api/save", "method": "POST",
       "post_data": "{\"name\":\"ada\"}", "status": 200, "failure": null}
    ],
    "raised": null
  },
  "sha256": "ed727efcdccbc..."
}

(Real output, from tests/test_capture_live.py -- a real headless Chromium, clicking a real button, against a real local HTTP server.)

Install

pip install clicked-evidence

For once, no PyPI name-squatting to work around -- both clicked and clicked-evidence were actually free.

Use

capture() takes any Playwright Page object and a task description. Everything inside the with block is one interaction:

from clicked import capture

with capture(page, task="delete account button") as c:
    page.click("#delete-account-button")
    page.wait_for_load_state("networkidle")

c.write("receipt.json")   # a Providence bundle -- see below

c.requests is every network request/response pair that happened during the block (URL, method, POST body, status, or a failure reason if the request never got a response at all). This is what was actually sent and actually came back -- not what the page's own JavaScript claims it sent.

Redaction

url and post_data are swept through receipt.redact before being stored -- a real interaction routinely carries a credential in a query string (?api_key=...) or a form/JSON POST body ({"password": "..."}), and a receipt is meant to be kept and handed to someone else as evidence, not a second place that credential now lives. Same regex-based, best- effort sweep receipt and custody already use, not exhaustive -- see receipt's own README for what it doesn't catch.

Watching the filesystem too

Pass watch_dir to also snapshot-diff a local directory before and after the interaction, reusing receipt.snapshot's real snapshot()/diff() core directly (not reimplemented):

with capture(page, task="click save button", watch_dir="./data") as c:
    page.click("#save")
    page.wait_for_timeout(200)

print(c.result["changes"])  # {"added": ["saved.json"], "modified": [], ...}

This closes the loop from client interaction to backend side effect -- proving the click didn't just send a request that returned 200, but that a real file actually landed on disk because of it. watch_dir=None (the default) skips this step entirely; no extra install needed either way.

Why no CLI

Every other tool in this portfolio is a CLI because each one wraps a command, a file, or a config a human or CI job invokes directly. clicked instruments one interaction inside a caller's own Playwright script -- there's nothing to invoke from a shell that isn't already that script. The receipt itself is a Providence bundle either way (c.to_dict() / c.write(path)), so it plugs into the same evidence pipeline as everything else in this portfolio without needing its own entry point.

Playwright is never imported here

capture() only calls .on() and .remove_listener() on whatever object you pass it -- duck-typed, not a hard dependency on Playwright or any particular version of it. receipt-evidence is the one real dependency this package has -- a hard one, not an extra, because redaction (above) is part of the core network-capture path, not an opt-in feature; it's also itself dependency-free, so this stays a light install either way.

Tests

pip install -e "."
python tests/test_capture.py         # pure logic, a fake page object, no browser needed
pip install -e "." playwright
python -m playwright install chromium
python tests/test_capture_live.py    # real Chromium, real HTTP server, real network + filesystem effects

17 tests total (13 + 4). The live suite is the one that actually matters for a package whose whole point is "did this really happen" -- it skips cleanly, rather than failing, if Playwright or its browser binary isn't installed.

MIT licensed.

Release files for clicked-evidence 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for clicked-evidence 0.1.0
File Size Uploaded
clicked_evidence-0.1.0.tar.gz 10.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for clicked-evidence 0.1.0
File Interpreter ABI Platform
clicked_evidence-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 17.8 kB

Release files / clicked_evidence-0.1.0.tar.gz

Download URL clicked_evidence-0.1.0.tar.gz
Size 10.6 kB
Tags Source
SHA-256 checksum
How to use checksums
5a7a3da3b174cd866bbaa0dfe2fa1e9a476eb3872170b1b9085e3ed6394d3e4a
BLAKE2b-256 checksum
How to use checksums
c8195b65069e024949d398a3ad02ef064c567961f9f7cd74fea72e34d2c8ada0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / clicked_evidence-0.1.0-py3-none-any.whl

Download URL clicked_evidence-0.1.0-py3-none-any.whl
Size 7.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0febf90cc35f12e7b780d9db522979b5f46271b4384c6cb8b2605e8d06e873b9
BLAKE2b-256 checksum
How to use checksums
6df13776f99eafe4b9d865e76502b699fc7600f575a9b032af01dd882be5e415
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page