Machine Presence SDK is a standalone Python project for describing physical and virtual machines, checking their state, safely controlling power through adapters, opening remote sessions, running mock KVM/remote-control scenarios, and keeping an audit log.
The project is designed as a portable core: it can be used from Python code,
through the machine_presence CLI, or as a foundation for future integrations
with Wake-on-LAN, Xiaomi board, JetKVM, Luckfox PicoKVM, PiKVM, RustDesk,
Tailscale, and RDP.
For the current-PC phone-control MVP, start with the setup wizard:
python -m pip install -e ".[dev]"
machine_presence init current-pcThe wizard creates .machine_presence/current_pc.toml and
.machine_presence/control-token.txt, then prints exact doctor and serve
commands for the detected LAN/Tailscale address.
Typical next steps:
machine_presence doctor --config .machine_presence/current_pc.toml --host 192.0.2.10 --port 8765 --token-file .machine_presence/control-token.txt
machine_presence serve --config .machine_presence/current_pc.toml --host 192.0.2.10 --port 8765 --token-file .machine_presence/control-token.txtOpen the printed URL from the phone and enter the token from
.machine_presence/control-token.txt.
Russian MVP documentation:
- Changelog
- Documentation index
- MVP overview
- Phone control setup
- Security model
- Adapter roadmap
- Autostart helper
- Current PC mobile demo
- Wake-on-LAN adapter
- Generic HTTP power adapter
- Network health probes
- Network access troubleshooting
- Production token setup
- Network diagnostics
- From zero to phone control
- Current PC init wizard
- MVP release checklist
- Unified Presence Status
The first MVP is intentionally mock-first. It must work without real hardware
and without access to powered-off computers. This keeps development safe on a
regular workstation: real shutdown, reboot, and power actions are not
performed in the MVP.
Real control of a powered-off PC is impossible without a suitable hardware or network mechanism: Wake-on-LAN, external KVM, a managed power board, BMC/IPMI, a smart plug, or another out-of-band channel. The SDK will prepare interfaces for those adapters, but the first stage is limited to software/mock scenarios.
The SDK includes deterministic mock adapters for power control, health probes,
remote sessions, and KVM-style screen/input flows. Mock adapters never perform
real OS, network, keyboard, mouse, shutdown, reboot, or hardware actions.
Dangerous mock actions such as power_off, reboot, send_key, and
send_macro create a pending action request first. The action runs only after
the request is explicitly confirmed.
examples/current_pc.toml describes the machine currently running Machine
Presence SDK as a software-local endpoint. It can report hostname, platform,
Python version, basic reachability, and best-effort uptime when that metric is
available safely on the current OS. If a metric is unavailable, the action
returns partial degraded information instead of failing.
The local adapter is not power control. It never shuts down, reboots, wakes, or executes system commands. Remote access is only a configured link or instruction, such as a RustDesk URL:
machine_presence --config examples/current_pc.toml status current_pc
machine_presence --config examples/current_pc.toml probe current_pc
machine_presence --config examples/current_pc.toml open current_pcexamples/current_pc_mobile.toml is the recommended production-like starting
point for opening the SDK web panel from a phone. It is tuned for the current
software-level flow: home-pc, local health, Chrome Remote Desktop instruction,
read-only Tailscale status, and audit logging. Real power and KVM adapters stay
disabled by default.
For a local daily-use profile, generate a private config and token file:
machine_presence init current-pcThe wizard writes .machine_presence/current_pc.toml, creates or reuses
.machine_presence/control-token.txt, and prints the exact serve and
doctor commands for the detected LAN/Tailscale address. It does not print the
raw token.
For real phone access, generate a long token and use --token-file instead of
keeping the token in command history:
machine_presence token generate --output .machine_presence/control-token.txt
machine_presence network-info --config examples/current_pc_mobile.toml --port 8765
machine_presence doctor --config examples/current_pc_mobile.toml --host 192.0.2.10 --port 8765 --token-file .machine_presence/control-token.txt
machine_presence serve --config examples/current_pc_mobile.toml --host 192.0.2.10 --port 8765 --token-file .machine_presence/control-token.txtIf the token may have leaked, rotate it without printing the new secret:
machine_presence token rotate --token-file .machine_presence/control-token.txtThe old token is written to .machine_presence/control-token.txt.bak; restart
machine_presence serve and re-enter the new token in open phone/browser tabs.
If a specific overlay network client does not work, Machine Presence can still run over another private path such as LAN, Tailscale, ZeroTier, WireGuard, Chrome Remote Desktop, RustDesk, or a private tunnel. See Network access troubleshooting.
Use machine_presence network-info to see local LAN/Tailscale addresses and a
recommended bind host. Use machine_presence doctor to check config, token,
token hygiene, bind host, port availability, audit writability, heartbeat, and
Tailscale visibility before debugging phone access. The doctor command also
checks remote session profile readiness for phone-control configs and prints
fix lines with copyable next steps.
Use machine_presence presence <machine_id> or the web UI machine cards for a
single aggregated view of whether a machine looks online, offline,
degraded, or unknown. Unified presence combines read-only power status,
health probe, Tailscale status, and remote profile evidence without writing
audit events on every refresh.
The SDK includes a read-only Tailscale status adapter. It checks whether the
local tailscale CLI is available and, when possible, reads
tailscale status --json to find a configured machine by tailscale_name.
The adapter never logs in, never runs tailscale up, and never changes
Tailscale settings. If the CLI is missing, the action returns unsupported
instead of raising a traceback.
machine_presence --config examples/current_pc.toml tailscale-status current_pc
machine_presence --config examples/machine_presence.toml tailscale-status home_pcexamples/wake_on_lan.toml shows a safe Wake-on-LAN power adapter
configuration. power_on sends a UDP magic packet only after explicit
confirmation. power_off and reboot are unsupported because WoL cannot shut
down or restart a machine. WoL also cannot report power status; use a health
probe, Tailscale status, or a remote session profile after sending the packet.
Wake-on-LAN must be enabled in BIOS/UEFI and network adapter settings. It may still fail depending on power state, router behavior, Wi-Fi/Ethernet support, and OS driver settings. Across another city or country, WoL usually requires a VPN, router relay, or another device already inside the LAN. It does not replace KVM: it cannot show BIOS, capture HDMI, or send pre-boot keyboard input.
machine_presence --config examples/wake_on_lan.toml power-on wol_pc
machine_presence --config examples/wake_on_lan.toml confirm <request_id>
machine_presence --config examples/wake_on_lan.toml power-on wol_pc --confirmexamples/http_power.toml shows a generic HTTP power relay configuration. The
adapter reads a bearer token from an environment variable named by token_env;
the token is not stored in machine_presence.toml and is not written to audit
events. A request timeout is always used.
status calls the configured route with GET; power_on, power_off, and
reboot use POST. Runtime power actions go through the confirmation workflow
before the relay is called.
Do not expose an HTTP power relay directly to the internet. Use a trusted local network, VPN, or Tailscale-style private route, and keep the relay behind that private boundary.
$env:HOME_PC_POWER_TOKEN = "dev-token"
machine_presence --config examples/http_power.toml power-on http_power_pc
machine_presence --config examples/http_power.toml confirm <request_id>examples/network_probes.toml shows TCP and HTTP health probes. TCP probes open
a socket to host:port; HTTP probes call a configured URL and compare the
status code with expected_status. Both require explicit timeout_seconds and
use only Python standard library networking.
Connection refused returns offline; timeouts and unexpected HTTP statuses
return degraded. Ping is intentionally deferred because a safe
cross-platform implementation needs more OS-specific handling.
machine_presence --config examples/network_probes.toml probe tcp_service
machine_presence --config examples/network_probes.toml probe http_serviceMachines can define multiple remote session profiles under
[machines.<id>.remote_profiles.<profile_id>]. Supported profile types are
url, rustdesk, rdp, vnc, ssh, and instruction.
Profiles return structured connection information and instructions. The SDK does not automatically start RustDesk, RDP, VNC, or SSH clients.
machine_presence --config examples/machine_presence.toml sessions home_pc
machine_presence --config examples/machine_presence.toml open home_pc --profile rustdeskThe SDK can run a FastAPI server for local or phone-based control of mock
machines. By default the server binds only to 127.0.0.1:
machine_presence serve --config examples/machine_presence.tomlFor phone access, first ask the SDK which private address is safest to bind:
machine_presence network-info --config examples/machine_presence.toml --port 8765If Tailscale or another private interface has a stable IP, prefer binding to that specific address instead of all interfaces:
machine_presence serve --config examples/machine_presence.toml --host 192.0.2.10 --port 8765 --token-file .machine_presence/control-token.txt--host 0.0.0.0 remains available only as a fallback. It exposes the server on
every interface and now requires explicit --allow-public-bind in addition to a
control token:
machine_presence serve --config examples/machine_presence.toml --host 0.0.0.0 --port 8765 --token-file .machine_presence/control-token.txt --allow-public-bindThen open http://<pc-lan-or-tailscale-ip>:8765/ from the phone for the web
panel, or http://<pc-lan-or-tailscale-ip>:8765/api/health for a health check.
Protected API endpoints require:
Authorization: Bearer dev-token
The server refuses to bind outside 127.0.0.1 without a token. Binding to
0.0.0.0 also requires --allow-public-bind; prefer a concrete Tailscale/LAN IP
from machine_presence network-info.
The web panel exchanges the raw control token via POST /api/auth/session and
then uses a short-lived session token for API calls. The session token stays only
in the current browser tab memory and expires after 30 minutes by default.
The server keeps only a token hash in memory, rate-limits failed auth attempts,
and exposes non-secret security state at /api/security/status. The web panel
and CLI show a warning when the server is bound outside 127.0.0.1.
The mobile web panel auto-refreshes heartbeat, machine status, pending actions,
and audit events. It also shows the current panel URL for copying to a phone and
displays refresh timestamps so manual audit refreshes are visible. The Phone
Connection panel shows live API reachability, the best connection path
(Tailscale, LAN, or another private route), a copyable phone URL, and a QR
code generated locally by the SDK.
Dangerous HTTP actions return a pending request id. Use
GET /api/actions/pending, POST /api/actions/{request_id}/confirm, or
POST /api/actions/{request_id}/deny to finish the lifecycle. The mobile UI
shows pending actions with explicit Confirm and Deny buttons.
When the HTTP server is running, Machine Presence SDK writes a lightweight
runtime marker to .machine_presence/heartbeat.json. The marker contains the
UTC timestamp, hostname, process id, SDK version, server bind host, port, and
process uptime. It does not require administrator rights.
The API exposes the current heartbeat status at /api/agent/heartbeat; this
endpoint uses the same bearer-token protection as the rest of the control API
when a token is configured. The CLI can inspect the marker without starting the
server:
machine_presence agent-status
machine_presence serve --config examples/machine_presence.toml --heartbeat-interval 5A fresh marker reports online, a stale marker reports degraded, and a
missing or very old marker reports offline.
Machine Presence SDK can render and safely install autostart entries for Windows Scheduled Tasks and Linux systemd user services.
Install/uninstall helpers are dry-run by default and change the system only
when --confirm is passed. Use --token-file for persistent phone access so
the raw token is not stored in the generated autostart entry.
machine_presence autostart status
machine_presence autostart install-windows --config examples/current_pc_mobile.toml --host 192.0.2.10 --port 8765 --token-file .machine_presence/control-token.txt
machine_presence autostart install-windows --config examples/current_pc_mobile.toml --host 192.0.2.10 --port 8765 --token-file .machine_presence/control-token.txt --confirm
machine_presence autostart install-systemd --config examples/current_pc_mobile.toml --host 192.0.2.10 --port 8765 --token-file .machine_presence/control-token.txtThe project requires Python 3.11 or newer. This is a careful baseline for the SDK: Python 3.11 is already widely available on Windows, Linux, and macOS, supports modern typing, and does not force users to move immediately to the newest interpreter versions.
python -m pip install -e ".[dev]"CI runs the release gate on Linux and Windows for Python 3.11 and 3.12:
ruff check ., pytest, and a wheel smoke build.
machine_presence --version
python -m machine_presence --version
machine_presence init current-pc --output .machine_presence/smoke-current_pc.toml --token-file .machine_presence/smoke-control-token.txt --force
machine_presence --config examples/machine_presence.toml machines
machine_presence --config examples/machine_presence.toml status home_pc
machine_presence --config examples/machine_presence.toml presence mock_server
machine_presence --config examples/machine_presence.toml tailscale-status home_pc
machine_presence --config examples/machine_presence.toml sessions home_pc
machine_presence --config examples/machine_presence.toml open home_pc --profile rustdesk
machine_presence --config examples/wake_on_lan.toml power-on wol_pc
machine_presence --config examples/http_power.toml power-on http_power_pc
machine_presence --config examples/network_probes.toml probe tcp_service
machine_presence token generate --output .machine_presence/control-token.txt
machine_presence token rotate --token-file .machine_presence/control-token.txt
machine_presence --config examples/current_pc_mobile.toml machines
machine_presence --config examples/current_pc_mobile.toml sessions current_pc
machine_presence network-info --config examples/current_pc_mobile.toml --port 8765
machine_presence doctor --config examples/current_pc_mobile.toml --host 192.0.2.10 --port 8765 --token-file .machine_presence/control-token.txt
machine_presence --config examples/machine_presence.toml reboot home_pc
machine_presence --config examples/machine_presence.toml confirm <request_id>
machine_presence --config examples/machine_presence.toml audit --limit 5
machine_presence agent-status
machine_presence autostart status
machine_presence autostart install-windows --config examples/current_pc_mobile.toml --port 8765 --token-file .machine_presence/control-token.txt
machine_presence autostart install-systemd --config examples/current_pc_mobile.toml --port 8765 --token-file .machine_presence/control-token.txt
machine_presence autostart render-windows --config examples/current_pc.toml --port 8765
machine_presence autostart render-systemd --config examples/current_pc.toml --port 8765
machine_presence serve --config examples/machine_presence.toml
python -m machine_presence --config examples/machine_presence.toml status home_pc
python -m pip wheel . --no-deps -w dist-smoke
pytest
ruff check .Both version commands should print the machine-presence package version.
Runtime actions append audit events to .machine_presence/audit.jsonl by default.
Use --audit-log <path> to write or read a different JSONL audit file.
Pending action requests are stored in .machine_presence/action_requests.json
by default; use --action-store <path> to override that file.