testsAndMisc/python_pkg/phone_lease/__init__.py
Krzysztof kuhy Rudnicki c0c51036fc phone_lease: per-app leases, a self-cleaning whole-phone lease, one serial
Several sessions can now share one phone: a lease covers one package (the
real screen stays the default scope, so existing callers keep their
meaning), and only phone-wide actions take `--whole-phone`, which is capped
at 300 s and runs its `--cleanup` commands exactly once on release or, via a
detached reaper, on expiry. The serial is always resolved, never the
"default" placeholder that let android_ui and phone_deploy lease different
keys for the same phone (2026-09-25). Adds status --json, holds and whoami
for phone_vd.sh and the raw-adb hook.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Ajzz98xksbfak8CaunZWC
2026-09-25 15:05:57 +02:00

60 lines
1.8 KiB
Python

"""One phone, many Claude sessions: leases that keep them from colliding.
Two sessions driving the same phone interleave their taps -- on 2026-09-20 a
tap meant for the workout sandbox landed in another session's manga reader,
twice. This package hands out *scoped* leases:
* the leases are one JSON file per serial under ``~/.cache/phone-lease/``,
guarded by ``flock`` so read-modify-write is atomic across processes;
* a lease covers one app (``--package``), the real screen (the default), or
the whole phone (``--whole-phone``: Doze, sleep, reboot -- capped at five
minutes, with cleanup commands a detached reaper runs if nobody releases);
* the owner is the nearest ancestor ``claude`` process (one per session);
* the serial is always resolved (:mod:`.serial`), never a placeholder, so
every caller agrees on which phone a lease is for;
* a lease expires ``ttl`` seconds after its last refresh.
Sessions that drive apps on their own virtual display
(``~/.claude/scripts/phone_vd.sh``) need only a package lease, so several of
them can work on one phone at the same time.
"""
from python_pkg.phone_lease.lease import (
DEFAULT_TTL,
DEFAULT_WAIT,
SCREEN,
WHOLE_PHONE,
WHOLE_PHONE_MAX_TTL,
Clock,
Lease,
PhoneBusyError,
Terms,
acquire,
scope_of,
)
from python_pkg.phone_lease.ops import holds, reap, release, status, status_all
from python_pkg.phone_lease.owner import owner_id
from python_pkg.phone_lease.serial import NoPhoneError, resolve_serial
__all__ = [
"DEFAULT_TTL",
"DEFAULT_WAIT",
"SCREEN",
"WHOLE_PHONE",
"WHOLE_PHONE_MAX_TTL",
"Clock",
"Lease",
"NoPhoneError",
"PhoneBusyError",
"Terms",
"acquire",
"holds",
"owner_id",
"reap",
"release",
"resolve_serial",
"scope_of",
"status",
"status_all",
]