Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Pigeon - SFTP/FTP SyncNew to Visual Studio Code? Get it now.
Pigeon - SFTP/FTP Sync

Pigeon - SFTP/FTP Sync

Kévin Martin

|
1 install
| (0) | Free
Carry your files to remote servers over SFTP/FTP (maintained fork of Natizyskunk.sftp)
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Pigeon logo

Pigeon - SFTP/FTP Sync

Carry your files to remote servers over SFTP and FTP, right from VS Code.

Marketplace version Installs GitHub release License

Install · Quick start · Documentation · Changelog · Report a bug


Edit files locally and let Pigeon deliver them to your server. Pigeon syncs a local folder with a remote directory over SFTP or FTP. A few lines of configuration are enough to start, and many options cover advanced setups.

Pigeon is the actively maintained successor of Natizyskunk's SFTP extension, itself forked from liximomo's SFTP plugin. It runs on current VS Code and Node versions and keeps evolving.

Features

  • Upload on save: every save goes straight to the server.
  • Sync both ways: local to remote, remote to local, or both directions.
  • Diff local and remote: compare a file with its remote copy before you overwrite anything.
  • Remote Explorer: browse, open and download remote files from the Activity Bar.
  • File watcher: upload or delete files changed by external tools (build output, generators).
  • Profiles and multiple contexts: switch between dev and prod, or map several folders to several servers.
  • Connection hopping: reach a target server through one or more SSH hops, with keys read locally or on the hop.
  • Temp files: view remote content without touching your workspace.

Installation

From the Marketplace: search for Pigeon in the Extensions view (Ctrl+Shift+X / Cmd+Shift+X), or run:

code --install-extension kmartin26.pigeon-sync

From a VSIX: download the latest .vsix from the releases page, open the Extensions view, then "..." > Install from VSIX....

Coming from Natizyskunk or liximomo SFTP?

Uninstall Natizyskunk.sftp or liximomo.sftp first: they register the same sftp.* commands. Your .vscode/sftp.json files and commands are unchanged, so existing projects work as-is.

Quick start

  1. Open the local folder you want to sync. It can be empty if you start from the server.

  2. Open the Command Palette (Ctrl+Shift+P / Cmd+Shift+P) and run SFTP: Config.

  3. Fill in .vscode/sftp.json with your server details:

    {
      "name": "My Server",
      "host": "example.com",
      "protocol": "sftp",
      "port": 22,
      "username": "username",
      "remotePath": "/var/www/project",
      "uploadOnSave": true
    }
    

    password is optional: Pigeon prompts for it when needed. Escape backslashes and other special characters with a backslash.

  4. Run SFTP: Download Project to pull remotePath into your local folder, or SFTP: Sync Local -> Remote to push it.

  5. Edit and save. With uploadOnSave, each save is uploaded.

Type sftp in the Command Palette to see every command, or right-click files in the Explorer. See the full list of commands and configuration options.

Example configurations

Simple

{
  "host": "host",
  "username": "username",
  "remotePath": "/remote/workspace"
}

Profiles

{
  "username": "username",
  "password": "password",
  "remotePath": "/remote/workspace/a",
  "watcher": {
    "files": "dist/*.{js,css}",
    "autoUpload": false,
    "autoDelete": false
  },
  "profiles": {
    "dev": {
      "host": "dev-host",
      "remotePath": "/dev",
      "uploadOnSave": true
    },
    "prod": {
      "host": "prod-host",
      "remotePath": "/prod"
    }
  },
  "defaultProfile": "dev"
}

context and watcher are only available at root level. Run SFTP: Set Profile to switch profile.

Multiple contexts

Each context must be different, and name is required in this mode.

[
  {
    "name": "server1",
    "context": "project/build",
    "host": "host",
    "username": "username",
    "password": "password",
    "remotePath": "/remote/project/build"
  },
  {
    "name": "server2",
    "context": "project/src",
    "host": "host",
    "username": "username",
    "password": "password",
    "remotePath": "/remote/project/src"
  }
]

Connection hopping

Connect to a target server through one or more SSH proxies. Variable substitution does not work in a hop configuration.

Single hop: local -> hop -> target

{
  "name": "target",
  "remotePath": "/path/in/target",

  // hop
  "host": "hopHost",
  "username": "hopUsername",
  "privateKeyPath": "/Users/localUser/.ssh/id_rsa", // <-- The key file is on the local machine.

  "hop": {
    // target
    "host": "targetHost",
    "username": "targetUsername",
    "privateKeyPath": "/Users/hopUser/.ssh/id_rsa", // <-- The key file is on the hop.
    // or
    "localPrivateKeyPath": "/Users/localUser/.ssh/target_rsa" // <-- The key file is on the local machine.
  }
}

Multiple hops: local -> hopa -> hopb -> target

{
  "name": "target",
  "remotePath": "/path/in/target",

  // hopa
  "host": "hopAHost",
  "username": "hopAUsername",
  "privateKeyPath": "/Users/hopAUsername/.ssh/id_rsa", // <-- The key file is on the local machine.

  "hop": [
    // hopb
    {
      "host": "hopBHost",
      "username": "hopBUsername",
      "privateKeyPath": "/Users/hopaUser/.ssh/id_rsa" // <-- The key file is on hopa.
    },

    // target
    {
      "host": "targetHost",
      "username": "targetUsername",
      "privateKeyPath": "/Users/hopbUser/.ssh/id_rsa", // <-- The key file is on hopb.
      // or
      "localPrivateKeyPath": "/Users/localUser/.ssh/target_rsa" // <-- The key file is on the local machine.
    }
  ]
}

Use localPrivateKeyPath instead of privateKeyPath to read the key file from the local machine. It works in every hop entry and takes precedence over privateKeyPath.

Configuration in user settings

Use remote to read the connection from remote-fs settings.

In user settings:

"remotefs.remote": {
  "dev": {
    "scheme": "sftp",
    "host": "host",
    "username": "username",
    "rootPath": "/path/to/somewhere"
  },
  "projectX": {
    "scheme": "sftp",
    "host": "host",
    "username": "username",
    "privateKeyPath": "/Users/xx/.ssh/id_rsa",
    "rootPath": "/home/foo/some/projectx"
  }
}

In sftp.json:

{
  "remote": "dev",
  "remotePath": "/home/xx/",
  "uploadOnSave": false,
  "ignore": [".vscode", ".git", ".DS_Store"]
}

Remote Explorer

Remote Explorer preview

Open the Remote Explorer from the SFTP view in the Activity Bar, or run View: Show SFTP.

  • View and edit: the Remote Explorer opens a read-only view of a file. Run SFTP: Edit in Local to edit it.
  • Multiple select: hold Ctrl or Shift to select several files and folders, then download or upload them at once.
  • Download buttons: hover a file or folder to show its inline download button.
  • Refresh: click the refresh button in the editor title bar, or run SFTP: Refresh Active Remote File, to reload an open remote file from the server.
  • Order: set remoteExplorer.order in sftp.json to sort several Remote Explorer roots (default 0).
{
  "remoteExplorer": {
    "order": 1
  }
}

After you delete a file, refresh the parent folder manually if the explorer does not update.

Debug

  1. Open the settings (File > Preferences > Settings, or Code > Settings on macOS).
  2. Set sftp.debug to true and reload VS Code.
  3. Read the logs in View > Output > sftp.

FAQ

See the Frequently Asked Questions.

Contributing

Bug reports, feature requests and pull requests are welcome. Open an issue or read the contributing guide. Every report is read and handled as fast as possible.

Credits

  • @liximomo: original author of vscode-sftp.
  • @Natizyskunk and contributors: maintained fork up to v1.16.4.

License

MIT

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft