ssh into any instance your workspace owns, with the keypair you already have. Once your public key is registered, the whole OpenSSH toolchain works: interactive shells with a PTY, scp and sftp for files, port forwarding with -L, and VS Code Remote SSH for editing straight on the box.
Nothing is installed in your image. The platform injects the SSH server into the sandbox at runtime, so SSH works on agent37-hermes, agent37-openclaw, and every custom image you build, including images that ship no sshd and no shell tooling of their own.
Quickstart
ssh setup is a one-time step and safe to re-run. It saves your API key to ~/.config/agent37/config.json (prompting for it if AGENT37_API_KEY is not set), registers ~/.ssh/id_ed25519.pub with your workspace under your machine’s hostname (generating the keypair if you do not have one, and treating an already-registered key as done), and writes a managed block into ~/.ssh/config:
~/.ssh/config
ssh keeps the first value it finds for each setting and a Host * stanza further down would otherwise override it. IdentityFile names the key setup registered, so the connection still works if your existing config sets IdentitiesOnly yes.
That block is the whole client-side configuration. ProxyCommand is what carries the SSH stream (there is no port to dial directly), and setup writes it as the absolute path of the CLI that wrote it, so it works without a global install. Run under npx that path is inside the npx cache, so npm install -g agent37 is the durable form; if ssh ever reports the ProxyCommand is missing, re-run agent37 ssh setup. User root is the login user on every instance. ServerAliveInterval keeps an idle session from being dropped. Host-key checking is off because an instance regenerates its host key when the platform relocates it, and the tunnel is already TLS plus your API key, so a pinned known-hosts entry would warn on a legitimate move.
You do not have to touch ~/.ssh/config at all. agent37 ssh connects with the same options inline, and takes plain ssh arguments after --:
How it works
ssh runs agent37 tunnel as its ProxyCommand, which pipes the SSH byte stream over a WebSocket to https://{instanceId}-22022.agent37.app, carrying your sk_live_ key in the X-Agent37-Key header. The Agent37 edge authenticates that key, checks your workspace owns the instance, and hands the stream to the instance’s SSH server, which then authenticates your SSH public key. The instance has no public IP and no listening port on the internet.
So there are two independent layers, and a connection needs both:
- Your workspace API key, checked at the edge. Revoking the key closes the door for every SSH client using it.
- Your SSH private key, checked by the SSH server inside the instance. The platform never sees it; only the public half is registered.
Manage keys
ssh setup calls these for you. Use them directly to enroll a teammate’s key, rotate keys from CI, or audit what is registered. The dashboard lists the same keys under API keys at dashboard/cloud/api-keys.
Register a key
string
required
One OpenSSH public key line, the contents of a
.pub file: ssh-ed25519 AAAA... you@laptop. Accepted types are ssh-ed25519, ssh-rsa, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, and sk-ecdsa-sha2-nistp256@openssh.com. A private key, an unsupported type, or a malformed line returns 400 invalid_request.string
A label for the key, such as
laptop. Optional: omit it and the key’s trailing comment is used.string
The key’s id. Pass it to
DELETE /v1/ssh-keys/{id} to revoke.string | null
The label you sent, the key’s trailing comment when you omitted
name, or null when the key carries no comment either.string
The key’s SHA256 fingerprint, the same string
ssh-keygen -lf ~/.ssh/id_ed25519.pub prints. Compare it locally to confirm you registered the key you meant to.string
The key type, for example
ssh-ed25519.integer | null
When the key was registered, in epoch seconds.
409 ssh_key_exists. A workspace holds at most 20 keys; the 21st returns 400 invalid_request.
List keys
curl
response
fingerprint.
Delete a key
curl
response
404 not_found, and another workspace’s key id returns the same 404.
Keys are workspace-wide
A registered key opens every instance your workspace owns, current and future. There are no per-instance keys. Key changes reach running instances automatically, within about 25 seconds of the API call. An instance you create after registering a key has it from the moment it boots, with nothing to wait for.Copy files
scp and sftp work as they do anywhere, recursive copies included:
VS Code Remote SSH
With the~/.ssh/config block in place, the instance is an ordinary SSH host to VS Code. Install the Remote - SSH extension, run Remote-SSH: Connect to Host, and enter ab12cd34ef.agent37.app. The instance shows up in the host list on later connections.
VS Code installs its remote server into the instance on the first connect, so that connect is the slow one and later ones come up fast. Any editor that speaks plain SSH works the same way.
Revoke
Two ways, neither on a timer. There are no TTLs and no expiring sessions, so access lasts until you take it away.- Delete the SSH key (
DELETE /v1/ssh-keys/{id}) to stop that keypair from logging in anywhere in the workspace. - Revoke the
sk_live_API key to stop every SSH client configured with it, whatever keypair it holds.
Rules and limits
- You log in as
root. Every instance has exactly one SSH user, and password authentication is off: keys only. - A stopped instance refuses connections. Start it first. Connecting to a sleeping instance wakes it, the same as any other request to its URLs.
- An open session counts as activity. Keepalives keep bytes moving, so an auto-sleep instance stays awake for as long as you are connected, billing at the 4x awake rate. Close the session when you are done.
- Port
22022can never be exposed without a credential. It is a reserved platform port: no public port and no signed URL can be minted for it, so a WebSocket carrying an authenticatedsk_live_key is the only way in. - 20 SSH keys per workspace, one entry per fingerprint.
- SSH traffic is ordinary instance traffic and is not metered separately.