ConfluenceImportExport
Health Uyari
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Gecti
- Code scan — Scanned 6 files during light audit, no dangerous patterns found
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Утилита командной строки и MCP-сервер для двусторонней синхронизации страниц Confluence с локальной файловой системой (.NET 10)
Confluence Page Exporter v2.11.0
Русский | 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 - Многоуровневая конфигурация с приоритетом: 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, а не копировать существующую локальную папку.
Правило для AI-ассистентов
В папке 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-сервер для ИИ-агентов
Утилиту можно запустить как 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. - Сервер автоматически передаёт агенту короткий гайд по использованию
через MCPInitializeResult.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отключает параллелизм)
Пример confluence-exporter.json
{
"Global": {
"BaseUrl": "https://wiki.example.com",
"Username": "[email protected]",
"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 [email protected]
export CONFLUENCE_EXPORTER__GLOBAL__TOKEN=secret
export CONFLUENCE_EXPORTER__DOWNLOAD__OUTPUTDIR=./export
export CONFLUENCE_EXPORTER__DOWNLOAD__UPDATE__PAGEID=12345
export CONFLUENCE_EXPORTER__UPLOAD__SOURCEDIR=./export
Формат вызова
ConfluencePageExporter [глобальные параметры] <команда подкоманда> [параметры команды]
Обзор команд
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 после завершения команды выводится сводка всех страниц, требующих ручного разрешения.
Команда download update
Принудительно скачивает страницу Confluence (или поддерево) на локальный диск. Различающиеся страницы перезаписываются серверными версиями. Локальные правки будут потеряны.
Параметры download update
--base-url(обязательный)--username(обязательный)--token(обязательный)--space-key(обязательный)--page-idили--page-title(обязательно указать ровно один)--output-dir(обязательный)--recursive(опционально)--auth-type onprem|cloud(опционально, по умолчаниюonprem)--dry-run(опционально)--report(опционально)
Пример download update
ConfluencePageExporter download update \
--base-url https://wiki.example.com \
--username [email protected] \
--token <token> \
--space-key DOCS \
--page-id 12345 \
--recursive \
--output-dir ./export
Команда download merge
Скачивает страницы с сервера, перезаписывая только те, которые новее на сервере. Локальные правки сохраняются. Конфликты (двойные правки) пропускаются с предупреждением.
Параметры download merge
--base-url(обязательный)--username(обязательный)--token(обязательный)--space-key(обязательный)--page-idили--page-title(обязательно указать ровно один)--output-dir(обязательный)--recursive(опционально)--auth-type onprem|cloud(опционально, по умолчаниюonprem)--dry-run(опционально)--report(опционально)
Пример download merge
ConfluencePageExporter --report download merge \
--base-url https://wiki.example.com \
--username [email protected] \
--token <token> \
--space-key DOCS \
--page-id 12345 \
--recursive \
--output-dir ./export
Команда upload update
Принудительно загружает локальные страницы на сервер. Различающиеся страницы перезаписываются локальными версиями. Серверные правки будут потеряны. Перемещение страниц при расхождении родителя выполняется автоматически.
Параметры upload update
--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(опционально, по умолчаниюonprem)--dry-run(опционально)--report(опционально)
Приоритет определения корневой страницы
- Явно заданные
--page-id/--page-title - Локальный файл-маркер
.id<pageId>_<version>вsource-dir - Имя папки
source-dirкак заголовок страницы
Если корневая страница не найдена, команда завершается ошибкой.
Пропуск неизменённых страниц
Перед отправкой обновления утилита сравнивает локальный контент с серверным. Если заголовок, контент и родительская страница не изменились, обновление пропускается — это предотвращает создание лишних версий на сервере.
Обновление вложений
Вложения обновляются через версионирование Confluence (создание новой версии файла). Перед загрузкой проверяется, изменился ли файл (по размеру и SHA-256 хэшу). Неизменённые вложения пропускаются.
Пример upload update
ConfluencePageExporter upload update \
--base-url https://wiki.example.com \
--username [email protected] \
--token <token> \
--space-key DOCS \
--source-dir ./export/MyPage \
--recursive
Команда upload merge
Загружает на сервер только локально изменённые страницы. Серверные правки сохраняются. Конфликты (двойные правки) пропускаются с предупреждением.
Дополнительно upload merge распознаёт структурные изменения локального дерева:
- Локальное перемещение папки (новая родительская папка имеет свой
.id-маркер) — выполняется перемещение страницы на сервере (ancestors) в одном вызове API. - Новая папка внутри уже синхронизированного поддерева — создаётся как страница на сервере с правильным родителем и с автоматической записью локального
.id-маркера. Использоватьupload createдля одиночных новых страниц внутри существующей иерархии не нужно.
Если контент той же страницы был изменён и на сервере, структурное перемещение откладывается: страница попадает в раздел Skipped с подсказкой выполнить download merge, переместить папку заново и повторить upload 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(опционально, по умолчаниюonprem)--dry-run(опционально)--report(опционально)
Пример upload merge
ConfluencePageExporter --report upload merge \
--base-url https://wiki.example.com \
--username [email protected] \
--token <token> \
--space-key DOCS \
--source-dir ./export/MyPage \
--recursive
Команда upload create
Создает новые страницы Confluence по локальному содержимому.
Параметры upload create
--base-url(обязательный)--username(обязательный)--token(обязательный)--space-key(обязательный)--source-dir(обязательный)--parent-idили--parent-title(опционально)--recursive(опционально)--auth-type onprem|cloud(опционально, по умолчаниюonprem)--dry-run(опционально)
Пример upload create
ConfluencePageExporter upload create \
--base-url https://wiki.example.com \
--username [email protected] \
--token <token> \
--space-key DOCS \
--parent-id 67890 \
--source-dir ./export/NewPage \
--recursive
Команда compare
Сравнивает дерево страниц в Confluence с локальным снимком и выводит отчет.
Для каждого обнаруженного различия определяется вероятный источник изменения (сервер или локально) на основе сравнения дат модификации.
При использовании --detect-source дополнительно анализируется история версий Confluence для повышения точности определения источника переименований и перемещений.
Параметры compare
--base-url(обязательный)--username(обязательный)--token(обязательный)--space-key(обязательный)--page-idили--page-title(обязательно указать ровно один)--output-dir(обязательный)--recursive(опционально)--match-by-title(опционально)--detect-source(опционально) — анализировать историю версий для определения источника переименований и перемещений (дополнительные API-вызовы)--auth-type onprem|cloud(опционально, по умолчаниюonprem)
Стратегия сопоставления
- по умолчанию: сопоставление локальных страниц по
.id<pageId>_<version> - с
--match-by-title: если.idотсутствует, используется fallback-сопоставление по заголовкам/пути папок
Определение источника изменений
Для каждого обнаруженного различия утилита пытается определить, где произошло изменение — локально или на сервере. Используется два уровня эвристик:
Сравнение версий маркера (для контента, если доступен
.id<pageId>_<version>) — если версия маркера совпадает с серверной, изменение локальное; если серверная версия новее — изменение на сервере. Достоверность: высокая.Сравнение дат (всегда, как fallback) — сопоставляет дату последней модификации серверной страницы (
version.when) с датой изменения локальной папки (переименование/перемещение) или файлаindex.html(контент). Достоверность: средняя.Анализ истории версий (с
--detect-source) — для переименований ищет прежний заголовок в истории версий страницы, для перемещений ищет прежнего родителя в ancestors исторических версий. Достоверность: высокая.
Пример compare
ConfluencePageExporter compare \
--base-url https://wiki.example.com \
--username [email protected] \
--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)
Команда config show
Выводит текущую действующую конфигурацию с указанием источника каждого значения.
Возможные источники:
[CLI]— задано аргументом командной строки[ENV]— задано переменной окружения[FILE]— задано в JSON-файле конфигурации[DEFAULT]— значение по умолчанию
Пример config show
ConfluencePageExporter config show
Пример вывода:
Effective configuration
=======================
Global:
BaseUrl = https://wiki.example.com [FILE]
Username = [email protected] [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
Миграция с v1.x
В версии 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 |
Отчёт о страницах с конфликтами (новый глобальный ключ) |
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi