Русский | English
Утилита командной строки для синхронизации страниц Confluence с локальной структурой папок.
Инструмент поддерживает:
- скачивание страниц из Confluence на диск с принудительной перезаписью (
download update) или умным слиянием (download merge) - загрузку локальных страниц обратно в Confluence с принудительной перезаписью (
upload update), умным слиянием (upload merge) или созданием новых (upload create) - сравнение дерева страниц в Confluence с локальным снимком (
compare) - просмотр действующей конфигурации с указанием источников значений (
config show)
- Git-подобная модель синхронизации:
update(force) иmerge(smart) - Определение конфликтов: если страница изменена и локально, и на сервере — конфликт выявляется, перезапись не выполняется, пользователь получает предупреждение
- Отчёт
--report— сводка страниц, требующих ручного разрешения (конфликты, удалённые страницы) - Выбор страницы по
--page-idили--page-title - Опциональная рекурсивная обработка (
--recursive) - Работа с несколькими пространствами: пространство страницы сохраняется в маркере и берётся с сервера; деревья из разных пространств можно держать рядом и синхронизировать вместе (
--multi-treeдля upload). Непреднамеренный перенос поддерева в чужое пространство отклоняется и попадает в отчёт - Формат локального снимка:
- одна папка на страницу (имя папки = заголовок страницы, с sanitization под файловую систему)
- файл
index.htmlс контентом страницы в storage representation - вложения как отдельные файлы
- файл-маркер
.id<pageId>_<version>(в теле — JSON с оригинальным заголовком и ключом пространства) для стабильной идентификации страницы и отслеживания версии
- Режимы аутентификации:
--auth-type onpremи--auth-type cloud; по умолчанию тип определяется автоматически по--base-url(хосты*.atlassian.net→cloud) - Полная поддержка Confluence Cloud (REST API v2 + сохранившиеся v1-эндпоинты): все команды — download, upload, compare, вложения — работают одинаково на Server/DC и Cloud; числовые идентификаторы пространств Cloud прозрачно резолвятся из ключей
- Многоуровневая конфигурация с приоритетом: CLI > переменные окружения > файл > значение по умолчанию
- Глобальный параметр
--verboseдля подробного (debug-level) вывода - Поддержка dry-run там, где применимо
При выгрузке (download update/download merge) страницы сохраняются в иерархию папок внутри --output-dir.
Каждая папка страницы содержит контент, маркер идентификатора и вложения.
<output-dir>/
Root Page/
index.html
.id12345_7
image.png
spec.pdf
Child Page A/
index.html
.id23456_3
Child Page B/
index.html
.id34567_1
Правила:
- имя папки страницы = заголовок страницы в Confluence (каждый недопустимый символ заменяется на
_); оригинальный заголовок сохраняется в маркере.id*и восстанавливается при загрузке на сервер; переименование папки пользователем интерпретируется как намерение переименовать страницу index.htmlсодержитbody.storage.value- файл
.id<pageId>_<version>используется для стабильного сопоставления при синхронизации и сравнении; суффикс_<version>отражает номер версии страницы на сервере в момент последней синхронизации; время последней записи маркера (LastWriteTimeUtc) используется как точка отсчёта для определения конфликтов; содержимое файла хранит оригинальный заголовок страницы Confluence для восстановления при загрузке на сервер - все файлы, кроме
index.htmlи.id*, считаются вложениями страницы
Санитизация имён папок выполняется по правилам файловой системы, на которой создаётся зеркало: на Windows заменяются символы < > : " / \ | ? * и управляющие, на Linux/macOS — только / и \0. Это значит, что зеркало привязано к ОС, на которой оно создано:
- заголовок
Модуль "Провайдеры"на Windows даст папкуМодуль _Провайдеры_, а на Linux —Модуль "Провайдеры"(такое имя папки на Windows создать нельзя); - прямое копирование зеркала между ОС (через облачные папки,
scp/rsync, сетевые шары) может привести к невалидным именам или к тому, что утилита перестанет узнавать уже синхронизированные страницы.
Рекомендуемый сценарий при смене рабочей машины — заново выгрузить зеркало с сервера Confluence через download update или download merge, а не копировать существующую локальную папку.
В папке docs/ai-rules/ лежит файл local-mirror-format.mdc — описание структуры и формата локального зеркала Confluence, которое можно подключить к вашему AI-ассистенту (Cursor, Claude Code, Continue, Aider, Windsurf и др.), чтобы он корректно понимал иерархию папок, формат index.html (Confluence Storage Format), маркеры .id* и вложения при работе с выгруженным деревом страниц.
Инструкции по подключению для разных инструментов — в docs/ai-rules/README.md.
Утилиту можно запустить как MCP-сервер
по stdio — это даёт ИИ-агентам (Claude Desktop, Cursor, Codex и др.)
возможность выполнять шесть операций синхронизации
(download update/merge, upload update/create/merge, compare)
прямо из чата, без перехода в терминал, плюс два helper-инструмента
для самодиагностики и agent-assisted merge:
confluence_ping— лёгкая проверка связности и учётных данных (base URL, текущий пользователь, latency, sandbox-настройки); доступна и в--read-only.confluence_get_page_content— получение storage-format XHTML страницы (текущая или историческая версия) для сценария «конфликт → diff → merge», когда агент локально читаетindex.htmlсвоими файловыми инструментами и сводит правки. Поддерживает 2-way и 3-way merge (черезversionиз локального маркера.idPAGEID_VER).
ConfluencePageExporter mcp --root-dir <path> [--read-only]--root-dir— обязательная песочница: агент не может писать вне неё.--read-only— блокирует upload-инструменты (download/compare/ping/get_page_content остаются).- Параметры подключения к Confluence (BaseUrl/Username/Token/SpaceKey/AuthType)
задаются через env-переменные
CONFLUENCE_EXPORTER__*или JSON-конфиг — они никогда не попадают в context window LLM. - Сервер автоматически передаёт агенту короткий гайд по использованию
через MCP
InitializeResult.Instructions— большинство клиентов подмешивают это в системный промпт без ручных действий.
Подробное описание инструментов, формата результатов, кодов ошибок,
сценарии 2-/3-way merge, гайд для агента и готовые конфиги для
Claude Desktop / Cursor / Codex — в docs/mcp/.
Готовые сборки публикуются на GitHub Releases как self-contained single-file архивы — .NET Runtime ставить не нужно.
| Платформа | Архив |
|---|---|
| Windows x64 | ConfluencePageExporter-v<версия>-win-x64.zip |
| Linux x64 | ConfluencePageExporter-v<версия>-linux-x64.tar.gz |
| macOS arm64 | ConfluencePageExporter-v<версия>-osx-arm64.tar.gz |
После распаковки архива получаете один исполняемый файл (ConfluencePageExporter.exe или ConfluencePageExporter), README.md, README.en.md и LICENSE. На macOS/Linux потребуется chmod +x ConfluencePageExporter.
dotnet buildСамостоятельная публикация self-contained single-file сборки:
dotnet publish src/ConfluencePageExporter -c Release -r <RID> \
--self-contained true \
-p:PublishSingleFile=true \
-p:IncludeNativeLibrariesForSelfExtract=true \
-p:EnableCompressionInSingleFile=trueгде <RID> — один из win-x64, linux-x64, linux-arm64, osx-arm64, osx-x64.
Утилита использует стандартный Microsoft.Extensions.Configuration pipeline. Параметры читаются из нескольких источников с приоритетом (последний побеждает):
- JSON-файл — по умолчанию
confluence-exporter.jsonв текущей директории; путь можно указать явно через--config <path>. - Переменные окружения — с префиксом
CONFLUENCE_EXPORTER__, двойное подчёркивание разделяет секции (например,CONFLUENCE_EXPORTER__GLOBAL__BASEURL). - Параметры командной строки — явно заданные CLI-аргументы имеют наивысший приоритет.
Указываются перед именем команды:
--config <path>— путь к JSON-файлу конфигурации--verbose— включить подробный (debug-level) вывод в лог--report— вывести сводку страниц, требующих ручной обработки, после завершения команды--max-parallelism N— максимальное число одновременных операций при обходе дерева страниц вdownload/upload(по умолчанию8;1отключает параллелизм)
{
"Global": {
"BaseUrl": "https://wiki.example.com",
"Username": "user@example.com",
"Token": "token-or-password",
"SpaceKey": "DOCS",
"AuthType": "onprem",
"DryRun": false,
"Recursive": true,
"Report": false,
"MaxParallelism": 8
},
"Download": {
"PageId": "12345",
"OutputDir": "./export",
"Merge": {
"OutputDir": "./export-merge"
}
},
"Upload": {
"SourceDir": "./export",
"Update": {
"PageId": "67890"
},
"Create": {
"ParentTitle": "Architecture"
},
"Merge": {
"PageTitle": "MyPage"
}
},
"Compare": {
"OutputDir": "./export",
"MatchByTitle": true,
"DetectSource": false
}
}Конфигурация поддерживает двухуровневую модель: общие параметры команды наследуются подкомандами и могут быть переопределены на уровне подкоманды.
Цепочка разрешения значений (от высшего приоритета к низшему):
- Секция подкоманды — например,
Download:Update:OutputDir - Секция команды — например,
Download:OutputDir - Global — для параметра
Recursive(fallback в коде хэндлера) - Значение по умолчанию —
false/null
Пример: если в JSON указан "Download": { "PageId": "12345", "OutputDir": "./export", "Merge": { "OutputDir": "./export-merge" } }, то:
download updateполучитPageId = 12345,OutputDir = ./export(наследование отDownload)download mergeполучитPageId = 12345(наследование),OutputDir = ./export-merge(переопределение)
Переменные окружения именуются по формату CONFLUENCE_EXPORTER__<Секция>__<Параметр> (всё в верхнем регистре):
export CONFLUENCE_EXPORTER__GLOBAL__BASEURL=https://wiki.example.com
export CONFLUENCE_EXPORTER__GLOBAL__USERNAME=user@example.com
export CONFLUENCE_EXPORTER__GLOBAL__TOKEN=secret
export CONFLUENCE_EXPORTER__DOWNLOAD__OUTPUTDIR=./export
export CONFLUENCE_EXPORTER__DOWNLOAD__UPDATE__PAGEID=12345
export CONFLUENCE_EXPORTER__UPLOAD__SOURCEDIR=./exportConfluencePageExporter [глобальные параметры] <команда подкоманда> [параметры команды]
ConfluencePageExporter download update ... # принудительное скачивание (сервер → локально)
ConfluencePageExporter download merge ... # умное скачивание с сохранением локальных правок
ConfluencePageExporter upload update ... # принудительная загрузка (локально → сервер)
ConfluencePageExporter upload merge ... # умная загрузка с сохранением серверных правок
ConfluencePageExporter upload create ... # создание новых страниц
ConfluencePageExporter compare ... # сравнение и отчёт
ConfluencePageExporter config show # отображение конфигурации
Утилита использует git-подобную модель с двумя режимами:
| Режим | Описание |
|---|---|
| update | Принудительная синхронизация. Источник считается эталоном, целевая сторона перезаписывается. Локальные/серверные правки на целевой стороне будут потеряны. |
| merge | Умная синхронизация. Перезаписываются только страницы, изменённые на стороне-источнике. Правки на целевой стороне сохраняются. Страницы с конфликтом (двойные правки) пропускаются с предупреждением. |
# Полностью скачать серверную версию, затерев локальные изменения
ConfluencePageExporter download update --page-id 12345 --output-dir ./export --recursive
# Скачать только серверные обновления, сохранив локальные правки
ConfluencePageExporter download merge --page-id 12345 --output-dir ./export --recursive
# Загрузить локальные изменения на сервер, затерев серверные
ConfluencePageExporter upload update --source-dir ./export/MyPage --recursive
# Загрузить только локальные обновления, сохранив серверные правки
ConfluencePageExporter upload merge --source-dir ./export/MyPage --recursive
# Двусторонняя синхронизация (сохраняются самые новые изменения с обеих сторон)
ConfluencePageExporter download merge --page-id 12345 --output-dir ./export --recursive --report
ConfluencePageExporter upload merge --source-dir ./export/MyPage --recursive --reportВ режиме merge утилита использует маркер .id<pageId>_<version> для определения конфликтов:
- syncTimeUtc = время последней записи маркерного файла (момент последней синхронизации)
- serverChanged = серверная версия новее версии в маркере
- localChanged = файл
index.htmlизменён послеsyncTimeUtc - Если оба флага
true→ конфликт: страница не перезаписывается ни в одну сторону, выводится предупреждение
При наличии ключа --report после завершения команды выводится сводка всех страниц, требующих ручного разрешения.
Принудительно скачивает страницу Confluence (или поддерево) на локальный диск. Различающиеся страницы перезаписываются серверными версиями. Локальные правки будут потеряны.
--base-url(обязательный)--username(обязательный)--token(обязательный)--space-key(обязательный)--page-idили--page-title(обязательно указать ровно один)--output-dir(обязательный)--recursive(опционально)--auth-type onprem|cloud(опционально, по умолчанию — автоопределение по--base-url)--dry-run(опционально)--report(опционально)
ConfluencePageExporter download update \
--base-url https://wiki.example.com \
--username user@example.com \
--token <token> \
--space-key DOCS \
--page-id 12345 \
--recursive \
--output-dir ./exportСкачивает страницы с сервера, перезаписывая только те, которые новее на сервере. Локальные правки сохраняются. Конфликты (двойные правки) пропускаются с предупреждением.
--base-url(обязательный)--username(обязательный)--token(обязательный)--space-key(обязательный)--page-idили--page-title(обязательно указать ровно один)--output-dir(обязательный)--recursive(опционально)--auth-type onprem|cloud(опционально, по умолчанию — автоопределение по--base-url)--dry-run(опционально)--report(опционально)
ConfluencePageExporter --report download merge \
--base-url https://wiki.example.com \
--username user@example.com \
--token <token> \
--space-key DOCS \
--page-id 12345 \
--recursive \
--output-dir ./exportПринудительно загружает локальные страницы на сервер. Различающиеся страницы перезаписываются локальными версиями. Серверные правки будут потеряны. Перемещение страниц при расхождении родителя выполняется автоматически.
--base-url(обязательный)--username(обязательный)--token(обязательный)--space-key(обязательный)--source-dir(обязательный)--page-idили--page-title(опционально, явное указание корневой страницы)--recursive(опционально)--multi-tree(опционально;--source-dirуказывает на каталог с несколькими деревьями — каждое обрабатывается со своим пространством; несовместимо с--page-id/--page-title)--auth-type onprem|cloud(опционально, по умолчанию — автоопределение по--base-url)--dry-run(опционально)--report(опционально)
- Явно заданные
--page-id/--page-title - Локальный файл-маркер
.id<pageId>_<version>вsource-dir - Имя папки
source-dirкак заголовок страницы
Если корневая страница не найдена, команда завершается ошибкой.
Перед отправкой обновления утилита сравнивает локальный контент с серверным. Если заголовок, контент и родительская страница не изменились, обновление пропускается — это предотвращает создание лишних версий на сервере.
Вложения обновляются через версионирование Confluence (создание новой версии файла). Перед загрузкой проверяется, изменился ли файл (по размеру и SHA-256 хэшу). Неизменённые вложения пропускаются.
ConfluencePageExporter upload update \
--base-url https://wiki.example.com \
--username user@example.com \
--token <token> \
--space-key DOCS \
--source-dir ./export/MyPage \
--recursiveЗагружает на сервер только локально изменённые страницы. Серверные правки сохраняются. Конфликты (двойные правки) пропускаются с предупреждением.
Дополнительно upload merge распознаёт структурные изменения локального дерева:
- Локальное перемещение папки (новая родительская папка имеет свой
.id-маркер) — выполняется перемещение страницы на сервере (ancestors) в одном вызове API. - Новая папка внутри уже синхронизированного поддерева — создаётся как страница на сервере с правильным родителем и с автоматической записью локального
.id-маркера. Использоватьupload createдля одиночных новых страниц внутри существующей иерархии не нужно.
Если контент той же страницы был изменён и на сервере, структурное перемещение откладывается: страница попадает в раздел Skipped с подсказкой выполнить download merge, переместить папку заново и повторить upload merge.
--base-url(обязательный)--username(обязательный)--token(обязательный)--space-key(обязательный)--source-dir(обязательный)--page-idили--page-title(опционально, явное указание корневой страницы)--recursive(опционально)--multi-tree(опционально;--source-dirуказывает на каталог с несколькими деревьями — каждое обрабатывается со своим пространством; несовместимо с--page-id/--page-title)--auth-type onprem|cloud(опционально, по умолчанию — автоопределение по--base-url)--dry-run(опционально)--report(опционально)
ConfluencePageExporter --report upload merge \
--base-url https://wiki.example.com \
--username user@example.com \
--token <token> \
--space-key DOCS \
--source-dir ./export/MyPage \
--recursiveСоздает новые страницы Confluence по локальному содержимому.
--base-url(обязательный)--username(обязательный)--token(обязательный)--space-key(обязательный)--source-dir(обязательный)--parent-idили--parent-title(опционально)--recursive(опционально)--auth-type onprem|cloud(опционально, по умолчанию — автоопределение по--base-url)--dry-run(опционально)
ConfluencePageExporter upload create \
--base-url https://wiki.example.com \
--username user@example.com \
--token <token> \
--space-key DOCS \
--parent-id 67890 \
--source-dir ./export/NewPage \
--recursiveСравнивает дерево страниц в Confluence с локальным снимком и выводит отчет.
Для каждого обнаруженного различия определяется вероятный источник изменения (сервер или локально) на основе сравнения дат модификации.
При использовании --detect-source дополнительно анализируется история версий Confluence для повышения точности определения источника переименований и перемещений.
--base-url(обязательный)--username(обязательный)--token(обязательный)--space-key(обязательный)--page-idили--page-title(обязательно указать ровно один)--output-dir(обязательный)--recursive(опционально)--match-by-title(опционально)--detect-source(опционально) — анализировать историю версий для определения источника переименований и перемещений (дополнительные API-вызовы)--auth-type onprem|cloud(опционально, по умолчанию — автоопределение по--base-url)
- по умолчанию: сопоставление локальных страниц по
.id<pageId>_<version> - с
--match-by-title: если.idотсутствует, используется fallback-сопоставление по заголовкам/пути папок
Для каждого обнаруженного различия утилита пытается определить, где произошло изменение — локально или на сервере. Используется два уровня эвристик:
-
Сравнение версий маркера (для контента, если доступен
.id<pageId>_<version>) — если версия маркера совпадает с серверной, изменение локальное; если серверная версия новее — изменение на сервере. Достоверность: высокая. -
Сравнение дат (всегда, как fallback) — сопоставляет дату последней модификации серверной страницы (
version.when) с датой изменения локальной папки (переименование/перемещение) или файлаindex.html(контент). Достоверность: средняя. -
Анализ истории версий (с
--detect-source) — для переименований ищет прежний заголовок в истории версий страницы, для перемещений ищет прежнего родителя в ancestors исторических версий. Достоверность: высокая.
ConfluencePageExporter compare \
--base-url https://wiki.example.com \
--username user@example.com \
--token <token> \
--space-key DOCS \
--page-id 12345 \
--recursive \
--match-by-title \
--detect-source \
--output-dir ./exportПример вывода:
Compare report
==============
Added in Confluence: 1
+ [55555] New Page (Root/New Page)
Deleted in Confluence: 0
Renamed/moved: 1
~ [12345] New Title | local: Root/Old Title -> confluence: Root/New Title
Переименование: СЕРВЕР (высокая) — заголовок 'Old Title' найден в серверной версии 3
Content changed: 1
* [23456] Some Page (Root/Some Page)
Источник: ЛОКАЛЬНО (средняя) — локальный файл изменён (2026-03-12) позже сервера (2026-03-10)
Выводит текущую действующую конфигурацию с указанием источника каждого значения.
Возможные источники:
[CLI]— задано аргументом командной строки[ENV]— задано переменной окружения[FILE]— задано в JSON-файле конфигурации[DEFAULT]— значение по умолчанию
ConfluencePageExporter config showПример вывода:
Effective configuration
=======================
Global:
BaseUrl = https://wiki.example.com [FILE]
Username = user@example.com [FILE]
Token = to***en [FILE]
SpaceKey = DOCS [FILE]
AuthType = onprem [DEFAULT]
Verbose = False [DEFAULT]
DryRun = False [DEFAULT]
Recursive = True [FILE]
Report = False [DEFAULT]
Для включения debug-level вывода используйте глобальный параметр --verbose:
ConfluencePageExporter --verbose download update \
--page-id 12345 \
--output-dir ./exportВ версии 2.0 произведены ломающие изменения в структуре команд:
| v1.x | v2.0 | Описание |
|---|---|---|
download |
download update |
Принудительное скачивание |
| — | download merge |
Умное скачивание (новая команда) |
upload update --on-error abort |
upload update |
Параметр --on-error удалён; при ошибке выполнение прерывается |
upload update --move-pages |
upload update |
Параметр --move-pages удалён; перемещение выполняется автоматически |
download --overwrite-strategy overwrite |
download update |
Параметр --overwrite-strategy удалён |
| — | upload merge |
Умная загрузка (новая команда) |
| — | --report |
Отчёт о страницах с конфликтами (новый глобальный ключ) |