DevPort
A lightweight VS Code extension to sync local workspace files with a remote server over SFTP.
No telemetry. No tracking. No accounts. Everything runs locally between your editor and your server.
Features
- Connection panel — a DevPort icon in the Activity Bar opens a settings
form for the whole connection: protocol, host, credentials, remote path, sync
options. Validates as you go, tests the connection before you commit to it,
and shows live connection status. No JSON editing required.
- SFTP: Connect — connect using the configured server
- SFTP: Disconnect — close the active connection
- SFTP: List — browse the remote server folder by folder; open, download, copy the path of, or delete a file
- SFTP: List All — dump the full recursive remote tree into a new editor tab
- Upload File — upload the active or selected file
- Download File — download a file from the remote server
- Download Folder — recursively download a remote folder
- Sync Folder — upload only changed files (size / modification-time comparison)
- Delete Remote File — delete the remote copy of a file (with confirmation)
- Upload on Save — optionally upload files automatically when you save
- Upload Log — an SFTP Log view (in the Explorer) lists every uploaded
file with its time, action, and a
+added / -removed line summary. Click an
entry to open a diff of the previously uploaded version vs. the one you just
sent, so you can see exactly which lines changed.
- Automatic remote folder creation — parent directories are created as needed (
mkdir -p)
- Progress notifications — every long operation reports progress and can be cancelled
- Output logs — all activity is logged to the DevPort output channel
- Automatic reconnect — dropped connections are re-established with backoff and one retry
- Graceful error handling — failures are reported without crashing the editor
Requirements
- VS Code
1.75.0 or newer
- Node.js
18+ (for building)
- An SFTP-accessible server (password or private-key authentication)
Configuration
Click the DevPort icon in the Activity Bar and fill in the connection panel.
Saving writes .vscode/sftp.json:
{
"protocol": "sftp",
"host": "example.com",
"port": 22,
"username": "deploy",
"remotePath": "/var/www/app",
"uploadOnSave": false,
"ignore": [".git", "node_modules", ".vscode/sftp.json"]
}
Note what is not in that file: your password. Credentials go to your OS
keychain via VS Code's SecretStorage, so .vscode/sftp.json is safe to commit.
The file remains the config format and stays hand-editable — the panel picks up
external edits, and there is an Edit sftp.json link in the panel footer. The
table below documents every field.
Upgrading from 1.0.7 or earlier? A password already in your
sftp.json keeps working. The first time you save from the panel, DevPort
moves it into the keychain and removes it from the file.
| Field |
Type |
Required |
Description |
protocol |
"sftp" | "ftp" |
no |
Wire protocol (default "sftp"). "ftp" covers plain FTP and FTPS |
host |
string |
yes |
Server hostname or IP |
port |
number |
no |
Port (default 22 for SFTP, 21 for FTP) |
username |
string |
yes |
Login username |
password |
string |
* |
Password auth. Normally stored in the OS keychain, not here. Required unless privateKey is set (always required for FTP) |
remotePath |
string |
yes |
Remote base directory that mirrors your workspace root |
privateKey |
string |
* |
SFTP only. Path to a private key file (absolute, or relative to workspace) |
passphrase |
string |
no |
SFTP only. Passphrase for an encrypted private key. Also stored in the keychain |
secure |
boolean | "implicit" |
no |
FTP only. true = explicit FTPS (AUTH TLS), "implicit" = implicit FTPS. Default false (plain FTP) |
secureRejectUnauthorized |
boolean |
no |
FTP only. Set false to accept self-signed FTPS certificates (default true) |
uploadOnSave |
boolean |
no |
Upload files automatically on save (default false) |
ignore |
string[] |
no |
Path fragments to skip during upload/sync |
* Provide either password or privateKey (SFTP). FTP always uses password.
FTP / FTPS notes
- FTP always uses passive mode (PASV/EPSV) — there is no active/passive
option to set.
- Prefer
"secure": true (FTPS). Plain FTP sends credentials and file
contents unencrypted; the extension logs a warning when you connect that way.
- There is no host-key trust prompt for FTP. FTPS identity rests on TLS
certificate validation.
- Change detection for Sync Folder uses size + modification time. Servers
that only support the old
LIST command (no MLSD) don't report a reliable
time, so sync falls back to comparing size alone.
- Bulk transfers use at most 2 parallel connections for FTP (many servers cap
concurrent sessions), dropping to 1 if the server refuses them.
Path mapping
Local files map to remote paths by preserving their path relative to the
workspace root under remotePath. For example, with remotePath: "/var/www/app":
<workspace>/src/index.js -> /var/www/app/src/index.js
Security tip: if you hand-edit a password into .vscode/sftp.json rather
than using the panel, add the file to your .gitignore so it is never
committed.
Usage
- Open a workspace folder.
- Click the DevPort icon in the Activity Bar.
- Fill in the connection form, press Test to check it, then Save.
- Press Connect.
- Right-click files/folders in the Explorer for Upload, Download,
Sync, and Delete actions, use the quick actions in the panel, or run
them from the Command Palette.
Build & Run
# Install dependencies
npm install
# Compile TypeScript -> out/
npm run compile
# Or watch mode during development
npm run watch
To run the extension in a development host:
- Open this folder in VS Code.
- Press
F5 (uses .vscode/launch.json → Run Extension).
- A new Extension Development Host window opens with DevPort loaded.
Package a .vsix
npm install -g @vscode/vsce
vsce package
This produces harshkajale-syncfiles-1.0.0.vsix (displayName DevPort), installable via
Extensions → … → Install from VSIX.
Architecture
src/
extension.ts Command registration, VS Code wiring, upload-on-save, progress UI
config.ts Load / validate / save .vscode/sftp.json
secrets.ts SecretStore: credentials in the OS keychain, namespaced per workspace
connectionView.ts ConnectionViewProvider: the "Connection" settings panel
sftp.ts SftpManager: connection lifecycle, reconnect, file operations
ftp.ts FtpManager: the FTP / FTPS backend
sync.ts Folder walking, changed-only sync, recursive download
history.ts UploadHistory: snapshots + line-diff of each uploaded file
logView.ts SftpLogProvider: the "Upload Log" tree view
statusBar.ts Connection-state status-bar indicator
utils.ts Logger/OutputChannel, path mapping, ignore matching, helpers
media/ Webview assets for the connection panel (HTML / CSS / JS)
images/ Extension icon and the Activity Bar icon
The panel is a webview: it holds no logic of its own beyond form state and
validation, and reaches the extension host by postMessage for everything real
(reading and writing the config, file dialogs, connecting). Passwords are never
sent into the webview — it is told only whether one is stored.
Upload snapshots for the log are kept in the extension's own global storage
(namespaced per workspace) — never inside your project and never uploaded.
Each module has a single responsibility; extension.ts orchestrates the others
and owns all VS Code API interaction.
License
MIT — see LICENSE.