Skip to content
Agent Workspaces
Agent

ssh

- `apps/emdash-desktop/src/core/services/ssh/node/` — physical connection generation, credentials, stable SSH proxy, configuration resolution, and bounded channel operations - `apps/emdash-desktop/src/core/services/hosts/node/connection-supervisor.ts` — sole remote recovery

From plugin
emdash
6.3k33 skills33 agents

Agent definition

ssh.md

Risky Area: SSH And Shell Escaping

Main Files

  • `apps/emdash-desktop/src/core/services/ssh/node/` — physical connection generation, credentials,

stable SSH proxy, configuration resolution, and bounded channel operations

  • `apps/emdash-desktop/src/core/services/hosts/node/connection-supervisor.ts` — sole remote

recovery owner (ADR 0008); SSH and Wire adapters must not add independent reconnect loops

  • `src/main/core/fs/impl/ssh-fs.ts`
  • `src/main/core/pty/ssh2-pty.ts`
  • `src/main/core/terminals/impl/ssh-terminal-provider.ts`
  • `src/main/utils/shellEscape.ts`

Rules

  • treat remote shell construction as security-sensitive
  • use shared escaping and validation helpers
  • do not bypass path-safety or shell validation helpers
  • verify how a change affects both connection setup and command execution
  • Fence callbacks and late resources by physical generation; preserve logical client identity

across outages, but never across destination identity edits.

  • Do not automatically restart a healthy-but-unresponsive workspace daemon to repair transport;

sessions and other desktop clients may still depend on it.

  • Test and Save share credential-draft resolution. Blank secrets can retain stored credentials

only for an unchanged destination/account/authentication method (and unchanged key selection for passphrases). Changing identity must not silently carry an old secret forward.

  • Enable TCP_NODELAY on every physical ssh2 client immediately after `connect()` assigns its

socket, before waiting for authentication/ready. ProxyJump and ProxyCommand use child-stdio Duplex streams without `setNoDelay`; ssh2 safely skips these, so this does not configure the proxy child's TCP sockets.

  • An edit test loads the saved identity in the main process, tests the draft on a separate

ephemeral connection, and never writes secrets or disconnects the saved connection. Stored secrets remain wrapped until SSH connect-config assembly; never send them to the UI.

  • Connection saves prepare encrypted credential records before a synchronous SQLite transaction,

then atomically commit the row, secrets, and identity bindings. Reject a stale row or secret snapshot rather than overwriting a concurrent save; never await inside the transaction.

  • Credential bindings use the effective destination and, for passphrases, the selected key path

and content fingerprint. Resolve aliases before credential reuse, including normal reconnects. Legacy passwords may be retained for a verified unchanged destination; legacy passphrases lack a verifiable key binding and require re-entry once. Keep bindings with the encrypted secret so readers cannot mix a credential with another generation's identity.

  • An unchanged key with an unbound legacy passphrase must request re-entry before Save, Test,

or reconnect. A rejected save preserves both the row and secret; never interpret an unverified legacy passphrase as absent and silently delete it during a name-only edit.

  • Local proxy children (ProxyJump `ssh -W`, ProxyCommand) and `ssh -G` run with `windowsHide`

and piped stdio, so nobody can answer their prompts. ProxyJump passes `BatchMode=yes`, but OpenSSH does not forward it to earlier `-J` hops, and a ProxyCommand can prompt. On Windows such a prompt waits on a hidden console until the connect timeout, so proxy cleanup must kill the whole process tree there (signals end only `cmd.exe` or the outer `ssh.exe`).

  • Expand user-relative SSH key paths with the OS home-directory helper, not HOME alone;

Windows environments may provide USERPROFILE without HOME.

  • `ssh2` is patched (`patches/ssh2@<version>.patch` via `pnpm.patchedDependencies`) to keep

OpenSSH certificates from the agent and to spawn its Windows agent helpers (`pagent.exe`, `cygpath`) with `windowsHide`. When bumping `ssh2`, regenerate the patch, dropping only the parts upstream has released (certificates: mscdex/ssh2#1495), and keep `ssh-agent-certificate.test.ts` and `ssh-agent-windows-helpers.test.ts` passing.

Read more
@generalaction
Ships withemdash

Emdash is the Open-Source Agentic Development Environment (🧡 YC W26). Run multiple coding agents in parallel. Use any provider.

Stars on GitHub

Momentum

stars in total
6.3k
Star history of generalaction/emdash on GitHub, a chart by star-history.com

Other agents on emdash.

acp-runtime

acp-runtime

Agent

The ACP runtime is the domain service that serves the ACP API contract. It owns the host-scoped dependencies needed to run…

core-modules

core-modules

Agent

This page defines the target organization of `packages/core/src/`. Core is organized by module type so that shared domain APIs…

git-runtime

git-runtime

Agent

Git is split into a transport contract and a host-scoped runtime. Renderer, desktop, and workspace-server code share the Wire…

main-process

main-process

Agent

The main process is organized into domain modules under `src/main/core/`. Each domain typically has a `controller.ts` (RPC…

path-system

path-system

Agent

`@emdash/core/primitives/path/api` is the source of truth for portable file identity and lexical path operations. The detailed…

More agents from other plugins.

api-builder

api-builder

Agent

Deprecated placeholder. Do not use; follow root AGENTS.md and package instructions instead.

happier6d2.2k
@happier-dev@happier-devInstall Agent

Questions about ssh.

Which coding agents can use ssh?
ssh installs in Claude Code and Cursor: each loads subagents from .claude/agents, so copy the file there. Flowy's auto-invocation runs in Claude Code only.