VS Code Extensions
Remote Diff SSH

Remote Diff SSH

by taeman

Compare and safely transfer files with a remote server over SSH

Downloads

1

Rating

(0)

Version

0.5.0

Last updated

Aug 10, 2026

Compare files in a local VS Code workspace with files on a remote server over SSH.

Remote Diff SSH is a free public beta. Transfer one file at a time with explicit confirmation, conflict protection, verified backups, and no remote project-file deletion commands.

Marketplace versions are distributed as pre-releases while the extension is in public beta.

Why Remote Diff SSH

  • Review server differences inside VS Code before transferring anything.
  • Keep Upload disabled until each workspace explicitly enables it.
  • Back up and verify both local downloads and remote uploads.
  • Detect remote changes before overwriting another developer's work.
  • Connect directly from your machine to your SSH server without a hosted relay.

Requirements

  • Visual Studio Code 1.125.0 or newer
  • An SSH server reachable from the machine running VS Code
  • SSH password, private-key, or agent authentication

Getting started

  1. Open the local project folder that corresponds to the remote project.
  2. Create .vscode/remote-diff.json in that project. Copy the single-server example, the multi-server example, or use one of the connection recipes below.
  3. Update the SSH connection and remote path values.
  4. Open the Command Palette (Cmd+Shift+P on macOS or Ctrl+Shift+P on Windows/Linux) and run Remote Diff: Test Connection.
  5. On the first connection, verify the displayed server fingerprint with your server administrator before selecting Trust Fingerprint.
  6. Open a text file inside the workspace and run Remote Diff: Compare Current File. The command is also available from editor and Explorer context menus.
  7. Run Remote Diff: Scan Workspace to populate the Remote Diff SSH view in Explorer.
  8. To replace a local file with its remote version, use Remote Diff: Download Remote File from the editor, Explorer, or a Modified/Remote only result. Review the paths in the confirmation dialog before continuing.

The real .vscode/remote-diff.json file is ignored by Git to reduce the risk of publishing server details. Commit only the example file.

Connection setup guide

Option 1: Server password (easiest)

Create .vscode/remote-diff.json:

{
  "name": "Development server",
  "host": "server.example.com",
  "port": 22,
  "username": "deploy",
  "remotePath": "/var/www/example",
  "authentication": "password"
}

Run Remote Diff: Test Connection. Enter the SSH password when prompted. The password is saved in VS Code SecretStorage on the current computer and is never written to the JSON file. Use Remote Diff: Set or Update Server Password when the password changes, or Remote Diff: Forget Server Password to remove it.

Option 2: Private key

Only configure the private key, not its .pub public-key file:

{
  "name": "Development server",
  "host": "server.example.com",
  "port": 22,
  "username": "deploy",
  "remotePath": "/var/www/example",
  "authentication": "auto",
  "privateKeyPath": "~/.ssh/id_ed25519",
  "useAgent": false
}

Run Remote Diff: Test Connection. If the key is encrypted, enter its passphrase when prompted. The passphrase is stored in VS Code SecretStorage.

Option 3: SSH agent

Make sure the key is already loaded into your operating system's SSH agent, then use:

{
  "name": "Development server",
  "host": "server.example.com",
  "port": 22,
  "username": "deploy",
  "remotePath": "/var/www/example",
  "authentication": "auto",
  "useAgent": true
}

Enable uploads

Downloads are available immediately. Uploads remain disabled until the workspace explicitly opts in:

{
  "enableUpload": true
}

Add enableUpload to the same connection object; do not create a second JSON object. Compare or Scan before uploading so the extension can detect whether the remote file changed.

Connection troubleshooting

Message or symptom What to check
Connection timeout or refused Confirm host, port, VPN/firewall access, and that SSH is running on the server.
Authentication failed Confirm username and authentication method. For password mode, run Set or Update Server Password and try again.
Unable to read SSH private key Use the private-key path, not the .pub file, and confirm that the file exists on the computer running VS Code.
Host fingerprint rejected or changed Verify the server fingerprint with an administrator. If the server was legitimately replaced, run Reset Credentials and Host Trust and reconnect.
Permission denied during Scan, Download, or Upload Confirm that the SSH user can read remotePath; uploads also require write access.
Local and remote files do not correspond Open the correct local project root and ensure remotePath points to the matching remote project root.

Configuration

One server

The original flat configuration remains supported. Copy .vscode/remote-diff.single.example.json to .vscode/remote-diff.json, then edit the values:

{
  "name": "Staging server",
  "host": "staging.example.com",
  "port": 22,
  "username": "deploy",
  "remotePath": "/var/www/example",
  "authentication": "auto",
  "privateKeyPath": "~/.ssh/id_ed25519",
  "useAgent": true,
  "keyboardInteractive": false,
  "connectTimeout": 10000,
  "enableUpload": false,
  "backup": {
    "maxVersionsPerFile": 5,
    "maxAgeDays": 30,
    "maxTotalSizeMB": 100
  },
  "remoteBackup": {
    "maxVersionsPerFile": 5,
    "maxAgeDays": 30,
    "maxTotalSizeMB": 100
  },
  "ignore": [
    ".git/**",
    "node_modules/**",
    ".env"
  ]
}

Multiple servers

Use targets when one workspace maps to environments such as development, staging, and production. Copy .vscode/remote-diff.multi.example.json to .vscode/remote-diff.json, or start with:

{
  "defaultTarget": "development",
  "targets": {
    "development": {
      "name": "Development",
      "environment": "development",
      "host": "dev.example.com",
      "port": 22,
      "username": "deploy",
      "remotePath": "/var/www/example",
      "authentication": "password",
      "enableUpload": true
    },
    "production": {
      "name": "Production",
      "environment": "production",
      "host": "prod.example.com",
      "port": 22,
      "username": "deploy",
      "remotePath": "/var/www/example",
      "authentication": "password",
      "enableUpload": false
    }
  }
}

Run Remote Diff: Select Server to switch targets. The selected target is remembered for the current workspace and shown in the VS Code status bar. Switching targets clears old comparison snapshots, so Compare or Scan again before transferring a file.

Each target keeps its own password, key passphrase, and trusted host fingerprint in VS Code secure storage. A target marked "environment": "production" is highlighted in the status bar and requires typing its configured name before an upload can continue. Keep production uploads disabled until they are explicitly needed.

Field Required Description
name No Friendly name for the remote target.
environment No Target safety label: development, staging, production, or other. Production adds a warning and typed upload confirmation. Defaults to other.
host Yes SSH hostname or IP address.
port No SSH port. Defaults to 22.
username Yes SSH username.
remotePath Yes Remote directory corresponding to the workspace root.
authentication No auto uses the existing private-key/agent flow. password securely prompts for and stores a server password. Defaults to auto.
privateKeyPath No Path to an SSH private key. ~/ is supported.
hostFingerprint No Pinned SHA256: host fingerprint. When omitted, the extension asks before trusting the first fingerprint.
useAgent No Use SSH_AUTH_SOCK. Defaults to true.
agentSocket No Override the SSH agent socket path.
keyboardInteractive No Enable interactive authentication prompts. Defaults to false.
connectTimeout No Connection timeout in milliseconds. Defaults to 10000.
enableUpload No Enable guarded uploads. Defaults to false.
ignore No Glob patterns to exclude from comparison.
backup No Local backup retention: 5 versions per file, 30 days, and 100 MB total by default.
remoteBackup No Remote backup retention with the same defaults, applied after successful uploads.

Do not place passwords, private-key contents, or other secrets in this file. For password authentication, set "authentication": "password", then run Remote Diff: Test Connection or Remote Diff: Set or Update Server Password. The password is stored in VS Code SecretStorage.

Current functionality

  • Load connection settings from .vscode/remote-diff.json
  • Configure one server with the original flat format or multiple named targets with defaultTarget and targets
  • Select and remember the active target per workspace, display it in the status bar, and require an extra typed confirmation for production uploads
  • Refresh only the transferred file after an upload or download; run Scan Workspace manually when a full server refresh is needed
  • Authenticate with a securely stored password, SSH private key, encrypted key passphrase, or SSH agent
  • Verify a pinned host fingerprint or ask before trusting a host on first use
  • Open an SFTP session with read, stat, and directory-listing operations
  • Test an SSH connection from the Command Palette
  • Map a local workspace file to its counterpart below remotePath
  • Open the local and remote UTF-8 text files in VS Code's Diff Editor
  • Decode legacy Thai files that explicitly declare TIS-620, Windows-874, or CP874
  • Recursively scan local and remote directories using configured ignore patterns
  • Group files as Modified, Local only, Remote only, or Identical in an Explorer Tree View
  • Use size and modification time as a fast path, then SHA-256 content hashes for ambiguous equal-sized files
  • Batch remote metadata and hash commands when supported, with an SFTP fallback and in-memory hash cache
  • Refresh workspace results and open Modified files in the Diff Editor
  • Download one Modified or Remote only file after an explicit confirmation
  • Back up an existing local file under .vscode/remote-diff-backups, write through a temporary file, verify its SHA-256 hash, and refresh the comparison
  • Automatically remove backups over 5 versions per file, older than 30 days, or over 100 MB total (all limits are configurable)
  • Reject dirty editors, path traversal, and local symbolic-link destinations during downloads
  • Upload one Modified or Local only file when enableUpload is explicitly enabled
  • Detect remote changes since Compare or Scan before uploading
  • Back up an existing remote file under .remote-diff-backups, preserve its mode, upload through a temporary file, verify SHA-256, and atomically replace it
  • Automatically remove remote backups over 5 versions per file, older than 30 days, or over 100 MB total
  • Reject local or remote symbolic links and remove temporary upload files after failures or cancellation
  • Reset a saved key passphrase and trusted host fingerprint from the Command Palette
  • Set, update, or forget a saved server password from the Command Palette

Planned functionality

  • Download or upload multiple selected files

Development

npm ci
npm run check-types
npm run lint
npm test
npm run package
npm run package:vsix
npm run package:marketplace

Press F5 in VS Code to launch an Extension Development Host.

Installation

For the public beta, open the VS Code Extensions view, find Remote Diff SSH, select Switch to Pre-Release Version when necessary, and install it. Marketplace builds receive automatic updates.

For local testing, build a VSIX with npm run package:marketplace. In VS Code, open the Extensions view, choose Views and More Actions…, select Install from VSIX…, and pick the generated file.

Security

On the first connection to a target without hostFingerprint, verify the displayed fingerprint through a trusted channel before selecting Trust Fingerprint. The accepted fingerprint is stored in VS Code global state and a changed key is rejected. For managed environments, pin hostFingerprint in the workspace configuration.

Server passwords and encrypted private-key passphrases are stored in VS Code SecretStorage. Passwords and private-key contents must never be added to .vscode/remote-diff.json.

If a server key or private-key passphrase changes, run Remote Diff: Reset Credentials and Host Trust and reconnect. Verify a replacement server fingerprint before trusting it.

Remote files are opened read-only in a virtual document. UTF-8 is required unless a legacy Thai file explicitly declares TIS-620, Windows-874, or CP874 in its first 16 KB. Binary files and undecodable text are rejected instead of being decoded speculatively. For an accurate legacy-file comparison, use VS Code's Reopen with Encoding on the local file and choose Thai (Windows 874) before comparing.

Downloads affect only the local workspace. Existing files require confirmation and are copied to .vscode/remote-diff-backups before replacement. By default, cleanup retains up to 5 versions per file for 30 days and limits all workspace backups to 100 MB, deleting the oldest backups first. A single local file larger than the configured total limit is not replaced because it cannot be backed up safely. The extension also refuses to replace an unsaved editor or write through a symbolic link.

Uploads are disabled by default. Set "enableUpload": true, then Compare or Scan before uploading so the extension has a conflict snapshot. Existing remote files are backed up under <remotePath>/.remote-diff-backups and excluded from scans. By default, cleanup retains up to 5 versions per file for 30 days and limits remote backups to 100 MB, deleting the oldest managed backups first. Files not matching the extension's timestamped .bak format are never deleted. Uploads preserve the existing file mode, verify temporary and installed content, and refuse to write when the remote file changed after the snapshot. A remote file larger than the configured total backup limit is not replaced because it cannot be backed up safely.

Workspace scanning first compares file size and modification time. Equal-sized files with different modification times are read and compared using SHA-256 content hashes. Add generated files, dependencies, caches, logs, uploads, and other large directories to ignore to keep scans fast and reduce server load.

Please report security concerns privately to the repository owner instead of opening a public issue containing credentials or server details.

See SECURITY.md for private vulnerability reporting and PRIVACY.md for the extension's data-handling disclosure.

License

MIT

Related extensions