~ / plugins / vscode / ach-remote-sync

ACH Remote Sync

Расширение VS Code для синхронизации проекта с сервером по SFTP, FTP и FTPS: загрузка при сохранении, сравнение с сервером при открытии файла, проверка каждой загрузки.

v2.0.15 · stable
ACH Remote Sync

Зачем

ACH Remote Sync связывает папку проекта в VS Code с папкой на сервере. Вы правите файлы локально, расширение отправляет их на сервер по SFTP, FTP или FTPS. Открываете файл, и расширение сверяет его с серверной копией. Если копии разные, сразу открывается сравнение.

Расширение задумано для работы прямо на сервере разработки, где крутится сборщик в режиме наблюдения, работает PHP или любой другой код. Главная задача: файл на сервере всегда совпадает с тем, что вы сохранили, и ни одна загрузка не портит данные молча.

Ключевые возможности

  • Протоколы SFTP, FTP и FTPS. Для FTPS доступны оба режима TLS: явный (AUTH TLS) и неявный.
  • Вход через SSH-агент, файл ключа (ed25519, RSA, ECDSA, в том числе зашифрованный), пароль или режим auto.
  • Загрузка при сохранении файла. Три режима: выключено, всегда, только для файлов, которые уже есть на сервере.
  • Сравнение с сервером при открытии файла. Совпадает: ничего не происходит. Различается: открывается сравнение и окно с выбором «Upload local» или «Download remote».
  • Удаление на сервере вслед за локальным удалением. Режимы: выключено, с вопросом, всегда. Удаление папки расширение подтверждает всегда.
  • Ручные команды Sync Up и Sync Down в палитре, в контекстном меню проводника и вкладки.
  • Исключения в синтаксисе .gitignore. Служебные папки (.git, .vscode, node_modules и другие) исключены по умолчанию.
  • Строка состояния с текущим действием и числом операций в очереди. Значки состояния файлов в проводнике.
  • Несколько папок рабочей области, у каждой свой сервер.
  • Подробный журнал в панели Output. Пароли и парольные фразы в журнале скрыты.

Чем отличается

Запись на месте, без временного файла

Многие клиенты сначала пишут временный файл, потом удаляют старый и переименовывают новый. Вотчер сборки (webpack, vite, rollup) видит удаление, начинает пересборку и падает с ошибкой «Module not found». ACH Remote Sync открывает сам целевой файл на запись и перезаписывает его содержимое. Файл сохраняет inode, права и владельца. Вотчер видит одно событие изменения, и сборка идёт штатно.

Проверка размера после каждой загрузки

После записи расширение запрашивает у сервера размер файла и сравнивает его с локальным. Расхождение превращается в явную ошибку. Недописанный файл не останется на сервере незамеченным.

Отказ от нулевой перезаписи

Пустой локальный файл не затрёт непустой файл на сервере. Такая загрузка останавливается с понятной ошибкой. Так же работает скачивание: пустая серверная копия не затрёт ваш непустой локальный файл. Это защита от сбоя редактора, который иногда оставляет файл нулевой длины.

Сравнение при открытии

Вы открываете файл, и расширение в фоне скачивает его серверную копию и сравнивает по SHA-256. Сравнение открывается только при реальной разнице. Слева серверная версия, справа ваша. Ctrl+S в окне сравнения сохраняет локальный файл.

Безопасное скачивание и снимки

Sync Down скачивает файл во временный файл рядом, проверяет размер и только потом заменяет локальный. Перед заменой расширение сохраняет копию прежнего файла в .vscode/.ach-remote-sync-cache/. Для каждого файла хранятся три последние копии.

Автоподключение и повторы

Соединение открывается само при первой операции. Если связь оборвалась, расширение переподключается перед следующей операцией. Сетевые сбои (тайм-аут, сброс, отказ в соединении) повторяются до трёх попыток с растущей паузой. Ошибки входа и прав доступа расширение не повторяет и сразу показывает.

Одна загрузка на файл в каждый момент

Операции идут через общую очередь по одной. Если файл меняется, пока он отправляется, расширение дождётся конца загрузки и отправит итоговую версию один раз. Двойное уведомление об одном сохранении расширение распознаёт по времени изменения и размеру файла, поэтому повторная правка в ту же секунду не потеряется.

SSH-агент на Windows

Расширение само находит агент OpenSSH, встроенный в Windows, через канал \.pipeopenssh-ssh-agent. Если его нет, расширение обращается к Pageant. На macOS и Linux используется $SSH_AUTH_SOCK. Путь к агенту можно задать вручную.

Проверка ключа хоста

Расширение читает ~/.ssh/known_hosts, в том числе хэшированные записи. При первом подключении к новому серверу оно показывает отпечаток SHA-256 и предлагает доверять навсегда или один раз. Если ключ сервера сменился, подключение отклоняется. Отпечаток можно закрепить прямо в настройках.

Внешние изменения только по вашему выбору

По умолчанию на сервер уходят только сохранения из редактора. Файлы, которые изменили сборка, git или другой редактор, остаются локальными. Отправку внешних изменений включает отдельный параметр.

Файл настроек

Все настройки подключения лежат в файле .vscode/ach-remote-sync.json в корне папки проекта. Расширение запускается, когда видит этот файл в рабочей области. В файле можно писать комментарии // и /* … */.

Минимальный файл для SFTP через SSH-агент:

{
  "protocol": "sftp",
  "host": "example.com",
  "username": "deploy",
  "auth": { "type": "agent" },
  "remotePath": "/var/www/example.com"
}

Расширение читает файл при запуске окна. После создания файла и после каждой правки выполните в палитре команду Developer: Reload Window. Без перезагрузки окна изменения в уже загруженном файле не применяются.

Если в файле ошибка, расширение покажет сообщение ACH Remote Sync — config error in <папка>: … с описанием. Неизвестные ключи расширение пропускает без ошибки. Опечатка в имени параметра значит, что параметр просто возьмёт значение по умолчанию. Сверяйте имена с таблицей ниже.

Сам файл настроек и вся папка .vscode исключены из синхронизации по умолчанию. Хост, логин и пароль на сервер не попадут.

Все параметры

Параметр Тип По умолчанию Что делает
protocol строка обязательный Протокол: "sftp", "ftp" или "ftps".
host строка обязательный Имя сервера или IP-адрес.
port целое 1–65535 22 для sftp, 21 для ftp и ftps Порт сервера. Для неявного FTPS обычно нужен 990, его задают вручную.
username строка обязательный Имя пользователя на сервере.
auth объект обязательный Способ входа. Поле type обязательно: "agent", "key", "password" или "auto". Остальные поля зависят от типа, см. раздел «Аутентификация».
remotePath строка обязательный Папка на сервере, которая соответствует корню проекта. Путь к серверному файлу получается так: remotePath плюс путь файла от корня проекта. Саму папку создайте на сервере заранее.
localPath строка корень папки рабочей области Локальная папка, которая соответствует remotePath. Нужна, если синхронизировать надо только подпапку проекта. Указывайте абсолютный путь. Файлы вне этой папки расширение не трогает.
strictHostKey логический true Только SFTP. Политика для неизвестного ключа сервера в проверочных командах Smoke: true отклоняет подключение, false принимает его с предупреждением в журнале. В обычной работе неизвестный ключ всегда вызывает окно подтверждения, см. раздел «Ключ хоста».
hostFingerprint строка нет Только SFTP. Ожидаемый отпечаток ключа сервера в формате SHA256:…. Префикс SHA256: можно не писать. Когда параметр задан, расширение не читает known_hosts и не показывает окон: совпал отпечаток, подключение идёт, не совпал, подключение отклоняется.
knownHostsFile строка ~/.ssh/known_hosts Только SFTP. Файл, из которого расширение читает известные ключи серверов. Поддерживаются хэшированные записи и записи вида [host]:port.
keepaliveIntervalMs число, мс 20000 Только SFTP. Интервал служебных пакетов, которые держат соединение живым. 0 отключает их.
connectTimeoutMs число, мс 15000 Только FTP и FTPS. Тайм-аут соединения с сервером.
readyTimeoutMs число, мс 20000 Только SFTP. Сколько ждать, пока соединение и SSH-рукопожатие завершатся.
watch логический true Главный выключатель автоматики. При false не работают загрузка при сохранении, удаление на сервере, сравнение при открытии и значок несохранённых изменений. Ручные команды работают.
ignore массив строк [] Шаблоны исключений в синтаксисе .gitignore. Добавляются к встроенному списку. См. раздел «Исключения».
automation объект см. ниже Поведение при событиях редактора и диска. Четыре поля ниже.
automation.uploadOnSave строка "off" "off", "always" или "onlyExisting". Отправка файла на сервер при сохранении.
automation.diffOnOpen строка "always" "off" или "always". Сравнение с серверной копией при открытии файла.
automation.deleteOnLocalDelete строка "off" "off", "ask" или "always". Удаление на сервере вслед за локальным удалением.
automation.watchExternalChanges логический false Отправлять ли на сервер изменения, сделанные вне редактора: сборкой, git, терминалом, проводником.
cleanOrphansOnConnect логический false При каждом подключении искать в remotePath временные файлы .ach-tmp-* старше 24 часов и удалять их. Работает в фоне и уступает очередь вашим операциям.
logLevel строка "info" Подробность журнала: "debug", "info", "warn" или "error". Журнал общий для всех папок. Если папок несколько, действует самый подробный уровень.
ftps.secure строка "explicit" Только FTPS. "explicit": подключение на обычный порт и переход на TLS командой AUTH TLS. "implicit": TLS с первого байта, обычно порт 990.
ftps.rejectUnauthorized логический true Только FTPS. Отклонять сертификат сервера, который не прошёл проверку. false ставьте только для самоподписанного сертификата, который вы проверили сами.

Протоколы

  • sftp. Передача файлов поверх SSH. Шифрование, вход по ключу или через агент, одно соединение на одном порту. Выбирайте его, если сервер это позволяет.
  • ftps. FTP с шифрованием TLS. Вход только по паролю. Режим задаёт ftps.secure.
  • ftp. FTP без шифрования. Пароль и содержимое файлов идут по сети открытым текстом. Используйте только в доверенной локальной сети.

Для FTP и FTPS расширение работает в пассивном режиме. Защита загрузки (запись на месте, проверка размера, отказ от нулевой перезаписи) одинакова для всех трёх протоколов.

Пример FTPS с явным TLS:

{
  "protocol": "ftps",
  "host": "ftp.example.com",
  "port": 21,
  "username": "deploy",
  "auth": { "type": "password", "password": "••••" },
  "remotePath": "/var/www/example.com",
  "ftps": {
    "secure": "explicit",
    "rejectUnauthorized": true
  }
}

Аутентификация

Тип Поля Протоколы Как работает
agent agentPath (необязательно) SFTP Ключ берётся из запущенного SSH-агента. Без agentPath расширение ищет агент само.
key keyPath (обязательно), passphrase (необязательно) SFTP Ключ читается из файла. Поддерживаются ed25519, RSA и ECDSA. Для зашифрованного ключа нужна passphrase.
password password (обязательно) SFTP, FTP, FTPS Вход по паролю.
auto keyPath, passphrase, password (все необязательны) SFTP, FTP, FTPS Для SFTP расширение передаёт серверу все доступные способы сразу: агент (если он найден), ключ из keyPath и пароль. Для FTP и FTPS используется только password.

Для FTP и FTPS подходят только password и auto. С типами agent и key подключение завершится ошибкой CONFIG_INVALID.

Путь keyPath может начинаться с ~/, тогда он отсчитывается от домашней папки. Абсолютный путь берётся как есть. Относительный путь считается от рабочей папки процесса VS Code, поэтому его лучше не использовать.

Пароль и парольная фраза хранятся в файле настроек открытым текстом. Не добавляйте такой файл в репозиторий. Надёжнее держать ключ в агенте и указать "auth": { "type": "agent" }.

SSH-агент на Windows

Включите встроенную службу OpenSSH Agent и добавьте в неё ключ. Команды для PowerShell от имени администратора:

Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519
ssh-add -l

Последняя команда должна показать ключ. Расширение находит агент по каналу \\.\pipe\openssh-ssh-agent. Если этого канала нет, расширение обращается к Pageant.

Git Bash приносит свой ssh-add, который работает с другим агентом. Если ключ виден в Git Bash, а расширение его не находит, добавьте ключ из PowerShell командой C:\Windows\System32\OpenSSH\ssh-add.exe.

Pageant

Запустите Pageant и добавьте в него ключ .ppk через значок в трее. Укажите "auth": { "type": "agent" }. Расширение перейдёт на Pageant, если служба OpenSSH Agent не запущена.

SSH-агент на macOS

Агент в macOS уже запущен. Добавьте ключ и сохраните парольную фразу в связке ключей:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519

SSH-агент на Linux

Расширение берёт адрес агента из переменной $SSH_AUTH_SOCK. Она должна быть задана в среде, из которой запущен VS Code. Обычно агент запускает графическая сессия (gnome-keyring, KWallet). Если агента нет, добавьте в ~/.bashrc или ~/.zshrc:

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

Свой путь к агенту

Параметр agentPath задаёт агент вручную: путь к сокету на macOS и Linux или имя канала на Windows.

"auth": { "type": "agent", "agentPath": "/run/user/1000/ssh-agent.socket" }

Ключ хоста и known_hosts

При подключении по SFTP расширение сверяет ключ сервера с файлом ~/.ssh/known_hosts или с файлом из knownHostsFile.

  • Ключ найден и совпадает. Подключение идёт без вопросов.
  • Ключа нет в файле. Появляется окно с именем сервера, алгоритмом и отпечатком SHA256:…. Кнопка «Trust Permanently» дописывает ключ в ~/.ssh/known_hosts. Кнопка «Trust Once» доверяет ключу только в этом подключении, при следующем окно появится снова. Отмена прерывает подключение.
  • Для сервера в файле записан другой ключ. Подключение отклоняется, в журнале появляется строка HOST KEY MISMATCH for <host>:<port>. Refusing to connect.

Перед тем как нажать «Trust Permanently», сверьте отпечаток с администратором сервера. Узнать отпечаток можно так:

ssh-keyscan -t ed25519 example.com | ssh-keygen -lf -

Кнопка «Trust Permanently» всегда пишет в ~/.ssh/known_hosts, даже если задан knownHostsFile. Если вы используете свой файл, перенесите запись в него вручную.

Для серверов, у которых ключ меняется при каждом развёртывании, задайте hostFingerprint. Тогда known_hosts не используется.

Исключения

Параметр ignore принимает список шаблонов в синтаксисе .gitignore. Пути считаются от корня папки рабочей области, разделитель всегда /.

  • *.log: шаблон без косой черты совпадает на любой глубине.
  • /build: косая черта в начале привязывает шаблон к корню проекта.
  • dist/: косая черта в конце означает только папку.
  • wp-content/uploads/**: всё содержимое папки.
  • **/coverage/**: папка coverage на любой глубине.
  • !.vscode/launch.json: восклицательный знак возвращает файл, который исключён раньше.

Встроенный список действует всегда, ваши шаблоны добавляются после него:

.git
.git/**
.vscode/**
.claude/**
.idea/**
.cursor/**
node_modules
node_modules/**
.DS_Store
Thumbs.db
.ach-tmp-*
**/.ach-tmp-*
.ach-trash
.ach-trash/**

Исключения действуют на загрузку при сохранении, удаление на сервере, сравнение при открытии и значок несохранённых изменений. Ручные команды Sync Up и Sync Down работают с любым файлом, даже исключённым.

Пример для сайта на WordPress:

"ignore": [
  "wp-content/uploads/**",
  "wp-content/cache/**",
  "*.log"
]

Автоматика

Все параметры автоматики по умолчанию безопасны: без вашей команды сервер не меняется. По умолчанию включено только сравнение при открытии. Оно лишь читает файлы с сервера. Параметр "watch": false выключает всю автоматику разом.

automation.uploadOnSave

Значение Поведение
"off" Ничего не отправляется. Файлы отправляют командой Sync Up.
"always" Каждое сохранение отправляется на сервер. Недостающие папки на сервере создаются. При включённом watchExternalChanges на сервере появляются и новые пустые папки.
"onlyExisting" Сохранение отправляется, только если файл уже есть на сервере. Новые файлы остаются локальными, пока вы не отправите их командой Sync Up.

automation.watchExternalChanges

Значение Поведение
false На сервер уходят только сохранения из редактора VS Code. Изменения от сборки, git, терминала и других программ остаются локальными.
true Любое изменение файла на диске уходит на сервер по правилам uploadOnSave. События одного файла объединяются за 75 мс.

Этот параметр влияет только на загрузку. Без uploadOnSave он ничего не отправляет. Переключение ветки git при true отправит на сервер все изменённые файлы.

automation.diffOnOpen

Значение Поведение
"off" Сравнения нет.
"always" При открытии файла во вкладке расширение скачивает серверную копию и сравнивает. Подробности в разделе «Сравнение при открытии».

automation.deleteOnLocalDelete

Значение Поведение
"off" Сервер не трогается.
"ask" Перед каждым удалением появляется окно с кнопкой «Delete».
"always" Файлы удаляются на сервере без вопроса. Папки удаляются только после подтверждения кнопкой «Delete recursively», потому что удаление идёт со всем содержимым.

Расширение замечает удаление в VS Code и вне его: в проводнике, в терминале, при git rm и при переключении ветки git. Параметр watchExternalChanges на удаление не влияет. Если на сервере файла уже нет, расширение ничего не делает.

Временные файлы

Ранние версии расширения писали на сервер временные файлы .ach-tmp-*. После сбоя такие файлы могли остаться. Текущая версия на сервер временных файлов не пишет. Убрать старые помогают два средства:

  • команда ACH Remote Sync: Clean Up Orphan Temp Files, запуск вручную;
  • параметр "cleanOrphansOnConnect": true, проверка при каждом подключении.

Обход идёт по всей папке remotePath, поэтому на большом сайте занимает время. Папки .ach-trash от старых версий расширение не трогает, удалите их на сервере сами.

Несколько серверов

Один файл настроек описывает одно подключение. Профилей и переключения окружений внутри файла нет. Чтобы работать с несколькими серверами, откройте рабочую область из нескольких папок (multi-root) и положите в каждую свой .vscode/ach-remote-sync.json.

У каждой папки своё соединение, своя очередь и свой элемент в строке состояния. Команды Connect, Disconnect и Clean Up Orphan Temp Files спрашивают, с какой папкой работать. Sync Up и Sync Down выбирают папку по файлу.

Команды

Все команды доступны в палитре (Ctrl+Shift+P) с префиксом ACH Remote Sync:.

Команда Что делает
ACH Remote Sync: Connect Подключается к серверу. Вызывать её не обязательно: любая операция подключается сама.
ACH Remote Sync: Disconnect Закрывает соединение и сбрасывает запомненные сведения о сервере.
ACH Remote Sync: Sync Up (current file) Отправляет на сервер открытый файл или файл, выбранный в контекстном меню. Создаёт недостающие папки на сервере. Работает с файлами, папку целиком не отправляет.
ACH Remote Sync: Sync Down (current file) Скачивает серверную копию открытого или выбранного файла и заменяет локальный. Перед заменой сохраняет снимок локального файла.
ACH Remote Sync: Cancel All Pending Operations Убирает из очереди все операции, которые ещё не начались, во всех папках. Текущая операция доводится до конца.
ACH Remote Sync: Clean Up Orphan Temp Files Спрашивает минимальный возраст в часах (по умолчанию 24), обходит remotePath и удаляет файлы .ach-tmp-* старше этого возраста. Ход работы виден в уведомлении, там же её можно отменить.
ACH Remote Sync: Show Log Открывает журнал в панели Output.
ACH Remote Sync: Hello Показывает короткое сообщение, что расширение запущено.
ACH Remote Sync: Smoke: Test Connection Подключается по профилю achRemoteSync.testProfile, читает список файлов в remotePath и отключается. Файлы не меняет.
ACH Remote Sync: Smoke: Test Upload По профилю achRemoteSync.testProfile отправляет в remotePath маленький файл .ach-smoke-<время>.txt, проверяет размер и удаляет файл.
ACH Remote Sync: Smoke: Test Session Queue По профилю achRemoteSync.testProfile ставит в очередь пять чтений папки и проверяет, что они выполнились по порядку.

Команды Sync Up (current file) и Sync Down (current file) есть также в контекстном меню проводника и в контекстном меню заголовка вкладки.

Проверочный профиль

Команды Smoke работают без файла в проекте. Они берут настройки из пользовательского параметра achRemoteSync.testProfile. Это единственная настройка расширения в settings.json. Формат тот же, что у .vscode/ach-remote-sync.json:

"achRemoteSync.testProfile": {
  "protocol": "sftp",
  "host": "example.com",
  "username": "deploy",
  "auth": { "type": "agent" },
  "remotePath": "/var/www/example.com"
}

Команды Smoke не показывают окно доверия ключу. Неизвестный ключ сервера они отклоняют при "strictHostKey": true и принимают при false.

Строка состояния

Для каждой настроенной папки справа в строке состояния есть свой элемент. Щелчок по нему открывает журнал.

Текст Вид Значение
ACH: idle значок вилки, жёлтый фон Соединения нет. Оно откроется при первой операции.
ACH: connecting to deploy@example.com… вращение, жёлтый фон Идёт подключение.
ACH: deploy@example.com галочка, зелёный текст Соединение открыто, очередь пуста.
ACH: auto-upload (3) вращение, зелёный текст Идёт операция. Число в скобках показывает, сколько операций в работе, если их больше одной.
ACH: error — … красный фон Последняя операция завершилась ошибкой. Текст ошибки есть в журнале. Следующая успешная операция вернёт обычный вид.

Названия операций в строке: sync up, sync down, auto-upload, auto-mkdir, auto-delete, diff-on-open, fetch remote, stat, cleanup orphans. После ручной загрузки или скачивания на несколько секунд появляется сообщение с именем файла, серверным путём и размером.

Значки в проводнике

Значок Цвет Значение
● жёлтый Файл изменён в редакторе и ещё не отправлен.
⬆ синий Файл отправляется.
✓ зелёный Файл отправлен или совпадает с серверной копией. Значок исчезает через 3 секунды.
! красный Загрузка при сохранении не удалась. Текст ошибки виден во всплывающей подсказке.

При "uploadOnSave": "always" значок проходит путь ●, ⬆, ✓ сам. В ручном режиме ● остаётся после сохранения и напоминает, что файл не отправлен. Расширение помнит хэш последней отправленной или скачанной версии. Если после сохранения содержимое совпадает с ней, значок сменится на ✓.

Сравнение при открытии

Когда вы открываете файл во вкладке, расширение в фоне скачивает его серверную копию и сравнивает содержимое по SHA-256.

  • Копии совпадают. Ничего не происходит.
  • Копии различаются. Открывается окно сравнения Remote ↔ Local — <имя файла>. Слева серверная версия, только для чтения. Справа ваш локальный файл.
  • Файла на сервере нет. Ничего не происходит.

Вместе со сравнением появляется окно <имя> differs from remote. с размерами обеих версий и тремя вариантами:

  • «Upload local» отправляет локальный файл на сервер и закрывает сравнение;
  • «Download remote» заменяет локальный файл серверной копией, сохраняет снимок прежней версии и закрывает сравнение;
  • отмена закрывает только окно. Сравнение остаётся открытым, его можно изучить и поправить вручную.

В правой части сравнения можно править текст. Ctrl+S сохраняет локальный файл. Текст окна упоминает резервную копию на сервере. Начиная с версии 2.0.11 расширение её не создаёт.

Ограничения:

  • файлы больше 5 МБ не сравниваются;
  • исключённые файлы не сравниваются;
  • каждый файл сравнивается один раз, пока открыта его вкладка. Закройте и откройте вкладку, чтобы сравнить заново;
  • после перезагрузки окна расширение проверяет все вкладки, которые остались открытыми.

Sync Up, Sync Down и снимки

Sync Up отправляет файл тем же способом, что и загрузка при сохранении:

  1. проверяет, что локальный файл существует;
  2. проверяет серверную копию. Если на сервере непустой файл, а локальный пустой, загрузка останавливается с ошибкой TRANSFER_ZERO_BYTE_OVERWRITE;
  3. создаёт недостающие папки на сервере;
  4. перезаписывает содержимое серверного файла на месте. Inode, права и владелец сохраняются;
  5. запрашивает размер файла на сервере. Расхождение даёт ошибку TRANSFER_SIZE_MISMATCH.

Sync Down работает так:

  1. проверяет, что файл есть на сервере;
  2. отказывается заменять непустой локальный файл пустым серверным;
  3. скачивает файл во временный .ach-tmp-… в той же папке и сверяет размер;
  4. копирует прежний локальный файл в снимок;
  5. заменяет локальный файл скачанным.

Снимки лежат в папке .vscode/.ach-remote-sync-cache/. Для каждого файла там своя папка с тем же относительным путём, имя снимка состоит из имени файла и метки времени. Для каждого файла хранятся три последних снимка, старые удаляются. Команды восстановления нет: нужный снимок скопируйте на место файла вручную. Папка .vscode исключена из синхронизации, поэтому снимки на сервер не попадают.

Очередь, повторы и подключение

  • Все операции одной папки идут через общую очередь по одной.
  • Соединение открывается при первой операции и остаётся открытым.
  • Если соединение оборвалось, расширение подключается заново перед следующей операцией.
  • Сетевые сбои повторяются до трёх попыток. Пауза начинается с 0,5 секунды и растёт вдвое. Ошибки входа, прав доступа и проверки размера не повторяются.
  • Если файл меняется во время его загрузки, расширение дождётся конца и отправит итоговую версию один раз.
  • Команда Cancel All Pending Operations очищает очередь.

Журнал

Команда ACH Remote Sync: Show Log или щелчок по строке состояния открывает канал «ACH Remote Sync» в панели Output. В журнал попадают подключения, загрузки, ошибки и причины, по которым файл пропущен. При "logLevel": "debug" видна каждая операция очереди с временем выполнения. Пароли и парольные фразы в журнале заменяются на [redacted].

Типовые сценарии

Сервер разработки со сборкой в режиме наблюдения

На сервере работает webpack --watch или похожий сборщик. Вы правите исходники локально, сервер собирает их сам.

{
  "protocol": "sftp",
  "host": "example.com",
  "username": "deploy",
  "auth": { "type": "agent" },
  "remotePath": "/var/www/example.com",
  "automation": {
    "uploadOnSave": "always",
    "diffOnOpen": "always",
    "deleteOnLocalDelete": "ask",
    "watchExternalChanges": false
  },
  "ignore": [
    "dist/**",
    "*.log"
  ]
}
  • Запись на месте даёт вотчеру одно событие изменения, сборка не видит пропавший файл.
  • node_modules исключена по умолчанию, зависимости ставятся на сервере.
  • Папку с результатом сборки (здесь dist) добавьте в ignore. Тогда локальная сборка не затрёт серверную, а сравнение при открытии не будет срабатывать на собранных файлах.
  • watchExternalChanges выключен: файлы, которые меняет локальная сборка или git, на сервер не уходят.

Собираете локально и отправляете результат

Если сборка идёт на вашей машине и собранные файлы нужны на сервере, уберите папку сборки из ignore и включите "watchExternalChanges": true. Тогда на сервер уходит всё, что меняется на диске. Помните, что переключение ветки git тоже отправит изменённые файлы.

Ручной режим

Оставьте uploadOnSave и deleteOnLocalDelete в значении "off". Сравнение при открытии покажет расхождения, а файлы вы отправите командой Sync Up или кнопкой «Upload local». Жёлтый значок ● напомнит о неотправленных правках.

Сайт с пользовательскими файлами

Папки, куда пишет сам сайт, добавьте в ignore. Например wp-content/uploads/** и wp-content/cache/** для WordPress. Тогда расширение не будет их сравнивать и не удалит их на сервере.

Осторожно с удалением

При "deleteOnLocalDelete": "always" сервер повторяет любое локальное удаление, включая удаление при переключении ветки git. Для общего или боевого сервера выбирайте "ask".

Решение проблем

Начинайте с журнала: ACH Remote Sync: Show Log. Для подробностей поставьте "logLevel": "debug" и перезагрузите окно.

Расширение не реагирует на сохранение

  • Проверьте automation.uploadOnSave: по умолчанию стоит "off".
  • Проверьте, что watch не равен false.
  • Проверьте, не попадает ли файл под ignore или встроенные исключения. В режиме debug журнал пишет строку autoUpload[save]: … ignored.
  • При "onlyExisting" новые файлы не отправляются, пока их нет на сервере.
  • После правки файла настроек перезагрузите окно.

«no workspace has .vscode/ach-remote-sync.json configured»

Расширение не нашло файл настроек. Проверьте, что файл лежит в .vscode в корне папки, открытой в VS Code, и перезагрузите окно.

«… is not inside a configured workspace»

Файл лежит вне папки проекта или вне папки из localPath.

AUTH_FAILED

Сервер отклонил вход. Проверьте username. Проверьте вход из терминала: ssh -v deploy@example.com. Убедитесь, что открытый ключ есть в ~/.ssh/authorized_keys на сервере, а агент предлагает нужный ключ (ssh-add -l).

AUTH_AGENT_UNAVAILABLE

Агент не найден. На Windows запустите службу ssh-agent или Pageant. На macOS и Linux проверьте, что $SSH_AUTH_SOCK задана в среде, из которой запущен VS Code.

AUTH_KEY_ENCRYPTED

Ключ зашифрован, а парольной фразы в настройках нет, или она неверна. Укажите passphrase или загрузите ключ в агент и перейдите на "type": "agent".

AUTH_KEY_INVALID

Файл ключа не найден, не читается или не распознан. Проверьте путь. На macOS и Linux у файла ключа должны быть права 600.

CONFIG_INVALID при подключении по FTP

Для FTP и FTPS подходят только "type": "password" и "type": "auto" с паролем.

Подключение отклонено, в журнале HOST KEY MISMATCH

Ключ сервера отличается от записанного в known_hosts. Это бывает после переустановки сервера и при атаке посредника. Уточните новый отпечаток у администратора. Если смена ключа законна, удалите старую запись и подключитесь снова:

ssh-keygen -R example.com

Для нестандартного порта: ssh-keygen -R "[example.com]:2222".

NETWORK_REFUSED, NETWORK_TIMEOUT, NETWORK_UNREACHABLE

  • NETWORK_REFUSED: сервер доступен, но на порту никто не слушает. Проверьте port и что служба SSH или FTP запущена.
  • NETWORK_TIMEOUT: сервер не ответил. Проверьте адрес, брандмауэр и VPN. Для медленного соединения увеличьте readyTimeoutMs (SFTP) или connectTimeoutMs (FTP).
  • NETWORK_UNREACHABLE: имя сервера не найдено. Проверьте host или подключитесь по IP-адресу.

TRANSFER_ZERO_BYTE_OVERWRITE

Локальный файл пустой, а серверный нет. Расширение отказалось затирать серверную копию. Обычно это сбой редактора. Восстановите файл из локальной истории: правый щелчок по файлу в проводнике, раздел «Timeline». Если пустой файл нужен на самом деле, удалите серверный файл, затем отправьте локальный.

TRANSFER_SIZE_MISMATCH

После загрузки сервер сообщил другой размер. Частые причины: закончилось место на диске сервера или квота. Файл на сервере мог остаться недописанным. Освободите место и отправьте файл ещё раз.

Сравнение не открывается, хотя файлы разные

  • Файл больше 5 МБ.
  • Файл исключён через ignore.
  • diffOnOpen равен "off" или watch равен false.
  • Файла нет на сервере.
  • Файл уже сравнивался в этой вкладке. Закройте вкладку и откройте снова.
  • Соединение в ошибке. Откройте журнал щелчком по строке состояния.

Часть файлов не доехала после серии быстрых правок

Эта ошибка была в версиях до 2.0.14 и исправлена. Обновите расширение. На старой версии сохраните пропущенный файл ещё раз.

На сервере остались файлы .ach-tmp-* или папки .ach-trash

Их оставили старые версии. Файлы .ach-tmp-* удалит команда ACH Remote Sync: Clean Up Orphan Temp Files. Папки .ach-trash удалите на сервере вручную.

На сервере лежат файлы из .vscode или .claude

До версии 2.0.7 эти папки не были исключены и могли попасть на сервер. Сейчас они исключены, но уже отправленное расширение не удаляет. Удалите их на сервере вручную.

Требования

  • Visual Studio Code 1.96 или новее. Подходят Windows, macOS и Linux.
  • Сервер с доступом по SFTP (любой сервер с SSH), FTP или FTPS.
  • Для входа по ключу через агент: запущенный SSH-агент с добавленным ключом. На Windows подходит встроенная служба OpenSSH Agent или Pageant.

Node.js ставить не нужно. Расширение собрано в один файл вместе со всеми библиотеками и работает на среде, которая уже встроена в VS Code. Внешние программы ssh и sftp расширение тоже не вызывает: протоколы реализованы внутри него.

Установка из файла .vsix

Скачайте файл ach-remote-sync-<версия>.vsix с этой страницы.

Через интерфейс VS Code

  1. Откройте панель расширений: Ctrl+Shift+X, на macOS Cmd+Shift+X.
  2. Нажмите «…» в правом верхнем углу панели.
  3. Выберите «Install from VSIX…».
  4. Укажите скачанный файл.
  5. Если VS Code предложит перезагрузить окно, согласитесь.

Тот же пункт есть в палитре команд: Extensions: Install from VSIX….

Из командной строки

code --install-extension ach-remote-sync-2.0.15.vsix

Подставьте имя скачанного файла. Если команда code не найдена, на macOS выполните в палитре VS Code Shell Command: Install 'code' command in PATH. На Windows и Linux она обычно доступна после установки VS Code.

После установки расширение появится в списке под именем «ACH Remote Sync — SFTP/FTP for VS Code». Оно включается только в проектах, где есть файл .vscode/ach-remote-sync.json.

Первый конфиг

Создайте в корне проекта файл .vscode/ach-remote-sync.json:

{
  "protocol": "sftp",
  "host": "example.com",
  "port": 22,
  "username": "deploy",
  "auth": { "type": "agent" },
  "remotePath": "/var/www/example.com",
  "automation": {
    "uploadOnSave": "off",
    "diffOnOpen": "always",
    "deleteOnLocalDelete": "off"
  }
}
  • remotePath: папка на сервере, которая соответствует корню проекта.
  • auth: способ входа. Пример использует SSH-агент. Вход по файлу ключа или паролю описан на вкладке «Использование».
  • automation: в примере автоматическая загрузка выключена. Включите "uploadOnSave": "always", когда убедитесь, что подключение и исключения настроены верно.

Сохраните файл и выполните в палитре Developer: Reload Window. Расширение читает настройки при запуске окна, поэтому перезагрузка нужна и после каждой правки файла.

Проверка подключения

  1. Посмотрите в строку состояния справа внизу. Там должен появиться элемент ACH: idle.
  2. Выполните в палитре ACH Remote Sync: Connect.
  3. При первом подключении по SFTP появится окно с отпечатком ключа сервера. Сверьте отпечаток и нажмите «Trust Permanently».
  4. В строке состояния появится ACH: deploy@example.com, а в углу сообщение об успешном подключении.
  5. Откройте любой файл проекта. Если он отличается от серверной копии, откроется сравнение.
  6. Щёлкните правой кнопкой по файлу в проводнике и выберите ACH Remote Sync: Sync Up (current file). Внизу на несколько секунд появится сообщение с серверным путём и размером файла.

Если что-то пошло не так, выполните ACH Remote Sync: Show Log. Журнал покажет причину. Разбор частых ошибок есть на вкладке «Использование», раздел «Решение проблем».

Обновления

VS Code обновляет расширения автоматически только из маркетплейса. Расширение, установленное из файла, само не обновится. Новую версию ставят так же: скачайте свежий .vsix с этой страницы и установите его поверх старого через «Install from VSIX…» или code --install-extension. Настройки проектов сохранятся, они лежат в файлах .vscode/ach-remote-sync.json. История версий есть на вкладке «Изменения».

Переход со старого ach-sftp

Если у вас стоит прежнее расширение ACH SFTP, переходите так:

  1. Отключите ACH SFTP в панели расширений. Удалять его сразу не обязательно.
  2. Установите ACH Remote Sync из файла .vsix.
  3. Для каждого проекта создайте новый файл .vscode/ach-remote-sync.json. Старый .vscode/ach-sftp.json новое расширение не читает.
  4. Перезагрузите окно и проверьте подключение.
  5. Когда всё работает, удалите ACH SFTP.

Соответствие основных параметров:

ach-sftp.json ach-remote-sync.json
"protocol", "host", "port", "username", "remotePath", "ignore" без изменений
"agent": true "auth": { "type": "agent" }
"privateKey": "~/.ssh/id" "auth": { "type": "key", "keyPath": "~/.ssh/id" }
"password": "…" "auth": { "type": "password", "password": "…" }
"keepaliveInterval" "keepaliveIntervalMs"
"connectionTimeout" "connectTimeoutMs"
"readyTimeout" "readyTimeoutMs"
"autoUpload": true "automation": { "uploadOnSave": "always" }
"autoDelete": true "automation": { "deleteOnLocalDelete": "always" }
"autoDownload" замены нет. Вместо тихого скачивания работает сравнение "diffOnOpen": "always"
"strictHostKey" "strictHostKey", логическое значение

Параметры persistentConnection, passive, concurrency и fileNameEncoding больше не нужны. Соединение держится открытым, FTP работает в пассивном режиме, операции идут по одной, имена файлов передаются в UTF-8.

Оба расширения могут работать одновременно, но тогда автоматику включайте только в одном из них. Иначе каждое сохранение и удаление выполнится дважды.

Файлы старого расширения .vscode/ach-sftp.json, .vscode/ach-sftp.sync.cache.json и .vscode/ach-sftp.diff.* после перехода можно удалить.

  1. v2.0.15 последняя

    Изменено 2

    • Автозагрузка теперь идёт по одному файлу за раз: пока файл загружается, новые правки копятся, и после загрузки уходит одна итоговая версия. Серия быстрых сохранений больше не порождает пачку лишних загрузок устаревшего содержимого.
    • Если загрузка сорвалась или устарела, следом всегда уходит чистая загрузка последней версии файла — сервер приходит к тому же состоянию, что и локальная копия.