Skip to content

kymuco/machine-presence

Repository files navigation

Machine Presence SDK

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.

Quick Start

For the current-PC phone-control MVP, start with the setup wizard:

python -m pip install -e ".[dev]"
machine_presence init current-pc

The 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.txt

Open the printed URL from the phone and enter the token from .machine_presence/control-token.txt.

Documentation

Russian MVP documentation:

MVP 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.

Mock Adapters

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.

Local Software Adapter

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_pc

examples/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-pc

The 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.txt

If the token may have leaked, rotate it without printing the new secret:

machine_presence token rotate --token-file .machine_presence/control-token.txt

The 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.

Tailscale Status Adapter

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_pc

Wake-on-LAN Adapter

examples/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 --confirm

Generic HTTP Power Adapter

examples/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>

Network Health Probes

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_service

Remote Session Profiles

Machines 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 rustdesk

HTTP API

The 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.toml

For phone access, first ask the SDK which private address is safest to bind:

machine_presence network-info --config examples/machine_presence.toml --port 8765

If 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-bind

Then 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.

Local Agent Heartbeat

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 5

A fresh marker reports online, a stale marker reports degraded, and a missing or very old marker reports offline.

Autostart Helper

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.txt

Python

The 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.

Development Setup

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.

Verification

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.

About

Software-first machine presence control plane for local/private remote access workflows.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors