Transports
session_create takes a transport: "local", "ssh", or "docker". Any other
value is an error.
Every transport needs a POSIX shell and base64 on the target: execkit sends each
command base64-encoded and decodes it there.
Local
A shell on the machine running the server.
// session_create {"transport":"local"} -> {"session_id":"a3f9-1_local"}
The agent reaches whatever the server’s user can. Run that user with least privilege.
SSH
// session_create {
// "transport":"ssh", "host":"web-01", "user":"deploy",
// "key_path":"deploy_ed25519" // or "password":"..."
// }
Required: host, plus a user and a way to authenticate, unless your ssh config
supplies them (below). Optional: port (default 22) and fingerprint to pin an
exact host key.
Host aliases from your ssh config
host can be a Host alias from the operator’s ssh config, read from
<key dir>/config (so ~/.ssh/config by default). For an entry like this:
Host web
HostName web-01.internal
User deploy
Port 2222
IdentityFile ~/.ssh/deploy_ed25519
the agent only needs {"transport":"ssh","host":"web"}. HostName, User,
Port and IdentityFile fill in whatever the call leaves out; arguments the
agent passes take precedence. Only exact Host names match: wildcard patterns,
Match blocks and Include are ignored.
Authentication
execkit uses the first of these that applies:
password, if given.key_path, if given.- The alias’s
IdentityFileentries, in order, thenid_ed25519,id_ecdsaandid_rsain the key directory. The first file that exists inside the key directory is used. If the server rejects it, execkit does not try the next one; passkey_pathto choose a different key.
Every key must live inside the key directory (~/.ssh by default, or
EXECKIT_MCP_KEY_DIR). Out-of-bounds or traversal paths are rejected with a
generic error that does not leak whether the path exists. An IdentityFile that
points outside the key directory is skipped.
Host keys
Host-key handling is safe by default:
-
Verified against execkit’s own
known_hosts(TOFU). The file is~/.execkit/known_hostsunlessEXECKIT_MCP_KNOWN_HOSTSoverrides it. The first connection to a host records its key; a changed key is rejected as a likely man-in-the-middle. Entries are keyedhoston port 22 and[host]:portotherwise, so two ports on one host are verified separately. -
Not your OpenSSH
~/.ssh/known_hosts. Before v0.9 execkit wrote its pins to~/.ssh/known_hosts. It now keeps its own file and does not read the old pins, so after upgrading, the first connection to each host records its key again. To carry your pins over instead, copy execkit’s lines (host SHA256:...) across:mkdir -p ~/.execkit && chmod 700 ~/.execkit grep -E '^[^ ]+ SHA256:' ~/.ssh/known_hosts >> ~/.execkit/known_hostsOld pins were keyed by bare host whatever the port. A line for a host you reached on a port other than 22 must be rewritten as
[host]:portafter copying (for exampleexample.com SHA256:...becomes[example.com]:2222 SHA256:...); left as is, it is read as the port-22 pin, so a later port-22 connection to that host fails as a key mismatch.If
EXECKIT_MCP_KNOWN_HOSTSpoints at an OpenSSH-format file, connecting to a new host fails with an error saying so, instead of writing to that file. See Upgrading to 0.9 for the other changes. -
Pin a key by passing
fingerprint("SHA256:...") for an exact match.
Connect timeout
Connecting, the SSH handshake and authentication share one 15 second budget. An
unreachable host or a server that stalls during auth fails session_create with
a timeout error instead of hanging.
The home directory behind ~/.ssh and ~/.execkit resolves by priority
($HOME, then the system passwd database), so defaults are correct even when
$HOME is unset, as in a service-launched server.
For throwaway or test hosts only, EXECKIT_MCP_INSECURE_ACCEPT_ANY_HOSTKEY=1
disables host-key verification. Never use it in production.
Docker
// session_create {"transport":"docker","container":"app-web-1"}
Runs docker exec against any container the daemon can see, so the agent reaches
whatever your Docker context exposes. If the container does not exist or is not
running, session_create fails with an error that names it. The container needs
a POSIX /bin/sh. Grant the server Docker access only when you
want that, and scope the daemon or context accordingly.
Remote workspace undo
SSH and Docker sessions support Checkpoints: a git-backed snapshot of the workspace you can restore on demand.