Skip to main content

Flow2Skill

Flow2Skill: record, sanitize, review and prove

Watch the 50-second narrated proof · Studio screenshot · Replay evidence

Browser agents improvise. Flow2Skill preserves what already worked.

Flow2Skill is a local-first compiler for demonstrated browser workflows. Record a successful flow with Playwright codegen. Flow2Skill turns it into an inspectable contract, a portable agent skill, and an executable regression test.

human demonstration → strict AST compiler → protected workflow → agent skill + pytest proof

It exports:

  • flow.json and flow.yaml: fingerprinted workflow contracts;
  • SKILL.md: reviewable instructions for Hermes, Codex, Claude Code, Cursor, and other agents;
  • test_<workflow>.py: a standalone Playwright/pytest proof;
  • README.md: run instructions for the generated bundle.

Flow2Skill is not an autonomous browser agent. It preserves a workflow that already worked.

Why use it

Browser agents are useful when the path is unknown. They are expensive and inconsistent when the path is already known. Flow2Skill converts a successful run into a reusable asset with stable selectors, protected inputs, explicit review gates, and mechanical success criteria.

  • Local-first: Studio only binds to loopback.
  • Parse, never execute: recordings are inspected through Python's AST and are never imported or run.
  • Protected by default: typed values and text/value assertions become environment variables.
  • Echo-aware: a protected input repeated in later selector or result text is replaced with the same runtime variable.
  • Fail closed: dynamic values, unsupported locator operations, control flow, multiple tests, missing assertions, unknown selector modifiers, and unsupported calls stop compilation.
  • Review before mutation: all clicks, key presses, fills, selections, and check operations are review-gated. Publish, send, buy, submit, delete, and similar actions are approval-gated.
  • Proof required: a workflow without an executable assertion is rejected.
  • Portable: the generated pytest does not depend on Flow2Skill at runtime.

Install

Prerequisites:

  • Python 3.10–3.13;
  • Node.js with npx, required only for recording;
  • Chromium installed through Playwright, required for default replay.
python -m pip install "flow2skill[test]"
python -m playwright install chromium
flow2skill doctor
flow2skill studio

The test extra installs pytest for the standalone regression proofs. For compiling, Studio, or CLI replay without pytest, install the base flow2skill package.

From a source checkout:

python -m venv .venv
# Windows
.venv\Scripts\python.exe -m pip install -e ".[dev]"
.venv\Scripts\python.exe -m playwright install chromium
.venv\Scripts\flow2skill.exe doctor
.venv\Scripts\flow2skill.exe studio

Windows source checkouts also include launch-flow2skill.bat. Installed wheels use the flow2skill console command; the batch launcher is not installed by the wheel.

Recording uses Playwright-managed Chromium by default, matching doctor and the browser installation above. To use a separately installed Google Chrome instead, pass --channel chrome to flow2skill record. Studio uses managed Chromium.

Studio opens at http://127.0.0.1:8765 and writes bundles to ~/Flow2SkillWorkspaces unless another root is supplied.

Diagnose setup

flow2skill doctor
flow2skill doctor --mode compile
flow2skill doctor --mode record
flow2skill doctor --mode replay --json

The default checks recording and replay prerequisites. Compile mode does not require Node.js or a browser; replay mode does not require Node.js. Each failed check includes a repair instruction. Missing pytest is a warning for exported proofs, because CLI replay itself does not use pytest. Exit code 2 means a required prerequisite is missing or mismatched; 0 means the selected prerequisite checks passed.

Doctor inspects installation state without launching a browser. Run the demo proof to verify real browser execution; a successful setup check is not workflow evidence.

Thirty-second proof

Generate an entirely local sample bundle:

flow2skill demo --out ./flow2skill-demo

Run it against Flow2Skill's packaged local fixture:

# macOS/Linux
F2S_LABEL_API_TOKEN_1="runtime-demo-token" \
FLOW2SKILL_LIVE=1 \
FLOW2SKILL_ALLOW_SIDE_EFFECTS=1 \
python -m pytest -q ./flow2skill-demo/test_agent_release_gate.py

Windows Command Prompt:

set F2S_LABEL_API_TOKEN_1=runtime-demo-token
set FLOW2SKILL_LIVE=1
set FLOW2SKILL_ALLOW_SIDE_EFFECTS=1
python -m pytest -q flow2skill-demo\test_agent_release_gate.py

The side-effect flag is required because the proof fills a synthetic API-token field and clicks a validation button, even though the packaged fixture is local and harmless. The captured synthetic value is absent from the generated bundle.

Check that a regression is detected

The scoped trial runner uses a local page with two Save buttons. With Flow2Skill 0.2.0 and Chromium installed, save the script in a writable folder and run python scoped_trial.py. It compiles a synthetic recording, requires a passing standalone test, changes the page's success message and requires a failure, then restores the page and requires a pass again. It retains the output in trial-output/evidence.txt and never opens an external site. The script is also included in the source archive under examples/.

The recording is hand-written. This checks scope preservation and regression detection; it does not verify interactive Inspector recording. The runner overwrites its own trial-output files on reruns. Review the script before enabling execution on your machine.

Record a workflow

flow2skill record https://example.com ^
  --name "Documentation search" ^
  --success-text "Results"

Complete the flow in Playwright Inspector, capture an assertion or provide --success-text, and close the recorder window. Flow2Skill compiles the capture and deletes its temporary raw codegen and recorder log.

Recording uses the pinned Playwright codegen version declared by this package. flow2skill doctor verifies version alignment and prerequisites.

Compile existing codegen

flow2skill compile recording.py \
  --name "Documentation search" \
  --intent "Search the docs and prove results appear." \
  --out ./compiled-flow

Protection is enabled by default. --no-protect-inputs preserves non-sensitive literal values and should only be used for known-public test data. Sensitive fields remain protected.

Input-file contract: flow2skill compile never deletes the file you explicitly provide. Playwright codegen files can contain credentials or typed data; store and remove that source according to your own retention policy.

Inspect and replay

Dry-run without opening a browser:

flow2skill inspect ./compiled-flow/flow.json

Run the generated standalone proof:

FLOW2SKILL_LIVE=1 pytest -q ./compiled-flow/test_documentation_search.py

Live CLI replay and exported tests check all protected runtime variables before opening the browser. Missing variables are reported together; an explicitly empty value is allowed. Dry-run inspection does not require values.

Use FLOW2SKILL_HEADED=1 to watch. Any workflow containing review or approval actions also requires FLOW2SKILL_ALLOW_SIDE_EFFECTS=1. Set it only after reviewing the exact generated plan. Use FLOW2SKILL_CHANNEL=chrome to replay with an installed Chrome channel instead of Playwright's managed Chromium.

Supported capture surface

  • one synchronous pytest-style test function;
  • the exact session fixture emitted by --block-service-workers; other context fixtures are rejected;
  • direct Playwright call statements only;
  • page.goto;
  • role, label, placeholder, text, test-id, title, alt-text, and CSS selectors, including direct chains scoped inside another locator;
  • .first and nonnegative integer .nth(...) modifiers on element locators;
  • locator click, fill, press, select_option, check, uncheck, and hover;
  • expect(...).to_be_visible();
  • exact to_have_text() and substring to_contain_text() assertions;
  • expect(page).to_have_url();
  • expect(...).to_have_value().

Recorder, CLI replay, and exported proofs block service workers consistently. Arbitrary context options and user fixture code are not executed. Navigation and URL assertions require page; element actions and assertions require locators. Test-id and CSS selectors do not accept exact. Invalid targets and options stop compilation.

For example, this keeps both the dialog scope and the selected row:

page.get_by_role("dialog", name="Profile").first.locator(".row").nth(1).get_by_role("button", name="Save").click()

Scope is retained in the manifest, skill instructions, replay, and standalone test. Protected values and approval classification include parent selectors. New manifests use schema 1.1; schema 1.0 manifests retain their original fingerprints when loaded and exported. Older Flow2Skill versions cannot read schema 1.1 manifests, but exported Python tests remain standalone. Locator filters, frame locators, and dynamic scopes are still unsupported.

Unsupported calls, dynamic expressions, assignments, loops, branches, context managers, nested functions, and multiple tests are rejected. They are never flattened or silently omitted.

Security and privacy model

Recording boundary

During live recording, Playwright briefly writes raw Python to a hidden workspace file. Flow2Skill deletes this file and the recorder log on completion, cancellation, launch failure, or compile failure. On startup it removes abandoned raw captures older than one hour. A hard power loss can therefore leave a temporary file until the next cleanup window. Do not record real production credentials when synthetic test credentials are available.

Manifest integrity

flow.json carries a SHA-256 fingerprint. Loading rejects unknown fields, malformed selector types, missing fingerprints, content tampering, stale slugs, and risk-classification downgrades. The fingerprint detects accidental or local modification; it is not a cryptographic signature from a trusted publisher.

Runtime variables are restricted to the compiler-owned F2S_* namespace. Captured ${VARIABLE} syntax is rejected instead of being allowed to read arbitrary host environment variables. Navigation containing protected values is approval-gated because it can transmit the value to the destination.

Common credential-bearing URL parameters, including JWT, token, signature, session, authentication, and password fields, are replaced with runtime variables. Recompiling into an existing managed bundle directory removes obsolete generated test_*.py files so stale executable proofs cannot survive unnoticed.

Studio boundary

Studio enforces:

  • loopback-only binding;
  • strict local Host validation against DNS rebinding;
  • same-origin checks;
  • a random per-process request token;
  • a one-megabyte JSON body limit;
  • strict request field types;
  • workspace and artifact path containment;
  • no-store and browser hardening headers.

Approval boundary

Flow2Skill compiles instructions; it does not grant permission. Generated skills call out approval-gated actions. Generated tests are disabled unless FLOW2SKILL_LIVE=1 is present. Once live execution is requested, a missing side-effect flag fails the test rather than reporting a successful skip.

See SECURITY.md for the threat model and reporting process.

Development

python -m pip install -e ".[dev]"
ruff format --check src tests scripts
ruff check src tests scripts
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest -q
python -m build
python -m twine check dist/*

The release gate also installs the wheel into a clean environment, runs the packaged demo against a real browser, checks source/wheel contents, and scans tracked files for high-confidence secrets and private paths.

Intentional boundaries

Flow2Skill does not include cloud sync, a browser extension, shared secret storage, autonomous planning, or LLM selector healing. Those features create a platform before the deterministic compiler has earned it. The current product does one job: preserve a successful browser workflow as a reviewable procedure and executable proof.

License

MIT

Bundle recovery

An export replaces the generated files in its output directory; use a different output directory to retain a separate version. All five artifacts are rendered and staged before replacement. A failed replacement attempts to restore the previous files, including its generated test. Unrelated files are preserved. Exports to the same directory are serialized with .flow2skill-write.lock; wait for the current export to finish before reading or executing the bundle. The set of files is not an atomic directory snapshot for concurrent readers.

A killed process or power loss can leave the lock and a .flow2skill-stage-* directory. Do not remove a lock while an export is running. Check the PID recorded in it and confirm that export has stopped. Keep a copy of the whole output directory before recovery. Staging old/ contains backups of files that existed before replacement; new/ contains any staged files that were not yet published. Restore the old files and remove newly introduced generated files, or regenerate the bundle into a fresh directory from the original recording. Do not execute a mixed or unverified bundle. Remove the stale lock only after recovery; retained staging directories can then be removed. Incomplete rollback reports its recovery directory and keeps the lock.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flow2skill-0.2.0.tar.gz (807.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flow2skill-0.2.0-py3-none-any.whl (48.2 kB view details)

Uploaded Python 3

File details

Details for the file flow2skill-0.2.0.tar.gz.

File metadata

  • Download URL: flow2skill-0.2.0.tar.gz
  • Upload date:
  • Size: 807.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for flow2skill-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c049ecd83b1b03744a8044aec8ac9a293394f0a05f2ed1cca8413a9c03ca2741
MD5 f439816e263d4c14602caf3cd993bc9a
BLAKE2b-256 b608153a2c93a77a056ff016e51f4823fca994aabcbb3fae5a9ad64e8b198cb0

See more details on using hashes here.

Provenance

The following attestation bundles were made for flow2skill-0.2.0.tar.gz:

Publisher: release.yml on godhiraj-code/flow2skill

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file flow2skill-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: flow2skill-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 48.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for flow2skill-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6db1c9cd0e045239a3ef981a45b9a95ed35e25a5cabd384fbc7ee8614ad8922a
MD5 a0788aac4b8a45915715c7c87ae91445
BLAKE2b-256 007ef5fb2ef2bf4b18a60cb7ee90994a3d38250bc2fedb8f3d654884aec18cf6

See more details on using hashes here.

Provenance

The following attestation bundles were made for flow2skill-0.2.0-py3-none-any.whl:

Publisher: release.yml on godhiraj-code/flow2skill

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.0

2 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