Sync
Bidirectional synchronization between local markdown files and Confluence pages.
Prerequisites
Section titled “Prerequisites”- Authenticated profile with Confluence access (
atlcli auth login) - Space permission: View for pull, Edit for push operations
- Initialized sync directory (
atlcli wiki docs init)
Overview
Section titled “Overview”atlcli provides powerful sync capabilities:
- Watch: Real-time bidirectional sync with file watching and remote polling
- Pull: Download Confluence pages as markdown
- Push: Upload local changes to Confluence
- Conflict resolution: Three-way merge with automatic and manual resolution
Initialize
Section titled “Initialize”Set up a directory for sync:
atlcli wiki docs init ./docs --space TEAMOptions:
| Flag | Description |
|---|---|
--space |
Space key (required) |
--page-id |
Sync single page by ID |
--ancestor |
Sync tree under specific page |
Scope Options
Section titled “Scope Options”# Sync entire spaceatlcli wiki docs init ./docs --space TEAM
# Sync specific page treeatlcli wiki docs init ./docs --ancestor 12345
# Sync single page onlyatlcli wiki docs init ./docs --page-id 12345Watch Mode
Section titled “Watch Mode”The most powerful sync mode - automatically syncs changes in real-time using file watching and remote polling:
atlcli wiki docs sync ./docsHow Watch Mode Works
Section titled “How Watch Mode Works”Watch mode combines two mechanisms for bidirectional sync:
- Local file watching: Detects changes to local markdown files instantly
- Remote polling: Periodically checks Confluence for remote changes
sequenceDiagram participant L as Local Files participant A as atlcli sync participant C as Confluence
Note over L,C: Bidirectional Sync Flow
L->>A: File changed (watched) A->>C: Push to remote C-->>A: OK
loop Every 30s (configurable) A->>C: Poll for changes C-->>A: Changed pages end
A->>L: Pull if changedSync Command Options
Section titled “Sync Command Options”atlcli wiki docs sync <dir> [options]| Flag | Description |
|---|---|
--space <key> |
Sync entire space |
--ancestor <id> |
Sync page tree under parent ID |
--page-id <id> |
Sync single page |
--poll-interval <ms> |
Remote polling interval, 100–86400000 (default: 30000) |
--no-poll |
Disable remote polling (local watch only) |
--no-watch |
Disable file watching (poll only) |
--on-conflict <mode> |
Conflict handling: merge, local, remote |
--auto-create |
Auto-create pages for new local files |
--label <label> |
Only sync pages with this label |
--dry-run |
Report the plan and exit without changing anything |
--json |
JSON line output for scripting |
Run atlcli wiki docs sync --help for the same list from the CLI.
Previewing a Sync
Section titled “Previewing a Sync”atlcli wiki docs sync ./docs --page-id 12345 --dry-run--dry-run reports the plan and exits. It performs no filesystem writes at
all:
- No pages are pulled; no local file is created, moved or overwritten.
- Legacy
<file>.meta.json/<file>.basesidecars are reported asWould migrate:and left on disk — they are neither migrated nor deleted. - No
.atlcli/directory, state store or cache is created, and the target directory itself is not created if it does not exist. - The sync daemon is not started, so no watcher and no poller run.
Polling
Section titled “Polling”The poller periodically checks Confluence for changes. Efficiency depends on sync scope:
| Scope | API Calls | Best For |
|---|---|---|
--page-id |
Minimal (1 page) | Editing single document |
--ancestor |
Moderate (tree) | Working on a section |
--space |
Higher (all pages) | Full documentation sync |
# Poll single page (most efficient)atlcli wiki docs sync ./docs --page-id 12345
# Poll page treeatlcli wiki docs sync ./docs --ancestor 12345
# Poll entire spaceatlcli wiki docs sync ./docs --space TEAMPolling Events
Section titled “Polling Events”The poller detects three types of remote changes:
| Event | Description | Action |
|---|---|---|
created |
New page added in scope | Pull to local |
changed |
Page content or title updated | Pull or merge |
deleted |
Page removed from scope | Notify user |
Configuring Poll Interval
Section titled “Configuring Poll Interval”# Fast polling (every 10 seconds) - more API callsatlcli wiki docs sync ./docs --poll-interval 10000
# Slow polling (every 2 minutes) - fewer API callsatlcli wiki docs sync ./docs --poll-interval 120000
# Disable remote polling entirelyatlcli wiki docs sync ./docs --no-pollNote: Lower intervals mean faster remote change detection but more API requests. The default (30 seconds) balances responsiveness with API usage.
Webhooks
Section titled “Webhooks”For instant remote change detection without polling overhead, use webhooks:
atlcli wiki docs sync ./docs \ --webhook-port 8080 \ --webhook-url https://your-server.com:8080/webhook| Flag | Description |
|---|---|
--webhook-port |
Local webhook server port |
--webhook-url |
Public URL to register with Confluence |
Webhook Events:
The webhook server handles these Confluence events:
| Event | Description |
|---|---|
page_created |
New page created |
page_updated |
Page content changed |
page_removed |
Page deleted |
page_trashed |
Page moved to trash |
page_restored |
Page restored from trash |
page_moved |
Page moved to different parent |
Webhooks vs Polling:
| Feature | Polling | Webhooks |
|---|---|---|
| Latency | 0-30s (configurable) | Instant |
| Setup | None | Requires public URL |
| API usage | Regular requests | On-demand only |
| Reliability | Always works | Requires connectivity |
| Filtering | By scope | By page ID and space |
For local development, use polling. For production servers with public URLs, webhooks provide better performance.
Auto-Create Pages
Section titled “Auto-Create Pages”Create Confluence pages automatically for new local files:
atlcli wiki docs sync ./docs --space TEAM --auto-createAuto-create triggers in two scenarios:
- During initial sync: atlcli creates untracked local files (no frontmatter ID) as new pages
- During file watching: New files added while sync is running are automatically created
How it works:
| Aspect | Behavior |
|---|---|
| Title | From frontmatter title, or filename converted to title case |
| Parent | Space home page (for --space) or ancestor (for --ancestor) |
| Content | Full markdown content converted to Confluence storage format |
Example workflow:
# Start sync with auto-createatlcli wiki docs sync ./docs --space TEAM --auto-create
# In another terminal, create a new fileecho "# My New Feature" > ./docs/my-new-feature.md
# Sync automatically:# 1. Detects new file# 2. Creates page "My New Feature" in Confluence# 3. Updates local file with frontmatter containing page IDAfter auto-create, the file is updated with frontmatter:
---atlcli: id: "12345678" title: "My New Feature"---
# My New FeatureLock File
Section titled “Lock File”When sync runs, atlcli creates a lock file at .atlcli/.sync.lock. This:
- Prevents concurrent sync operations
- Signals to other tools that sync is active
- Is automatically removed on clean shutdown
Download pages from Confluence to local markdown files:
atlcli wiki docs pull ./docsThe path argument is optional and defaults to the current directory. Pass the same path you used for init (or cd into it and omit the path) so files land where the state expects them. --dir <path> does the same thing as the positional argument and is the spelling to use from scripts.
Options:
| Flag | Description |
|---|---|
--dir <path> |
Target directory (same as the positional path; use it when running from elsewhere) |
--out <path> |
Legacy alias for --dir |
--space |
Filter by space key |
--page-id |
Pull specific page |
--ancestor |
Pull page tree |
--label |
Filter by label |
--force |
Overwrite local modifications - markdown and attachments |
--comments |
Export comments to sidecar files |
--no-attachments |
Skip downloading attachments |
--limit <n> |
Maximum pages to pull |
Local modifications are never overwritten silently
Section titled “Local modifications are never overwritten silently”Pull compares each file it is about to write against the hash recorded at the last sync. Anything you changed locally is left alone and reported:
Skipping architecture.md (local modifications, use --force)Skipping architecture.attachments/diagram.png (local modifications, use --force)This applies to markdown files and to attachments alike. Skipped attachments are
counted as attachmentsSkipped in --json output. Use --force to discard the
local version and take the remote one.
Examples
Section titled “Examples”# Pull using saved scope from initatlcli wiki docs pull ./docs
# Pull into ./docs from an unrelated working directoryatlcli wiki docs pull --dir ./docs
# Pull pages with specific labelatlcli wiki docs pull ./docs --label api-docs
# Pull with comments exportedatlcli wiki docs pull ./docs --comments
# Force pull (overwrite local changes, attachments included)atlcli wiki docs pull ./docs --force
# Pull without attachmentsatlcli wiki docs pull ./docs --no-attachmentsComments Export
Section titled “Comments Export”When using --comments, page comments are saved to sidecar files:
docs/├── architecture.md├── architecture.comments.json # Comments for architecture.md└── api-reference.mdThe comments file contains both footer comments and inline comments with their full thread hierarchy.
Upload local changes to Confluence:
atlcli wiki docs push ./docsThe path argument is optional. When omitted, push walks up from the current directory to find the nearest .atlcli/ — so from inside your synced tree atlcli wiki docs push and atlcli wiki docs push --page-id 12345 both work without any path.
Options:
| Flag | Description |
|---|---|
--dir <path> |
Target directory (same as the positional path) |
--page-id <id> |
Push specific page by ID |
--validate |
Validate the files being pushed before pushing |
--strict |
Treat warnings as errors |
--json |
JSON output |
Examples
Section titled “Examples”# Push all tracked filesatlcli wiki docs push ./docs
# Push single fileatlcli wiki docs push ./docs/page.md
# Push by page ID (from anywhere inside the synced tree)atlcli wiki docs push --page-id 12345
# Validate before pushingatlcli wiki docs push ./docs --validate
# Strict validation (fail on warnings)atlcli wiki docs push ./docs --validate --strictValidation
Section titled “Validation”Pre-push validation checks for:
| Check | Severity | Description |
|---|---|---|
| Broken links | Error | Target file not found |
| Untracked pages | Warning | Link to page without ID |
| Unclosed macros | Error | :::info without closing ::: |
| Page size | Warning | Content exceeds 500KB |
--validate checks exactly what the push will send: the single file for
push <file> or push --page-id <id>, and the collected (ignore-filtered) set
for a directory push. Errors in files you are not pushing do not block the push,
and --validate works outside an initialized tree too - it validates the named
file rather than doing nothing.
# Run validation separatelyatlcli wiki docs check ./docs
# From an unrelated working directoryatlcli wiki docs check --dir ./docs
# Strict mode (warnings are errors)atlcli wiki docs check ./docs --strict
# JSON output for CI/scriptsatlcli wiki docs check ./docs --jsonAdd a new local file to Confluence tracking:
atlcli wiki docs add <file> [options]| Flag | Description |
|---|---|
--title <t> |
Page title (default: from H1 or filename) |
--parent <id> |
Parent page ID |
--template <name> |
Use template for initial content |
# Add file with auto-detected titleatlcli wiki docs add ./docs/new-page.md
# Add with specific parentatlcli wiki docs add ./docs/guide.md --parent 12345
# Add using a templateatlcli wiki docs add ./docs/meeting.md --template meeting-notesCompare local file with remote Confluence page:
atlcli wiki docs diff <file>Shows unified diff with colored output:
- Green: additions (local has, remote doesn’t)
- Red: deletions (remote has, local doesn’t)
- Cyan: file headers and hunk markers
# Compare single fileatlcli wiki docs diff ./docs/api-reference.md
# JSON output with statisticsatlcli wiki docs diff ./docs/api-reference.md --jsonConflict Resolution
Section titled “Conflict Resolution”Detection
Section titled “Detection”atlcli detects conflicts when:
- Local file was modified since last sync
- Remote page was modified since last sync
Conflict detected: docs/api.md Local: Modified 2025-01-14 10:30 (version 5 → local changes) Remote: Modified 2025-01-14 10:35 (version 5 → version 6)Resolution Strategies
Section titled “Resolution Strategies”Control how conflicts are handled in sync mode:
atlcli wiki docs sync ./docs --on-conflict <strategy>| Strategy | Behavior when the three-way merge fails |
|---|---|
merge |
Write conflict markers into the local file and stop (default) |
local |
Local wins: push the local file over the remote page in one update |
remote |
Remote wins: overwrite the conflicted local file in place; the local edit is discarded and never pushed |
All three emit a conflict event first, so --json consumers see which
strategy was applied:
{"schemaVersion":"1","type":"conflict","message":"Conflict (1 regions), keeping remote (--on-conflict remote): ./docs/api.md","file":"./docs/api.md","pageId":"12345","details":{"conflictCount":1,"resolution":"remote"}}Three-Way Merge
Section titled “Three-Way Merge”With --on-conflict merge, atlcli attempts automatic merging:
- Uses the common ancestor (base) version
- Computes diffs from both local and remote
- Merges non-conflicting changes
- Marks conflicting sections with markers
Conflict Markers
Section titled “Conflict Markers”When merge cannot auto-resolve, conflict markers are inserted:
## API Reference
<<<<<<< LOCALThis endpoint returns user data in JSON format.=======This endpoint returns user data. Response format is JSON.>>>>>>> REMOTE
### AuthenticationResolving Conflicts
Section titled “Resolving Conflicts”# Edit file to resolve conflicts manuallyvim docs/api.md
# Then resolve with chosen strategyatlcli wiki docs resolve docs/api.md --accept localatlcli wiki docs resolve docs/api.md --accept remoteatlcli wiki docs resolve docs/api.md --accept merged # After manual editStatus
Section titled “Status”Check sync status of all tracked files:
atlcli wiki docs status ./docsOutput:
Sync status for ./docs:
synced: 12 files local-modified: 2 files remote-modified: 1 files conflict: 1 files untracked: 3 files folders: 2
Attachments: synced: 8 local-modified: 1 conflict: 0 missing: 0
Last sync: 2025-01-14T10:30:00Z
Modified: api-reference.md (local changes) getting-started.md (remote changes) architecture.attachments/diagram.png (attachment local changes)
Conflicts: troubleshooting.mdThe file counters cover markdown only. Attachments are counted separately (they
have their own base hashes) and appear in --json output under
attachmentStats; individual files show up in modified with the type
attachment local changes, or attachment deleted locally when the file is
gone.
Options:
| Flag | Description |
|---|---|
--dir <path> |
Target directory (same as the positional path) |
--links |
Analyze link changes vs stored links |
--json |
JSON output |
Ignore Patterns
Section titled “Ignore Patterns”Create .atlcliignore to exclude files from sync:
# .atlcliignore (gitignore syntax)
# Ignore draftsdrafts/*.draft.md
# Ignore specific filesinternal-notes.md
# Ignore by patterntemp-*.md
# Negation (include despite earlier rule)!important-draft.mdDefault ignores (always excluded):
.atlcli/- sync state directory*.meta.json- legacy metadata files*.base- base versions for merge.git/- git directorynode_modules/- node dependencies
Note: Patterns from .gitignore are also respected and merged with .atlcliignore.
Directory Structure
Section titled “Directory Structure”After init and pull:
docs/├── .atlcli/│ ├── config.json # Sync configuration│ ├── state.json # Sync state (versions, timestamps)│ ├── .sync.lock # Lock file (when sync running)│ └── cache/ # Base versions for 3-way merge│ └── 12345.md # Base content by page ID├── getting-started.md├── api-reference.md├── api-reference.attachments/│ └── diagram.png # Attachments for api-reference.md├── guides/│ ├── installation.md│ └── configuration.md├── .atlcliignore # Ignore patterns└── .gitignore # Git ignore (also respected)State File
Section titled “State File”.atlcli/state.json tracks sync state per page:
{ "lastSync": "2025-01-14T10:00:00Z", "pages": { "12345": { "path": "api-reference.md", "title": "API Reference", "version": 5, "localHash": "abc123", "remoteHash": "abc123", "baseHash": "abc123", "syncState": "synced", "parentId": "12340", "ancestors": ["12340", "12300"] } }}File Format
Section titled “File Format”Local files use YAML frontmatter with the atlcli namespace:
---atlcli: id: "12345" title: "API Reference"---
# API Reference
Content here...The frontmatter fields:
| Field | Required | Description |
|---|---|---|
id |
Yes | Confluence page ID (set automatically on pull/create) |
title |
No | Page title override (defaults to first H1 heading) |
See File Format for details.
Hierarchy Handling
Section titled “Hierarchy Handling”atlcli maps Confluence page hierarchy to directory structure:
Confluence: Local:├── Parent Page ├── parent-page.md│ ├── Child A ├── parent-page/│ │ └── Grandchild │ ├── child-a.md│ └── Child B │ ├── child-a/ │ │ └── grandchild.md │ └── child-b.mdWhen pages move in Confluence, sync detects this and moves local files to match.
Folders
Section titled “Folders”atlcli supports Confluence Cloud folders (introduced September 2024):
Confluence: Local:├── My Folder (folder) ├── my-folder/│ ├── Page A │ ├── index.md (type: folder)│ └── Page B │ ├── page-a.md │ └── page-b.mdatlcli represents folders as directories with an index.md file containing type: folder in frontmatter. See Folders for full details on folder support and limitations.
JSON Output
Section titled “JSON Output”Most commands support --json for scripting. Apart from the two streaming
commands noted below, --json writes exactly one JSON document to stdout —
JSON.parse(stdout) is always safe. Progress notes, skip messages and warnings
are suppressed in this mode; the counters in the result document report the same
information (a skipped file shows up in results.skipped, not as a log line).
atlcli wiki docs status ./docs --json{ "schemaVersion": "1", "dir": "./docs", "stats": { "synced": 12, "localModified": 2, "remoteModified": 1, "conflict": 1, "untracked": 3 }, "lastSync": "2025-01-14T10:00:00Z"}Streaming commands
Section titled “Streaming commands”sync and watch are the exception: they run until done (or until you stop
them) and emit JSON Lines — one complete document per line. Parse these line
by line, not as a whole.
atlcli wiki docs sync ./docs --json{"schemaVersion":"1","type":"status","message":"Starting initial sync..."}{"schemaVersion":"1","type":"pull","file":"api-reference.md","pageId":"12345","message":"Pulled: API Reference"}{"schemaVersion":"1","type":"push","file":"guide.md","pageId":"12346","message":"Pushed: Guide"}Failures
Section titled “Failures”A command that exits non-zero reports the reason in an error object. For
docs check this is folded into the report document so there is still only one
document to parse — see Validation.
Best Practices
Section titled “Best Practices”- Use watch mode for real-time collaboration on documentation
- Use labels to sync subsets of pages (
--label architecture) - Enable webhooks for production servers with public URLs
- Commit to Git - track markdown files in Git for version history
- Use
.atlcliignorefor drafts and local-only content - Run validation before pushing (
--validate)
Troubleshooting
Section titled “Troubleshooting”Lock File Issues
Section titled “Lock File Issues”If sync fails due to lock:
# Check if sync is runningps aux | grep "atlcli wiki docs sync"
# Force remove stale lock (only if no sync is active)rm ./docs/.atlcli/.sync.lockMerge Conflicts
Section titled “Merge Conflicts”If you get stuck in merge conflicts:
# Reset to remote versionatlcli wiki docs pull ./docs --force
# Or force push local versionatlcli wiki docs resolve ./docs/file.md --accept localatlcli wiki docs push ./docsPermission Errors
Section titled “Permission Errors”Error: You don't have permission to edit page 12345Check your Confluence permissions for the space/page.
Rate Limiting
Section titled “Rate Limiting”If you see 429 errors, increase poll interval:
atlcli wiki docs sync ./docs --poll-interval 60000Related Topics
Section titled “Related Topics”- File Format - Frontmatter structure and directory conventions
- Ignore Patterns - Exclude files from sync with
.atlcliignore - Validation - Pre-push validation rules
- Attachments - Sync images and file attachments
- Webhooks - Real-time sync without polling
- Pages - Direct page operations (create, move, delete)