English · Türkçe sürüm: README.tr.md
Developer: Sanater
An FTP client that brings the workflow of NppFTP (the Notepad++ plugin) to VS Code: define a profile → connect → click a file in the remote tree → edit → save, and it uploads itself.
No NppFTP code was used — only its behaviour and dialog layout were taken as a reference. This extension is written from scratch in TypeScript.
Features
| NppFTP | This extension |
|---|---|
| Profile settings dialog | FTP Profiles webview (Add / Duplicate / Delete) |
| FTP, FTPES, FTPS, SFTP | Same (basic-ftp + ssh2-sftp-client) |
| Remote file tree | FTP view in the activity bar |
| Double-click to open, save to upload | Same; the mapping is stored persistently |
| Download / Upload / Upload as | Download, Download To, Upload Files/Folder Here |
| New file / New dir / Rename / Delete | Same (folder deletion is recursive) |
| Permissions (chmod) | Permissions (SETSTAT over SFTP, SITE CHMOD over FTP) |
| Properties | Properties (size, date, permissions, owner) |
| Message window | FTP output channel (raw protocol at trace level) |
| Cache (local↔remote mapping) | Per-profile local root or the extension cache |
On top of that:
- SSH terminal — opens a shell on the same server (not in NppFTP).
- Matching tag highlighting — Notepad++'s own feature, brought along too.
- Drag & drop: drop local files onto the tree to upload, drag inside the tree to move.
- Passwords and SSH key passphrases go to the operating system credential store (VS Code SecretStorage), never into the profile file.
- Silent reconnect when the connection drops while saving.
- Status bar indicator, keep-alive, timeout, ASCII/binary transfer mode.
- English and Turkish user interface.
Installation
From the Marketplace: open the Extensions panel (Ctrl+Shift+X), search for
FTP/SFTP Explorer and click Install.
From a .vsix file: Extensions panel → ... menu → Install from VSIX...,
or from a terminal:
code --install-extension ftp-explorer-<version>.vsix
Reload the window afterwards (Ctrl+Shift+P → Developer: Reload Window).
The FTP icon appears in the activity bar.
To build from source see Development below.
Language
The extension speaks English and Turkish. By default it follows the VS Code display language; to pin one explicitly:
"ftpx.language": "en" // "auto" (default) | "en" | "tr"
This setting covers messages, dialogs, the profile window and the message window.
Command and menu titles are translated through the VS Code platform mechanism
instead, so those follow the display language (Ctrl+Shift+P →
Configure Display Language) and require the matching language pack.
Getting started
- Click the FTP icon in the activity bar.
- Open Profile Settings, press Add and fill in the protocol, host, username and password. Then Save and Connect.
- Click a file in the remote tree — it is downloaded to a local cache and opened in the editor.
- Edit and press Ctrl+S — the file is uploaded back automatically.
To upload the current file manually: Ctrl+Alt+U (FTP: Upload Current File).
Profile fields
| Field | Meaning |
|---|---|
| Protocol | FTP, FTPES (21 / AUTH TLS), FTPS (990 / implicit TLS), SFTP (22) |
| Method (SFTP) | Password, private key (~/.ssh/id_ed25519) or SSH agent |
| Initial remote directory | Root of the tree. Leave / to use the server working directory |
| Local root directory | Empty = extension cache. If set, the remote tree is mirrored into that folder |
| Transfer mode | Binary, ASCII, or Automatic by file extension |
| Excluded patterns | Names hidden in the tree, e.g. *.tmp, .git, node_modules |
SSH terminal
You do not need a separate program to run php artisan cache:clear after
uploading a file. An interactive shell opens on the same server, inside the VS Code
terminal panel — no PuTTY or OpenSSH installation required.
| How to open | Where |
|---|---|
| The terminal icon in the FTP view title | While connected |
| Right-click a folder in the tree → Open SSH Terminal Here | The shell starts in that directory |
| Command palette → FTP: Open SSH Terminal | Lets you pick a profile even when disconnected |
Credentials come from the same place as the FTP/SFTP connection, and are not asked
for again if the profile is already connected. Servers requiring
keyboard-interactive authentication are supported. Terminal resizes are forwarded
to the server, so full-screen programs such as top, htop and nano work
correctly. Multi-byte UTF-8 characters survive chunk boundaries.
Which profiles can use it?
- SFTP profiles automatically — same host, port and credentials.
- FTP / FTPS / FTPES profiles once you enable the SSH terminal section in the profile settings. Port (22 by default) and username can be overridden; the FTP password is reused. If you need key-based authentication, create a separate profile using the SFTP protocol.
Matching tag highlighting
Move the cursor into a tag and both the opening and the closing tag stand out:
<div class="row"> ← highlighted as well while the cursor is in the </div> below
<div class="col-12">
@if($section->body) ← @if / @endif pairs are matched too
{!! $section->body !!}
@endif
</div>
</div> ← cursor here
Three highlight layers
Notepad++'s look is made of three separate layers; each can be toggled individually:
| Layer | Setting | Colour | What it does |
|---|---|---|---|
| Line band | highlightLine |
ftpxTag.matchLineBackground |
Fills the whole line of the opening and closing tag. This is the Notepad++ "eol filled" style and the layer that makes start and end obvious at a glance. |
| Tag | scope |
ftpxTag.matchBackground |
<div … > and </div> |
| Attribute names | highlightAttributes |
ftpxTag.attributeBackground |
Only the class, id, style … names of the matching tag. Values are not coloured. |
How much gets coloured? (ftpx.tagHighlight.scope)
In the default tag mode attribute values are not painted. This matters for
Tailwind projects where a single tag can exceed 300 characters:
<!-- scope: "tag" (default) --> <div class="..." style="..."> → <div and >
<!-- scope: "name" --> just div
<!-- scope: "full" --> the whole tag (Notepad++'s "highlight tag attributes" look)
Measured on a real 212-line Tailwind Blade file: full painted 76 characters
per tag on average and 356 in the worst case; tag paints 11 on average,
19 at worst.
What the scanner handles
<inside<!-- -->comments,<script>/<style>/<textarea>content and<?php ... ?>blocks is not treated as a tag.- A quoted
>such as<a title="a > b">does not end the tag. - In-tag Blade expressions like
<div {{ $attrs }} class="{!! $c !!}">are skipped. - Void elements (
<br>,<img>,<input>) and<x />are not openings. - Unclosed
<li>/<p>tags do not break the enclosing pair. - Blade component tags such as
<x-layout.app>and<x-slot:head>are supported. - Attribute scanning keeps Vue/Alpine forms:
:class,@click,@click.prevent,x-on:click.prevent,v-if,#slot.
Blade block directives are matched as well
(ftpx.tagHighlight.highlightBladeDirectives): @if, @unless, @isset, @for,
@foreach, @forelse, @while, @switch, @section, @push, @prepend,
@once, @verbatim, @php, @auth, @guest, @can, @cannot, @canany,
@error, @production, @env, @component, @slot, @fragment, @session and
@hasSection. Single-line forms (@section('title', 'Page'), @php($x = 1)) do
not open a block; @@if escapes and text like [email protected] are not directives.
Commands
| Command | Shortcut |
|---|---|
| Tag Matching: Go to Matching Tag | Ctrl+Alt+M |
| Tag Matching: Select Tag Block | — |
Changing the colours
In settings.json:
"workbench.colorCustomizations": {
"ftpxTag.matchBackground": "#a074c470",
"ftpxTag.matchLineBackground": "#8a6fc42e",
"ftpxTag.attributeBackground": "#d9b23a4d",
"ftpxTag.matchBorder": "#c08cf0cc",
"ftpxTag.guideForeground": "#a074c470"
}
Settings
| Setting | Default | Description |
|---|---|---|
ftpx.language |
auto |
Extension language: auto / en / tr |
ftpx.onSave |
upload |
On save: upload / ask / none |
ftpx.confirmDelete |
true |
Ask before deleting |
ftpx.showHiddenFiles |
true |
Show dot files |
ftpx.sortFoldersFirst |
true |
Sort folders first |
ftpx.logLevel |
info |
off / info / debug / trace |
ftpx.cachePath |
"" |
Folder for downloaded files |
ftpx.autoConnectProfile |
"" |
Profile to connect to on startup |
ftpx.reconnectOnUpload |
true |
Silently re-establish a dropped connection |
ftpx.tagHighlight.enabled |
true |
Matching tag highlighting |
ftpx.tagHighlight.style |
background |
background / outline / underline / background+outline |
ftpx.tagHighlight.bold |
false |
Render matching tags bold |
ftpx.tagHighlight.scope |
tag |
tag (boundaries), name (name only), full (with attributes) |
ftpx.tagHighlight.highlightLine |
true |
Fill the whole line of the matching tags |
ftpx.tagHighlight.highlightAttributes |
true |
Mark attribute names of the matching tag |
ftpx.tagHighlight.matchInsideContent |
false |
Match from the content between the tags too |
ftpx.tagHighlight.highlightBladeDirectives |
true |
Also match @if/@endif style Blade blocks |
ftpx.tagHighlight.showVerticalGuide |
false |
Draw a vertical guide between the tags |
ftpx.tagHighlight.languages |
HTML/Blade/Vue... | Enabled language ids (* = all) |
ftpx.tagHighlight.maxFileSize |
2000000 |
Skip tag matching above this size |
Project layout
src/
extension.ts Entry point: view, status bar, save-and-upload hook
session.ts The single active connection + operation queue
profileStore.ts profiles.json + SecretStorage
profileEditor.ts The "FTP Profiles" webview
tree.ts Remote file tree + drag & drop
commands.ts All commands
transfer.ts Download/upload, progress, ASCII conversion
cache.ts Local↔remote mapping
i18n.ts Language resolution (setting + display language)
i18n/
core.ts Active language, placeholder formatting, t()
en.ts / tr.ts Message bundles (key parity enforced by tests)
clients/
client.ts Shared interface
ftpClient.ts FTP / FTPES / FTPS (basic-ftp)
sftpClient.ts SFTP (ssh2-sftp-client)
ssh/
shell.ts SSH shell (vscode-free, testable)
terminal.ts Binds the shell to the VS Code terminal panel
tagmatch/
tags.ts HTML/XML tag scanner + stack-based matcher
directives.ts Blade block directives
match.ts Combines both, finds the pair under the cursor
highlighter.ts Decorations, listeners, cache
media/ Webview HTML/CSS/JS, icons
test/ Smoke tests against a real SFTP + SSH server
package.nls.json Command/setting titles (English)
package.nls.tr.json Command/setting titles (Turkish)
Development
npm install
npm run compile
Open this folder in VS Code and press F5: a separate "Extension Development Host" window starts so you can try your changes without touching the installed version.
See PUBLISHING.md in the repository for packaging and publishing.
Tests
npm test
test/sftp-server.js starts a real in-process SFTP + SSH server; test/smoke.js
verifies connecting, listing, stat, downloading (including progress reporting),
uploading, mkdir, rename, chmod and recursive deletion end to end. On the SSH
side it covers opening a shell, running commands, multi-byte character integrity,
window-size propagation, the initial directory (including quote escaping) and the
wrong-password path. It also covers every corner case of the tag/directive scanner
(comments, <script>, quoted >, void elements, @section forms, @@ escapes)
and the consistency of the translation bundles (key parity, empty strings,
placeholder agreement).
Known limitations
- Active (PORT) FTP mode is not supported.
basic-ftponly uses passive mode (PASV/EPSV); if a profile selects active mode a warning is logged and passive mode is used. - SSH host keys are not verified. The server key fingerprint is logged at
debuglevel but is not compared againstknown_hosts. - ASCII mode does not rely on the server's
TYPE Abehaviour; line endings are converted locally instead (to the OS convention on download, toLFon upload). Binary content is detected and left untouched. - Only one connection at a time (same as NppFTP).
- FTP has no single-file
statcommand, so "Properties" reads from the parent directory listing; some servers do not report permissions or ownership.
License and contact
MIT licensed. Developer: Sanater