Record a browser workflow once, export a portable agent skill and deterministic Playwright regression test.
Project description
Flow2Skill
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.jsonandflow.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, nested locator scopes, 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
python -m playwright install chromium
flow2skill doctor
flow2skill studio
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.
Studio opens at http://127.0.0.1:8765 and writes bundles to ~/Flow2SkillWorkspaces unless another root is supplied.
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 \
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
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.
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
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;
- direct Playwright call statements only;
page.goto;- role, label, placeholder, text, test-id, title, alt-text, and CSS selectors;
.firstand literal.nth(...)modifiers;click,fill,press,select_option,check,uncheck, andhover;expect(...).to_be_visible();- exact
to_have_text()and substringto_contain_text()assertions; expect(page).to_have_url();expect(...).to_have_value().
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
Hostvalidation 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
Project details
Release history Release notifications | RSS feed
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 flow2skill-0.1.0.tar.gz.
File metadata
- Download URL: flow2skill-0.1.0.tar.gz
- Upload date:
- Size: 783.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1fc83368ce613b9fd99034c44870d0f3aa1d787162f1d5c798b333e2306a602
|
|
| MD5 |
82f727cccd1f33866e7b8422a1aec939
|
|
| BLAKE2b-256 |
2c62466459c7bb73cde6c76aa32377f707ff1ea368bff6a76e4ef0cb746c844a
|
File details
Details for the file flow2skill-0.1.0-py3-none-any.whl.
File metadata
- Download URL: flow2skill-0.1.0-py3-none-any.whl
- Upload date:
- Size: 40.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ebc3aee1171cdd00be8dae0ba1fc23976cb9309ff7d24fe583b517023e3a96a
|
|
| MD5 |
1fd2f876e023757f2fbdaa00907cf81d
|
|
| BLAKE2b-256 |
6edb255abeaa5876767b5ad33f4e4b8d4c4a216e7d6ff93caff54879050aa653
|