Repository navigation
Releases: littlestjames82-sys/ghost-hands
Release list
ghost-hands v0.9.1
ghost-hands 0.9.1 — hardening patch
A security-hardening patch over 0.9.0 — no new features, no new dependencies, governed-action semantics unchanged (classify → record → approve → execute; timeouts and errors still always deny). Full audit detail, pre-fix proofs, and cleared non-findings: HARDENING_091.md in the repo. New regression suite: tests/test_hardening_091.py (35 tests).
Fixed:
- HIGH — Replay-export code injection (
export.py): page-controlled element names went raw into#comments in graduated replay scripts; a newline in a name broke out and became executable Python. Comments now fold all control characters to spaces. - HIGH — Chromium
file://navigation (drivers.py): any scheme was navigable; a governednavigatetofile://…classified readonly and a followingextractread the local file back to the decider.open/open_tabnow allow only http/https (plusdata:/about:fixtures), with browser-style whitespace stripping before the scheme check. - MEDIUM — Governor domain bypass (
governor.py): allow/block lists checked only the starting page's host;evaluate()now also checks the target's href and form-action hosts. - MEDIUM — MCP server crash on hostile messages (
mcp_server.py): non-dict payloads / wrong-shape params raised uncaught errors and killed the stdio loop. Now proper -32600/-32602 errors, type-validated args, 16 MiB line cap, generic -32603 on unexpected errors — the loop always survives. - MEDIUM — BusClient validation (
busclient.py):file:///ftp://bus URLs and workspace ids like../../adminwere accepted. Now http(s)-only, slug-only workspaces, 16 MiB response cap. - LOW — Response caps in Android driver (32 MiB), PhoneApprover (1 MiB, oversize still fails closed to deny), decider (16 MiB), doctor probes (1 MiB).
- LOW — Credential-file permissions: trail files (which record typed text verbatim) and
save_sessionfiles now created 0600; pre-existing loose files tightened. - LOW — Download filename traversal: CDP
suggestedFilenamereduced to its bare name at ingestion.
Verification: new hardening tests 35/35; full suite 442 passed, 1 failed — the failure (test_hosted_workspace_prefix_end_to_end) is pre-existing on the unmodified 0.9.0 baseline: it depends on an external GhostBus hosted server answering /health, which this environment can't reach; it fails before any ghost-hands code runs. Clean-venv pip install of the 0.9.1 wheel verified: imports 0.9.1, ghost-hands demo exits 0.
By Ghost Developer Studio. MIT licensed.
Ghost Hands v0.9.0
This release carries the three waves built since v0.6.0 — v0.7.0, v0.8.0, and v0.9.0 — plainly: an evaluation harness and Android gestures, human-readable audit reports and MCP parity, and a field kit for diagnosing the whole stack and proving the phone flow.
v0.9.0 — field kit
ghost-hands doctor— seven read-only checks covering the Python runtime, Chromium discovery, all four policy packs, model-key presence (presence only; values are never printed), GhostBus when configured, the Android phone bridge when configured, and adb. Every non-pass row includes a plain-language fix; JSON output is available.ghost-hands phone-proof— the guided five-step on-device proof: configuration, adb forwarding, bridge status, the harmless test approval decided on the phone, and a summary with the exact next commands. Exit codes distinguish proven, error, needs-setup, and denied-or-timeout outcomes.
v0.8.0 — receipts + reach
ghost-hands report— render any trail JSONL as one self-contained HTML audit report: summary statistics, a step-by-step timeline, governor verdicts and approval channels, heals, dialogs, downloads, and network events. Page-controlled strings are escaped; password-shaped typed values are masked.- MCP parity —
GHOST_HANDS_DRIVER=fake|chromium|simphone|androidselects the MCP session body, andGHOST_HANDS_APPROVER=phoneroutes consequential-action asks through phone approval. Responses name the deciding channel. seatbeltpolicy pack — a fourth policy pack whose governor-leveldeny_patternsdeny injection-shaped targets regardless of action class, while benign near-misses remain allowed.
v0.7.0 — proof + depth
- Model-evaluation harness —
ghost-hands evalruns eight graded tasks, four on real Chromium, scoring success, steps, wall time, approximate perception tokens, actions by class, approvals, and heals. The deterministic stub suite passes 8/8 as harness proof; the RuleDecider baseline scores 3/8. A real-model run did not execute for this wave because no usable key was reachable in the build environment, so no model-quality number is claimed. - Android gestures — the Android body and MrGhosty v1.8.0 bridge support
double_click,drag, and validatedclick_atin addition to the existing actions. - GhostBus file-store proof — the full bus demo and a parallel agent/poller barrage pass against a file-backed GhostBus store with zero HTTP 400s, closing the loop on the store fix shipped upstream in GhostBus 0.4.1. A broader many-simultaneous-writers read-modify-write characteristic remains documented in the changelog.
Verification
- pytest: 395 passed
- offline bench: 95/95
- live bench: 2/2
- zero runtime dependencies; Python standard library only
Full details are in the CHANGELOG for 0.7.0, 0.8.0, and 0.9.0.
Ghost Hands v0.6.0 — the phone-decides wave
The phone-decides wave: the last roadmap approver lands. This release brings the repo current — v0.4.0 and v0.5.0 were built and verified but never got their own releases, so their changes ship here too (summarized below).
v0.6.0 — PhoneApprover
- PhoneApprover (
phone_approver.py) — consequential asks route to Ryan's phone through the Ghost Hands bridge in MrGhosty v1.7.0. On an ask it POSTs a redacted approval request and polls for the phone's decision; approved → the action runs, and denied / expired / timeout / unreachable / 401 all mean it never does. Trail approval events carrychannel: "phone", request + decision phases, anddecided_by: "phone". - Redacted summaries, by construction. Requests carry kind, classification, target descriptor, and current URL/package only;
typeshows the target + character count (never the text — it may be a password),fill_formshows field names (never values). The contract tests prove a secret string never appears in the payload the bridge receives. - Bridge protocol addition —
POST /v1/approvalsandGET /v1/approvals/<id>. There is intentionally no decision endpoint: a token holder can create a request but can never approve their own — decisions exist only in MrGhosty's notification actions and Device-tab card. - CLI —
ghost-hands run --approver phoneworks with every driver (the phone can approve web runs too); conflicting approver flags exit 2. Newghost-hands phone-approval-testsends one harmless test approval and exits 0 only when the phone approves — the one-command on-device proof. - Bus agent —
--approval-channel bus|phone(envGHOST_HANDS_APPROVAL_CHANNEL). Withphone, consequential asks route to the phone; the agent posts a bus comment noting the phone decision and never requests an approval from the bus. - MrGhosty v1.7.0 (companion app) — approval store (JVM-tested core), the two bridge endpoints, a high-importance "Ghost Hands approvals" notification with Approve/Deny actions, and a Device-tab approvals card.
- Verification — pytest 299/299, offline bench 88/88 (new v6 phone-approval case), live bench 2/2. Wheel 123,802 B / sdist 454,640 B.
Also in this release — v0.5.0 (the real-hands wave)
- AndroidDriver — the real Android body: HTTP/JSON to the Ghost Hands bridge in MrGhosty v1.6.0 (loopback
127.0.0.1:8378, pairing token, never logged or trailed). Bridge protocolGET /v1/status,POST /v1/perceive,POST /v1/act; the bridge's target-missing/mismatch replies feed the Runner's self-healing unchanged. Web-only actions fail honestly, never faked. - CLI —
ghost-hands android-statusandrun --driver android. - Verified: 269 pytest, bench 87/87, live bench 2/2.
Also in this release — v0.4.0 (the collaboration wave)
- GhostBus agent mode —
ghost-hands bus-agentregisters on a GhostBus workspace, claims tagged tasks (respecting claim leases,blockedBy, and the bus's needs-approval gate), runs them through the unchanged Runner/Governor/Trail, uploads the JSONL trail as a shared bus file, and completes with a structured report. Approvals over the bus: deny/timeout denies. - Body Protocol —
docs/BODY_PROTOCOL.md: the formal driver contract, proven by SimPhoneDriver, an in-memory Android-style body driven unchanged by the existing Runner/Governor/deciders; conformance passes on all three bodies (Fake, Chromium, SimPhone). - Policy packs —
readonly/standard/strictpresets (--policy-pack, MCPGHOST_HANDS_POLICY). - Verified: 225 pytest, bench 86/86, live bench 2/2.
Honest status
On-device proof is still pending Ryan's install of MrGhosty v1.7.0 + accessibility grant — no phone was attached during these builds. The install above is the Python package; ghost-hands phone-approval-test is the one-command proof once the phone side is set up.
Full details: CHANGELOG.md
Ghost Hands v0.3.0
Ghost Hands v0.3.0 — governed, recorded, replayable agent hands for the web, on our own zero-dependency CDP stack. No Playwright. No Selenium. The browser body is a stdlib Chrome DevTools Protocol client driving Chromium directly.
Highlights
- Governor on every action. Each action is classified
readonly/write/consequential, judged against policy, and written to a JSONL provenance trail before it executes. Consequential actions (submits, pay/send/delete-shaped moves) stop for human approval; no approver attached = denied. - Trails graduate. Any finished run exports into a deterministic, model-free Ghost Hands script — explore with a model once, replay forever for free (proven by execution on real Chromium).
- Two kinds of eyes. DOM eyes walk the composed tree (open shadow roots pierced, same-page iframes tagged); AX eyes build the map from the CDP Accessibility tree. Numbered element maps: the bundled demo reads a page in ~174 estimated tokens.
- v0.3.0 capabilities (every one classified + trailed): AX-tree perception, shadow-DOM piercing, iframe perceive/act, dialog policy, downloads to disk, file upload, network capture into the trail, one-action
fill_form(failures named, submit stays gated), structured list/table extract, hover / drag / double-click / right-click / key chords, PDF export, device viewport presets, wait-for conditions, rawclick_at(markedraw: true). - Plus: tabs, session save/load (cookies + localStorage), self-healing targets (heal events on the trail), a stdlib MCP server, and pluggable deciders (scripted / deterministic rules / any OpenAI-compatible endpoint, key from env only).
Verified numbers (Oct 8, 2026)
- pytest: 170 passed
- Bench (offline): 82/82, including live-Chrome fixture cases
- Bench (live): 2/2 — example.com link-follow; a real Wikipedia search for "Oakdale, Tennessee" driven end-to-end by the rules decider
- Runtime dependencies: zero (stdlib only)
Honest limits
- The LLM decider's wire protocol is proven against a local stub endpoint only; live-model driving quality is unproven and is the model's business.
- The Chromium driver is proven on example.com + Wikipedia and local fixtures; arbitrary / authenticated third-party sites are untested.
- No head-to-head speed benchmarks vs Playwright/Stagehand/Browser Use have been run or are claimed.
MIT — Ghost Developer Studio.