SSH integration

Run shell commands on remote hosts and pull files back into the workspace.

Endpoints

EndpointPurpose
GET /api/shell/ssh-hostsList configured SSH hosts.
POST /api/shell/ssh-runExecute a command on a remote host.
POST /api/shell/ssh-pullPull a remote file into the workspace.

Configuring hosts

KrowForge reads hosts from your standard ~/.ssh/config on the server. Entries look like:

Host prod-web
  HostName 10.0.1.42
  User deploy
  IdentityFile ~/.ssh/deploy_key

Hosts with IdentityFile (key-based auth) work out of the box. Password-based hosts are not supported โ€” use a key.

Listing hosts

GET /api/shell/ssh-hosts

Returns:

[
  { "host": "prod-web", "user": "deploy", "hostname": "10.0.1.42" }
]

Running a command

POST /api/shell/ssh-run
{ "host": "prod-web", "cmd": "tail -50 /var/log/nginx/error.log" }

Streams output as SSE just like the local shell API. Same 300 s timeout. The command runs as the user defined in ~/.ssh/config for that host.

Pulling files

POST /api/shell/ssh-pull
{ "host": "prod-web", "remote_path": "/var/log/nginx/error.log" }

Pulls the file via scp into the workspace at pulled/<host>/<basename>. Useful for fetching production logs or config snapshots into the agent's context.

Pulled files are real files in the workspace. They show up in the project tree, can be edited, can be added to git. If the file contains secrets, they're now in the workspace โ€” apply the workspace's secret handling policies.

Limits

  • File pulls capped at 50 MB.
  • Concurrent SSH jobs per workspace: 4.
  • All commands logged to receipts.

Why this exists

For the common pattern: "the prod server is doing something weird, let me grab a log and ask the agent". Without this you'd be context-switching between terminal tabs; with it, the agent gets the log directly.