New Features (2026-06-18) — CLI & Integrations
Eight headless capabilities that round out scripting, integration, and
continuous-integration use: a real command-line interface,
recording-to-code generation, and first-class HTTP / SQL / email / PDF /
wait steps. Every feature ships a headless Python API, an AC_*
executor command, an MCP tool, and a visual Script Builder entry, and is
covered by headless tests — the network, SMTP, and PDF backends are
injected, so nothing touches the outside world.
Command-line interface
The package now installs a je_auto_control console script for running
and inspecting action files from a shell or CI pipeline:
je_auto_control run script.json --var user=alice --dry-run
je_auto_control validate script.json # alias: lint
je_auto_control list-commands --filter mouse --json
je_auto_control fmt script.json --check
je_auto_control record out.json --duration 5
je_auto_control codegen script.json --target pytest -o test_flow.py
je_auto_control version
run executes (--dry-run validates and lists steps without acting),
validate / lint checks structure and rejects unknown commands,
fmt canonicalises the JSON, record captures input, codegen
emits source (below), and list-commands prints the live executor
catalogue.
Code generation
Turn a recording or an action file into committable, runnable source:
from je_auto_control import generate_code, generate_code_file
code = generate_code(actions, target="pytest", style="calls")
generate_code_file("flow.json", "test_flow.py", target="pytest")
target is pytest / python / robot. The default calls
style maps each AC_* command to its facade call
(ac.click_mouse(...)) and falls back to ac.execute_action([...])
for flow control and private adapters; the actions style embeds the
list and replays it through the executor.
Executor command: AC_generate_code. CLI: je_auto_control codegen.
HTTP / API
A dependency-free HTTP(S) client for hybrid UI + API flows:
from je_auto_control import http_request
resp = http_request(
"https://api.example/items", method="POST",
json_body={"name": "Sam"},
headers={"X-Trace": "1"},
auth={"type": "bearer", "token": "..."},
timeout=30.0)
assert resp["status"] == 201
Returns {status, ok, headers, text, json, url}; non-2xx responses are
returned rather than raised, so you can assert on the status code. Only
http / https schemes are allowed. AC_http_to_var now shares
the same client, so it can POST bodies and send headers / auth.
Executor command: AC_http_request.
SQL
Read-only, parameter-bound SQLite queries:
from je_auto_control import query_sqlite
rows = query_sqlite("app.db", "SELECT id, name FROM users")
count = query_sqlite("app.db",
"SELECT COUNT(*) FROM users WHERE active = ?",
params=[1], fetch="scalar")
Queries are restricted to a single read-only SELECT / WITH
statement, run over a read-only connection, with values always bound as
parameters (never string-interpolated).
Executor commands: AC_sql_to_var (rows / one row / scalar into a
variable) and AC_assert_db (a scalar query asserted with
eq / ne / lt / gt / contains / …).
Email (SMTP)
Send mail — for example a flow’s report — over the standard library:
from je_auto_control import send_email
send_email(
{"sender": "bot@x.com", "to": ["qa@x.com"],
"subject": "Run passed", "body": "All green",
"attachments": ["report.html"]},
{"host": "smtp.x.com", "port": 587,
"username": "bot@x.com", "password": "..."})
TLS is enabled by default (STARTTLS, or implicit SSL when use_ssl is
set) over a verified default context; supports multiple recipients, CC,
HTML bodies, and file attachments.
Executor command: AC_send_email.
PDF
Extract text from and assert on PDF documents (optional pypdf
backend — pip install je_auto_control[pdf]):
from je_auto_control import extract_pdf_text, assert_pdf_text
text = extract_pdf_text("invoice.pdf", pages=1)
assert_pdf_text("invoice.pdf", "Total: $50.00")
Executor commands: AC_pdf_to_var (text into a variable) and
AC_assert_pdf_text (text present / absent, optionally on a page).
Smart waits
Two waits that replace unreliable sleep calls:
from je_auto_control import (
wait_until_file, wait_until_port, wait_until_process)
wait_until_file("~/Downloads/report.pdf", stable_for_s=1.0)
wait_until_port("127.0.0.1", 8080, timeout_s=30.0)
wait_until_process("myserver", present=True, timeout_s=30.0)
wait_until_file returns once a file exists, is at least min_size
bytes, and its size has held steady for stable_for_s (a download has
finished). wait_until_port returns once a TCP connection to
host:port succeeds — the companion to launching a server. wait_until_process
returns once a process whose name contains the target appears (or, with
present=False, exits) — the companion to launch_process /
kill_process (requires psutil). All return a WaitOutcome and honour
a hard timeout_s cap.
Executor commands: AC_wait_for_file, AC_wait_for_port,
AC_wait_for_process.
Security
HTTP and SMTP enforce http / https or TLS with verified
certificates and explicit timeouts; SQL is read-only and parameter-bound;
all user-supplied file paths are resolved with realpath before I/O.