Python SDK for the vssh AI-native remote execution daemon
Project description
vssh
AI-native remote execution daemon and protocol for Tailscale/private networks.
VSSH is designed for two audiences:
- operators who need sshd-free execution on private nodes
- Codex/LLM/runtime orchestrators that need typed execution APIs, long-running jobs, policy, and machine-readable evidence
Scope
vssh is a standalone remote execution agent product. Its core value is
the native vssh server daemon path: command execution, files, jobs, policy,
and evidence over a private network such as Tailscale.
vssh is not an OpenSSH wrapper. Tailscale + sshd already handles normal remote shell, so the product surface stays focused on the native daemon path.
Why Use vssh
Use vssh when the operator is an AI agent or automation runtime, not a human typing into a terminal.
vssh is better than plain SSH when you need:
- sshd-free execution on private nodes
- structured stdout/stderr/exit/duration evidence
- policy checks before risky actions
- durable jobs, logs, cancellation, and artifact collection
- typed server APIs for facts, services, logs, GPU/model state, and health
If the feature is only "SSH, but shorter", it does not belong in vssh. See Why vssh.
Out of scope here: operating the VPN mesh itself and fleet-wide monitoring dashboards—use Wire and mpop for those layers.
Implementation note: internal/adapter is discovery-oriented (Probe
over configured paths). The product direction is to make internal/server the
first-class execution path and keep internal/ssh for discovery helpers and
legacy internals only.
Documentation
- Full stack snapshot (Wire + mpop + vssh) — versions, PyPI, architecture, MCP, deferred work
- Why vssh
- Python SDK
- Codex orchestration notes
- Public repository audit
- 한국어 README
- CHANGELOG.md
- SECURITY.md
- HELP.md
Features
- Native protocol - sshd-free mode through
vssh server - AI-oriented execution - structured stdout/stderr/exit/duration/evidence
- Job semantics - designed for long-running work, cancellation, and logs
- File/artifact APIs - transfer and collect files without broad shell UX
- Policy hooks - classify and gate actions before execution
- Name-based access - route by node name rather than raw addresses
- Auto-discovery - finds nodes via Tailscale, config, or legacy sources
- Runtime-oriented results - MCP paths return structured execution evidence for Codex/LLM orchestration
Quick Start
# Install
curl -fsSL https://raw.githubusercontent.com/meshpop/vssh/main/install.sh | bash
# Run native daemon on a node
VSSH_SECRET=change-me vssh server
# From a client on the same private network
VSSH_SECRET=change-me vssh run web1 "df -h"
# Show status
vssh # Dashboard
vssh list # List all nodes
Commands
vssh Show dashboard (default)
vssh server Run native daemon
vssh <node> Open native shell
vssh run <node> <cmd> Run command through native daemon
vssh run-many <nodes> <cmd> Run command across comma-separated nodes
vssh rpc <node> <method> [json] Call typed daemon RPC
vssh rpc-many <nodes> <method> [json] Call RPC across nodes
vssh facts <node> Return typed daemon facts
vssh facts-many <nodes> Return facts across comma-separated nodes
vssh job-start <node> <cmd> Start a long-running daemon job
vssh job-status <node> <id> Return job status
vssh job-logs <node> <id> Return job logs
vssh job-cancel <node> <id> Cancel a job
vssh shell <node> Open native shell
vssh put <src> <dst> Upload through native daemon
vssh get <src> <dst> Download through native daemon
vssh exec <node> <cmd> Alias for native run
vssh list List all nodes
vssh status Show dashboard
vssh version Show version
vssh help Show help
Dashboard
vssh dashboard
SERVER IP LOAD MEM DISK UPTIME
--------------------------------------------------------
● web1 192.0.2.10 0.15 8% 40% 48 days
● web2 192.0.2.11 0.77 6% 63% 100 days
● db1 192.0.2.20 1.53 9% 30% 78 days
3/3 online
Execution Flow
The target product flow is:
vssh client
-> Tailscale IP / MagicDNS
-> vssh daemon
-> typed exec/file/job/service APIs
-> structured evidence
There is deliberately no OpenSSH wrapper command. If a node already has sshd
and all you need is a shell, use ssh directly.
Connection Flow
vssh tries multiple endpoints in order:
- Tailscale / VPN IP - Most reliable when private network is up
- LAN IP - Same local network
- Public IP - Fallback for remote access
Data Sources
Node discovery:
- Wire daemon - If Wire VPN is running
- Wire coordinator - If coordinator URL is configured
- Tailscale - If Tailscale is running
- Config file - Manual server list (~/.vssh/servers.json)
- Cache - Previously discovered nodes
Configuration
Servers config: ~/.vssh/servers.json
{
"web1": {
"ip": "192.0.2.10",
"user": "deploy",
"tags": ["linux", "web"],
"capabilities": ["docker"]
},
"gpu1": {
"ip": "192.0.2.20",
"user": "ubuntu",
"tags": ["linux", "gpu", "ollama"],
"capabilities": ["cuda", "ollama"],
"monitor_port": 8721
},
"mac1": {
"ip": "192.0.2.30",
"user": "admin",
"os": "darwin",
"tags": ["mac", "browser"],
"capabilities": ["browser"]
}
}
Do not commit real ~/.vssh/servers.json, Wire config, hostnames, VPN IPs, or secrets. Keep local inventory files outside the repository and use example values in documentation.
vssh.hosts.list returns these fields as routing metadata for agents, together
with inferred capabilities and a health object.
VSSH does not embed a monitoring daemon. If you run a separate monitor such as
meshclaw monitor or mpop agent, add either monitor_port or monitor_url
per host. Agent tools can then request include_health: true to merge live
/api/node/status data into the host record before routing.
User mapping: ~/.wire/users.json
{
"web1": "deploy",
"db1": "postgres",
"app1": "deploy"
}
Native Protocol
vssh can work without sshd using its native protocol:
# On server
vssh server # Start vssh server on :48291
# On client
vssh shell web1 # Native shell
vssh run web1 "df -h" # Native exec
vssh put file web1:/tmp # Native upload
vssh get web1:/tmp/x . # Native download
Set VSSH_SECRET on both client and server before exposing the native server. See SECURITY.md.
Codex / Runtime Usage
VSSH can be used as an execution substrate for AI-native runtimes:
- route work to nodes by name
- preserve quoted, piped, and multiline commands
- return
stdout,stderr,exit_code, duration, transport, and endpoint attempts - record evidence in Matrix events, task ledgers, or audit logs
Run the MCP server:
vssh mcp
Python SDK:
python -m pip install vssh
from vssh import VSSH
client = VSSH(secret="change-me")
facts = client.facts("web1")
fleet = client.facts_many(["web1", "db1"])
results = client.exec_many(["web1", "db1"], "uptime")
job = client.job_start("web1", "long-running-command")
The Python SDK is a client layer for AI agents and automation. It calls the
installed Go vssh binary instead of reimplementing the daemon protocol.
Agent-facing MCP tools:
| Tool | Purpose |
|---|---|
vssh.hosts.list |
List known hosts for routing |
vssh.exec.safe |
Execute read/diagnostic commands with policy blocking |
vssh.exec |
Execute with policy checks and optional allow_dangerous |
vssh.route.select |
Select the best host by capability, tag, and health |
vssh.exec.routed |
Route first, then execute with policy/evidence |
vssh.policy.check |
Classify a command before execution |
vssh_exec, vssh_list, vssh_status |
Backward-compatible tool names |
Commands matching destructive/service-impacting patterns such as rm -rf,
shutdown, reboot, docker rm, kubectl delete, and systemctl restart
are blocked unless the caller sets allow_dangerous: true after explicit human
approval. Every execution response is an evidence envelope with timestamps,
policy decision, target, command, timeout, and the structured execution result.
vssh.hosts.list returns agent-friendly records:
{
"name": "gpu1",
"addresses": {"vpn": "192.0.2.20"},
"user": "ubuntu",
"tags": ["gpu", "linux", "ollama"],
"capabilities": ["cuda", "gpu", "linux", "ollama"],
"health": {"status": "unknown", "reason": "no live health signal"}
}
Routed execution lets agents ask for capabilities instead of hard-coding a host:
{
"required_capabilities": ["cuda", "ollama"],
"preferred_tags": ["gpu"],
"avoid_health": ["offline", "degraded"],
"include_health": true,
"command": "ollama list",
"timeout_seconds": 20
}
VSSH evaluates candidates, records the route decision, checks command policy, and then executes on the selected host.
See docs/CODEX_ORCHESTRATION.md.
Public Repository Hygiene
This repository should contain source and public examples only. Release binaries are published as GitHub Release assets, not committed to Git. See docs/PUBLISHING_AUDIT.md.
Building
make build # Build vssh
make install # Install to /usr/local/bin
make release # Build for all platforms
Contributing
See CONTRIBUTING.md.
Requirements
- Go 1.21+ (for building)
- No SSH client required for native daemon mode
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vssh-4.2.0.tar.gz.
File metadata
- Download URL: vssh-4.2.0.tar.gz
- Upload date:
- Size: 85.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01efe69aa69977511fd2e7bd81c1a0b4dab9a1f3b8a0c934d112683114ec63ef
|
|
| MD5 |
34350ee652f586def2a728f639967e09
|
|
| BLAKE2b-256 |
4bdea483a0dafea8c5878af2a98e3c411161e6c2ccc5f5c9ffd35ed8313c117b
|
File details
Details for the file vssh-4.2.0-py3-none-any.whl.
File metadata
- Download URL: vssh-4.2.0-py3-none-any.whl
- Upload date:
- Size: 7.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85cbfea07e3b3b271fc2fc05fa159477592a40bad42074c27132f1e165875ed8
|
|
| MD5 |
9806227d6d882063ff2d2a22aed8f632
|
|
| BLAKE2b-256 |
a02e91979af94fd35320af9bbe837f85859b88b1d9f321018191b67a88d3ecf6
|