- Working with large codebases that don’t fit on your local machine
- Running resource-intensive agents on powerful remote servers
- Accessing development environments in the cloud
- Collaborating on shared infrastructure
Remote development uses the same parallel worktree workflow as local projects. Each remote task gets its own isolated worktree on the server.
Architecture
Emdash’s remote development stack:- Connection: ssh2 library (Node.js SSH2 client)
- Authentication: Password, private key, or SSH agent
- Credential storage: Keytar (OS keychain integration)
- File operations: SFTP over SSH
- Remote shells: Interactive PTY via ssh2’s shell API
- Git operations: Remote execution via
RemoteGitService
Key services
| Service | Purpose | Location |
|---|---|---|
SshService | Connection management, command execution | src/main/services/ssh/SshService.ts |
SshCredentialService | Secure password/passphrase storage | src/main/services/ssh/SshCredentialService.ts |
SshHostKeyService | Host key verification | src/main/services/ssh/SshHostKeyService.ts |
RemotePtyService | Remote terminal sessions | src/main/services/RemotePtyService.ts |
RemoteGitService | Git operations over SSH | src/main/services/RemoteGitService.ts |
Setting up SSH connections
Configure connection details
Enter your server information:
- Host: IP address or hostname (e.g.,
dev.example.com) - Port: SSH port (default: 22)
- Username: Your SSH username
- Authentication type: Agent, Key, or Password
Choose authentication method
Select one of three authentication types:
- SSH Agent (recommended)
- Private Key
- Password
Uses your local SSH agent for authentication. Best for security and convenience.Requirements:1Password users: Configure
- SSH agent must be running:
eval $(ssh-agent -s) - Key must be loaded:
ssh-add ~/.ssh/id_ed25519 - Verify with:
ssh-add -l
On macOS, if launching Emdash from Finder/Dock, the app may not detect your SSH agent. Launch from a terminal where the agent is configured, or use key/password authentication.
IdentityAgent in ~/.ssh/config:Test the connection
Click Test Connection to verify Emdash can connect to your server. A successful test will show:
- Connection established
- Server OS and shell information
- Git availability
Credential storage
Emdash uses Keytar (native OS keychain integration) to securely store SSH credentials:- macOS: Keychain Access.app
- Linux: libsecret (GNOME Keyring, KWallet)
- Windows: Windows Credential Manager
Remote PTY sessions
When you run an agent on a remote server, Emdash:- Opens an SSH connection to the server
- Creates a shell session via ssh2’s
client.shell() - Injects environment variables and changes to the worktree directory
- Spawns the agent CLI
- Streams output back to the local terminal UI in real-time
Security features
Shell allowlist
Remote PTY restricts shell binaries to a hardcoded allowlist (
/bin/bash, /bin/zsh, etc.) to prevent command injection.Env var validation
Environment variable keys are validated against
^[A-Za-z_][A-Za-z0-9_]*$ to prevent shell escaping.Argument escaping
All shell arguments pass through
quoteShellArg() from src/main/utils/shellEscape.ts.Connection pooling
Max 10 concurrent SSH connections. Pool warnings at 80% utilization.
Code example
FromRemotePtyService.ts:65-100:
Remote worktree management
Remote tasks use the same worktree isolation as local tasks:- Location:
<project>/.emdash/worktrees/<task-slug>/ - Branch:
emdash/<task-slug>-<hash> - Preserved files:
.env,.envrc, etc. (same as local)
Differences from local
Remote Git operations (commit, branch, status) work via
RemoteGitService, which executes Git commands over SSH.Connection management
Emdash maintains a connection pool with automatic cleanup:Connection events
SshService extends EventEmitter and emits:
connected: Connection establishederror: Connection errordisconnected: Connection closed
Command execution
All remote commands run in a login shell to ensure user configs are loaded:~/.ssh/configis loaded~/.gitconfigis available- Shell aliases and functions work
Troubleshooting
SSH agent not found
SSH agent not found
Symptom: Error: “SSH agent authentication failed: no agent socket found”Solutions:
- Start SSH agent:
eval $(ssh-agent -s) - Add your key:
ssh-add ~/.ssh/id_ed25519 - Verify:
ssh-add -l - If launching from GUI, restart Emdash from a terminal
- Or use private key/password auth instead
Host key verification failed
Host key verification failed
Symptom: Error: “Host key verification failed”Solutions:
- Ensure the host is in
~/.ssh/known_hosts - Run
ssh user@hostmanually to accept the host key - Or temporarily disable strict host checking in
~/.ssh/config:
Git not found on remote
Git not found on remote
Symptom: “Git is not installed on the remote server”Solution: Install Git on the remote server:
Permission denied on worktree directory
Permission denied on worktree directory
Symptom: “Failed to create worktree: Permission denied”Solution: Ensure your SSH user has write access to the project directory:
Security best practices
- Use SSH agent auth instead of storing passwords/keys
- Rotate credentials regularly
- Use dedicated SSH keys for Emdash (not your personal keys)
- Restrict remote user permissions to project directories only
- Enable SSH key-based auth and disable password auth on the server:
- Monitor SSH logs for suspicious activity