Skip to main content

vssh — AI-native, drop-in ssh replacement (CLI binary + Python SDK)

Project description

vssh

An sshd-free, AI-native remote execution daemon for private networks.

vssh runs commands, transfers files, and manages long-running jobs on remote nodes over your private network (Tailscale, WireGuard/Wire, or LAN) — without running sshd on the target. It speaks a typed protocol over TLS 1.3 with Ed25519 key authentication, and every result comes back as structured evidence (stdout, stderr, exit code, duration, transport), which makes it a natural execution layer for AI agents and automation as well as for humans.

# Install (Linux/macOS, amd64/arm64)
curl -fsSL https://raw.githubusercontent.com/meshpop/vssh/main/install.sh | bash
# or
pip install vssh

Why vssh

Use vssh when the operator is often an AI agent or automation runtime, not a person typing into a terminal, and when you want execution that is:

  • sshd-free — the target runs vssh server, not OpenSSH.
  • typed & auditable — structured stdout/stderr/exit/duration evidence, not a raw text stream.
  • policy-gated — classify and block dangerous commands before they run.
  • durable — start/poll/cancel long-running jobs and collect artifacts.
  • name-routed — address nodes by name and capability, not raw IPs.

If all you need is an interactive human shell on a box that already runs sshd, use ssh directly — vssh deliberately does not wrap OpenSSH. See docs/WHY_VSSH.md.

Out of scope: operating the VPN mesh and fleet dashboards. Use Wire for the network layer and mpop for monitoring.


Install

One-line installer (recommended)

curl -fsSL https://raw.githubusercontent.com/meshpop/vssh/main/install.sh | bash

The installer detects your OS/arch, downloads the matching binary from the latest GitHub release, verifies its SHA-256 against the published checksums.txt, and installs to ~/bin. Options:

# Install a specific version
curl -fsSL .../install.sh | VSSH_VERSION=0.7.36 bash
# Install to a custom directory
curl -fsSL .../install.sh | INSTALL_DIR=/usr/local/bin bash

pip (CLI + Python SDK)

pip install vssh

This installs both the vssh CLI (the Go binary is fetched and checksum-verified for your platform on first run, cached under ~/.vssh/bin) and the Python SDK (from vssh import VSSH). See Python SDK.

From source

git clone https://github.com/meshpop/vssh && cd vssh
make build          # builds ./vssh
make install        # installs to /usr/local/bin (sudo)

Requires Go 1.25+.


Quick start

On the target node, start the daemon (no shared secret — auth is key-based):

vssh server                  # listens on :48291

Authorize a client by adding its public key to the server's ~/.vssh/authorized_keys (run vssh pubkey on the client to print it). For a fleet, scripts/enroll.sh <node> does this from a controller automatically. Then, from the client:

vssh run web1 "df -h"        # run a command, get structured output
vssh web1                    # open an interactive shell
vssh put ./app web1:/tmp/    # upload a file
vssh get web1:/var/log/x .   # download a file
vssh                         # fleet dashboard
vssh doctor --json           # diagnose binary, secret, config, peers, MCP

vssh run returns an evidence envelope — exit code, durations, transport, and the endpoints it tried — not just raw text.

For a multi-node fleet, scripts/enroll.sh <node> installs the daemon and cross-authorizes keys from a controller. See Security.


How it works

vssh client ──TLS 1.3──▶ vssh server ──▶ typed exec / file / job / RPC APIs ──▶ structured evidence
            (Ed25519 pinned)   (:48291)
  1. Transport — TLS 1.3 with the daemon's Ed25519 public key pinned (raw-key, not a CA). The client is TLS-first; set VSSH_REQUIRE_TLS=1 to refuse plaintext entirely.
  2. Host identity — the client verifies it reached the intended host by checking the daemon key against a trusted registry (on by default since 0.7.33), so a name can't be silently misrouted to the wrong machine.
  3. Authentication — per-node Ed25519 challenge–response (VAUTH1) only. There is no shared secret; a client is authorized by listing its public key in the server's ~/.vssh/authorized_keys (or /etc/vssh/authorized_keys).
  4. Policy — commands can be classified and gated before execution; per-key allow/deny lists, path scoping, and rate limits are available opt-in.

CLI reference

Execution
  vssh <node>                 Interactive PTY shell
  vssh shell <node>           Interactive PTY shell
  vssh run <node> <cmd>       Run a command (structured result)
  vssh exec <node> <cmd>      Alias for run
  vssh run-many <n1,n2> <cmd> Run across comma-separated nodes
  vssh run-batch <node> ...   Run multiple commands on one session

Typed APIs
  vssh rpc <node> <method> [json]       Call a typed daemon RPC
  vssh rpc-many <nodes> <method> [json] RPC across nodes
  vssh facts <node>                     Typed host facts
  vssh facts-many <nodes>               Facts across nodes

Jobs (long-running)
  vssh job-start <node> <cmd>   Start a background job
  vssh job-status <node> <id>   Job status
  vssh job-logs <node> <id>     Job logs
  vssh job-cancel <node> <id>   Cancel a job
  vssh artifact-collect <node>  Collect output artifacts

Files
  vssh put <local> <node:path>  Upload
  vssh get <node:path> <local>  Download

Fleet & ops
  vssh                Dashboard (default)
  vssh status         Dashboard
  vssh list           List known nodes
  vssh doctor [--json] Diagnose local setup
  vssh deploy <node>  Atomic binary install + restart + verify
  vssh server         Run the daemon
  vssh mcp            Run the MCP server (for AI agents)
  vssh setup          First-run self-configuration
  vssh version        Show version
  vssh help           Full help

MCP server (for AI agents)

The MCP server is built into the binary — no separate install:

vssh mcp

It exposes typed tools that return execution evidence, so an agent can route, gate, and run work with an audit trail:

Tool Purpose
vssh_doctor Diagnose binary, secret source, config, peers, MCP readiness
vssh_hosts_list List known hosts (addresses, tags, capabilities, health) for routing
vssh_route_select Pick the best host by capability, tag, and health
vssh_exec_safe Run read-only/diagnostic commands (dangerous ones blocked)
vssh_exec Run with policy checks; allow_dangerous after explicit approval
vssh_exec_routed Route first, then execute with policy + evidence
vssh_policy_check Classify a command before running it
vssh_status, vssh_list Status and peer inventory

Commands matching destructive patterns (rm -rf, shutdown, reboot, docker rm, kubectl delete, systemctl restart, …) are blocked unless the caller sets allow_dangerous: true after explicit human approval. Every response is an evidence envelope with timestamps, the policy decision, target, command, and the structured result. See docs/CODEX_ORCHESTRATION.md.


Python SDK

from vssh import VSSH

client = VSSH(secret="a-long-random-value")

client.exec("web1", "uptime")              # -> ExecResult(stdout, exit_code, ...)
client.exec_many(["web1", "db1"], "uptime")
client.facts("web1")                        # typed host facts
job = client.job_start("web1", "long-task")
client.job_status("web1", job["job_id"])
client.doctor()

The SDK is a thin client over the installed vssh binary (it does not reimplement the protocol), so it inherits the same transport, auth, and policy. Full method list: exec, exec_many, rpc, rpc_many, facts, facts_many, job_start, job_status, job_logs, job_cancel, artifact_collect, doctor. See docs/PYTHON_SDK.md.


Configuration

Node inventory — ~/.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": ["gpu"], "capabilities": ["cuda", "ollama"], "monitor_port": 8721 }
}

Nodes are also discovered automatically from a Wire coordinator, Tailscale, and a local cache. Do not commit a real servers.json, hostnames, VPN IPs, or secrets — keep inventory outside the repo and use example values in docs.

Per-host users — ~/.wire/users.json

{ "web1": "deploy", "db1": "postgres" }

Environment variables

Variable Purpose
VSSH_PORT Daemon listen port (default 48291).
VSSH_REQUIRE_TLS 1 = refuse non-TLS connections.
VSSH_NO_HOSTKEY_VERIFY 1 = opt out of host-identity verification (not recommended).
VSSH_BIN (pip wrapper) use this binary instead of downloading.
VSSH_VERSION (pip wrapper / installer) pin the binary release to fetch.
VSSH_HOME Override the ~/.vssh directory.

Security

  • The native daemon grants authorized peers command execution and file transfer as the configured user — treat access as root-equivalent.
  • Authentication is per-node Ed25519 keys (VAUTH1) only; authorize clients via ~/.vssh/authorized_keys. Enforce encryption with VSSH_REQUIRE_TLS=1.
  • The VPN (WireGuard/Tailscale) encrypts the tunnel but is not a substitute for vssh authentication — always set a strong secret or enroll keys, and firewall the listen port.
  • Report vulnerabilities privately via GitHub Security Advisories.

Full model and hardening steps: SECURITY.md.


Documentation

Building & contributing

make build      # build ./vssh
make test       # go test ./... + Python SDK tests
make release    # cross-compile linux/darwin × amd64/arm64 into dist/

See CONTRIBUTING.md.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vssh-4.3.1.tar.gz (182.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vssh-4.3.1-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

File details

Details for the file vssh-4.3.1.tar.gz.

File metadata

  • Download URL: vssh-4.3.1.tar.gz
  • Upload date:
  • Size: 182.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for vssh-4.3.1.tar.gz
Algorithm Hash digest
SHA256 72b0d4e81ea195a1a97f28eb55a817bba1b5dc434caa6541b73bdbafa4c224ac
MD5 f9625564aa16ccefb4e30ebdea055ae2
BLAKE2b-256 62bdf24985e39fda517b7fe14c8d7672ba1e3b56e96ab9a2a021d2c487bb83f1

See more details on using hashes here.

File details

Details for the file vssh-4.3.1-py3-none-any.whl.

File metadata

  • Download URL: vssh-4.3.1-py3-none-any.whl
  • Upload date:
  • Size: 11.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for vssh-4.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 957828a39351aaeaf696db4c2f6cbee5dcee4a7994bd0a3483ade3e318457d9c
MD5 f142b24264feb66a980ff73c10455ea6
BLAKE2b-256 76dff40491eb421ca9f871b2d3cece498ba5dbeb4bb585df25ebd87772207c96

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page