agentleFS
sagy101sagy101/DotSkills/confluence-publisher/SKILL.md

confluence-publisher

Skill4 starsChanged 8 months agoMITView on GitHub

Publish, sync, diff, delete, discover, and export markdown documentation to/from Confluence Cloud (*.atlassian.net/wiki/*). Use when the user asks to publish, update, delete, preview, diff, or export markdown files to Confluence, or when they want to verify existing Confluence pages against local docs. Also supports surgical HTML edits (targeted find/replace without overwriting manual formatting), version comparison (diff two page versions), version history browsing, page revert, CQL search, page comments (list/add/reply/edit/delete/resolve/unresolve plus likes reads and threaded child traversal), page listing by space, and space listing. Handles page creation, updates, deletion, cross-page link rewriting, Mermaid diagram rendering, hierarchy verification, diff/preview, and reverse export to markdown.

  • Reads credentials
  • Installs packages

The file

Show its rules and text

We split this skill into the rules it gives an agent

27 rules. About 0 are common, 22 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈22

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use this skill when the user wants to:

    line 29
  2. Distinctive:

    Update existing Confluence pages from local markdown

    line 31
  3. Distinctive:

    Delete Confluence pages (by manifest file key or page ID)

    line 32
  4. Distinctive:

    Verify that Confluence pages match local docs (hierarchy, titles, content)

    line 33
  5. Distinctive:

    Before running any publish operation, ensure:

    line 45
  6. Very specific:

    If no config is found anywhere, help the user create one.

    line 53
  7. Very specific:

    If .confluence.json does not exist anywhere, help the user create one by asking for:

    line 70
  8. Distinctive:

    Run the preflight script before any other operation:

    line 97
  9. Distinctive:

    If the venv or dependencies are missing, the preflight tells you to run the setup script:

    line 110
  10. Distinctive:

    After setup, all subsequent script commands must use the venv Python:

    line 122
  11. Distinctive:

    If no config is found anywhere, do NOT proceed — instead help the user create one.

    line 128
  12. Distinctive:

    Always follow this sequence.

    line 132
  13. Distinctive:

    Run the pre-flight checks above.

    line 136
  14. Distinctive:

    Ask the user (or infer from their request) which files to publish:

    line 140
  15. Very specific:

    All: every .md file under docs_dir

    line 141
  16. Distinctive:

    Wait for explicit user approval before proceeding: If the user asks to change titles, parent pages, or skip files, update the plan and …

    line 169
  17. Distinctive:

    Run the publish script for each file in hierarchical order (parents before children):

    line 173
  18. Very specific:

    Use --dry-run to preview what would be published without making any changes:

    line 193
  19. Distinctive:

    After publishing, offer to run verification:

    line 209
  20. Distinctive:

    If the user already has pages on Confluence and wants to build a manifest from them:

    line 223
  21. Distinctive:

    When exporting the full tree, the script also updates the manifest with discovered pages.

    line 289
  22. Distinctive:

    Remove Confluence pages and their manifest entries.

    line 333
  23. Distinctive:

    Never run delete without explicit user approval: Before executing, list every page that will be deleted (title and ID) and wait for the …

    line 350
  24. Distinctive:

    Never print or log credentials: Only confirm that the environment variables are set.

    line 367
  25. Distinctive:

    If a page create fails, stop and report the error — do not continue with children of that page.

    line 370
  26. Very specific:

    When using surgical edit, prefer --check-sections to verify critical content survived the edit.

    line 374
  27. Distinctive:

    Search Confluence content using CQL (Confluence Query Language):

    line 430

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Confluence Publisher

Publish a tree of markdown files to Confluence Cloud, maintaining hierarchy, cross-page links, and embedded diagrams.

When to use this skill

Use this skill when the user wants to:

  • Publish one or more markdown files to Confluence
  • Update existing Confluence pages from local markdown
  • Delete Confluence pages (by manifest file key or page ID)
  • Verify that Confluence pages match local docs (hierarchy, titles, content)
  • Discover existing Confluence pages and build a local manifest
  • Validate that a manifest is consistent with both disk and Confluence
  • Apply targeted edits to a Confluence page without overwriting manual formatting (surgical edit)
  • Compare two versions of a Confluence page (version diff)
  • Browse page version history or fetch content from a specific version
  • Revert a page to a previous version
  • Manage Confluence page comments and read like counts/users for pages and comments
  • List pages in a space with title/status/type filters

Prerequisites

Before running any publish operation, ensure:

  1. Config: .confluence.json in project root and/or ~/.confluence.json for global defaults (see CONFIG.md)
  2. Credentials: CONFLUENCE_EMAIL and CONFLUENCE_TOKEN exported in shell profile (recommended) or in a .env file
  3. Python deps: installed via confluence_setup_env.py (shared venv in skill dir)

Config is auto-discovered — scripts search CWD upward, then ~/.confluence.json. If both exist, they are deep-merged (project-level wins). No --config flag needed.

If no config is found anywhere, help the user create one. For users with one Atlassian instance, a global ~/.confluence.json covers the shared settings:

{
  "confluence_url": "https://mycompany.atlassian.net/wiki",
  "credentials": { "username_env": "CONFLUENCE_EMAIL", "token_env": "CONFLUENCE_TOKEN" }
}

Then a minimal per-project .confluence.json only needs:

{
  "space_key": "DOCS",
  "root_page_id": "123456"
}

If .confluence.json does not exist anywhere, help the user create one by asking for:

  • Confluence base URL (e.g. https://mycompany.atlassian.net/wiki)
  • Space key
  • Root page ID (the parent page under which all docs live)
  • Which directory contains the markdown files (default: project root)

Configuration

Config is loaded from .confluence.json (project root) and/or ~/.confluence.json (global). If both exist, they are deep-merged (project-level wins). See references/CONFIG.md for the full schema.

Full single-file example:

{
  "confluence_url": "https://mycompany.atlassian.net/wiki",
  "space_key": "DOCS",
  "root_page_id": "123456",
  "docs_dir": ".",
  "credentials": {
    "username_env": "CONFLUENCE_EMAIL",
    "token_env": "CONFLUENCE_TOKEN"
  }
}

Pre-flight checks

Run the preflight script before any other operation:

python3 <skill_dir>/scripts/confluence_preflight.py

It validates the entire environment in a single pass:

  1. Python 3.10+ is available
  2. Virtual environment exists and dependencies are installed (atlassian-python-api, markdown)
  3. Config file (.confluence.json) is found and has required fields (confluence_url, space_key, root_page_id)
  4. Credentials — env vars are set (never prints values)
  5. Connectivity — API is reachable, space and root page exist

If the venv or dependencies are missing, the preflight tells you to run the setup script:

python3 <skill_dir>/scripts/confluence_setup_env.py

To skip the connectivity check (e.g. on repeated calls):

python3 <skill_dir>/scripts/confluence_preflight.py --skip-connectivity

After setup, all subsequent script commands must use the venv Python:

<skill_dir>/.venv/bin/python <skill_dir>/scripts/publish_page.py ...

If no config is found anywhere, do NOT proceed — instead help the user create one. For users with one Atlassian instance, suggest a global ~/.confluence.json with shared settings (URL, credentials) and a per-project .confluence.json with just space_key and root_page_id.

Workflow

Always follow this sequence. Never skip the pre-flight checks or the publish plan step.

Step 1 — Validate configuration

Run the pre-flight checks above. If any check fails, resolve it before proceeding.

Step 2 — Determine scope

Ask the user (or infer from their request) which files to publish:

  • All: every .md file under docs_dir
  • Changed: files modified since last publish (check git diff or timestamps)
  • Specific: a list of files the user names

Step 3 — Build the publish plan

For each file in scope, determine whether it is a create or update by checking the manifest (.confluence-manifest.json). If no manifest exists, treat all files as creates.

Present the plan to the user in this exact format (see references/PUBLISH_PLAN_FORMAT.md):

╔══════════════════════════════════════════════════════════════╗
║                   CONFLUENCE PUBLISH PLAN                    ║
╠══════════════════════════════════════════════════════════════╣
║ Target: https://mycompany.atlassian.net/wiki                 ║
║ Space:  DOCS                                                 ║
║ Root:   "My Project Docs" (id=123456)                        ║
╠══════════════════════════════════════════════════════════════╣
║ #  │ Action │ File                    │ Title                 ║
║────┼────────┼─────────────────────────┼───────────────────────║
║  1 │ UPDATE │ README.md               │ My Project Docs       ║
║  2 │ CREATE │ plan/README.md          │ Design & Plan         ║
║  3 │ UPDATE │ plan/architecture.md    │ Architecture          ║
╠══════════════════════════════════════════════════════════════╣
║ Creates: 1  │  Updates: 2  │  Skipped: 0  │  Total: 3        ║
╚══════════════════════════════════════════════════════════════╝

Wait for explicit user approval before proceeding. If the user asks to change titles, parent pages, or skip files, update the plan and present it again.

Step 4 — Execute

Run the publish script for each file in hierarchical order (parents before children):

<skill_dir>/.venv/bin/python <skill_dir>/scripts/publish_page.py \
  --file <relative_path> \
  --title "<title>" \
  --mode <create|update> \
  [--page-id <id>]        # for updates, from manifest \
  [--parent-id <id>]      # for creates, from manifest or root_page_id \
  [--emoji <codepoint>]   # page icon emoji, e.g. 1f399 for 🎙️

The script automatically:

  • Converts markdown to Confluence storage format
  • Renders Mermaid diagrams to PNG and uploads as attachments
  • Rewrites .md cross-links to Confluence page-link macros using the manifest
  • Converts attachment: links to Confluence attachment macros
  • Sets the page emoji icon (if --emoji is provided)
  • Updates the manifest with the resulting page ID

Use --dry-run to preview what would be published without making any changes:

<skill_dir>/.venv/bin/python <skill_dir>/scripts/publish_page.py \
  --file <relative_path> \
  --title "<title>" \
  --mode <create|update> \
  [--page-id <id>] \
  [--parent-id <id>] \
  --dry-run

Dry run still renders markdown transformations (mermaid counts, link rewrites, body size) but does not create/update pages, upload attachments, set emoji, or update the manifest.

Step 5 — Verify (optional but recommended)

After publishing, offer to run verification:

# Validate manifest entries against disk and Confluence
<skill_dir>/.venv/bin/python <skill_dir>/scripts/validate_manifest.py

# Show the full page tree on Confluence
<skill_dir>/.venv/bin/python <skill_dir>/scripts/verify_hierarchy.py

Other operations

Discover existing pages

If the user already has pages on Confluence and wants to build a manifest from them:

<skill_dir>/.venv/bin/python <skill_dir>/scripts/discover_pages.py

This walks the Confluence tree under root_page_id and creates .confluence-manifest.json.

Diff / Preview

Compare local markdown against what is currently on Confluence without publishing.

The diff normalizes both sides to the same representation before comparing:

  1. Local markdown is transformed through the publish pipeline (mermaid blocks → placeholders, .md links → Confluence link macros) to produce Confluence storage HTML
  2. Remote Confluence page storage HTML is fetched and mermaid image macros are replaced with matching placeholders
  3. Both HTML strings are converted to markdown via markdownify
  4. A unified diff is produced from the two normalized markdown strings

This eliminates false positives from mermaid diagrams and cross-page links. Minor whitespace differences may still appear due to round-trip formatting.

# Diff a single file
<skill_dir>/.venv/bin/python <skill_dir>/scripts/diff_pages.py --file README.md

# Diff all manifest entries
<skill_dir>/.venv/bin/python <skill_dir>/scripts/diff_pages.py --all

# Summary only (changed/unchanged counts, no full diff)
<skill_dir>/.venv/bin/python <skill_dir>/scripts/diff_pages.py --all --summary

# Save diff output to file (avoids terminal truncation for large pages)
<skill_dir>/.venv/bin/python <skill_dir>/scripts/diff_pages.py --file README.md --output /tmp/diff-report.txt

Note: The diff script exits with code 1 if any changes or new pages are detected, and code 0 if everything is unchanged. This is informational (like the diff command), not an error — do not treat exit code 1 as a failure.

Output truncation: For large pages, the diff output may exceed the terminal/tool output limit and get truncated. Use --output /tmp/diff-report.txt to save to a file, then read it with your file-reading tool.

Present the diff output to the user before publishing so they can review what would change.

Export from Confluence

Pull Confluence pages back into local markdown files (reverse sync). Useful for bootstrapping local docs from an existing Confluence space, or for recovering content.

# Export a single page by ID, URL, or tiny link
<skill_dir>/.venv/bin/python <skill_dir>/scripts/export_pages.py \
    --page https://mycompany.atlassian.net/wiki/spaces/DOCS/pages/123456/My+Page

# Export using a Confluence tiny link (/wiki/x/...)
<skill_dir>/.venv/bin/python <skill_dir>/scripts/export_pages.py \
    --page https://mycompany.atlassian.net/wiki/x/sYjwQ

# Export a single page to a specific file
<skill_dir>/.venv/bin/python <skill_dir>/scripts/export_pages.py --page 123456 -o docs/setup.md

# Export all manifest entries (overwrites local files)
<skill_dir>/.venv/bin/python <skill_dir>/scripts/export_pages.py --manifest

# Export full tree under root_page_id (discovers and exports everything)
<skill_dir>/.venv/bin/python <skill_dir>/scripts/export_pages.py --tree

# Dry run — show what would be exported without writing files
<skill_dir>/.venv/bin/python <skill_dir>/scripts/export_pages.py --tree --dry-run

When exporting the full tree, the script also updates the manifest with discovered pages.

Always confirm with the user before running --manifest or --tree exports, as they overwrite local files.

Attachments

The publish script supports uploading file attachments alongside a page:

<skill_dir>/.venv/bin/python <skill_dir>/scripts/publish_page.py \
    --file docs/setup.md --title "Setup Guide" --mode update --page-id 123456 \
    --attachments "docs/images/diagram.png,docs/files/schema.pdf"

To upload attachments without modifying page content, use --attachments-only:

# Upload files to a page without touching its content
<skill_dir>/.venv/bin/python <skill_dir>/scripts/publish_page.py \
    --attachments-only --page-id 123456 \
    --attachments "images/diagram.png,images/chart.png"

Never use --file /dev/null to upload attachments — it will wipe the page content. Always use --attachments-only instead.

Attachment paths are relative to docs_dir. Multiple files are comma-separated. If an attachment file is not found, a warning is printed but the page publish still succeeds.

Mermaid diagram PNGs are uploaded automatically — no need to list them in --attachments.

Attachment links in markdown

To link to an uploaded attachment from within the page content, use the attachment: URL scheme:

[My Presentation.pdf](attachment:My Presentation.pdf)
[Architecture Diagram](attachment:arch-overview.png)

During publish, these are automatically converted to Confluence <ac:link><ri:attachment …/></ac:link> macros that link directly to the attachment on the page.

The filename in attachment: must exactly match the filename used in --attachments (or the name of a previously uploaded attachment on the page).

Delete pages

Remove Confluence pages and their manifest entries. Supports deletion by manifest file key or direct page ID.

# Delete by manifest file path
<skill_dir>/.venv/bin/python <skill_dir>/scripts/delete_page.py --file plan/old-design.md

# Delete multiple files
<skill_dir>/.venv/bin/python <skill_dir>/scripts/delete_page.py \
    --file "plan/old-design.md,plan/deprecated.md"

# Delete by page ID (not in manifest)
<skill_dir>/.venv/bin/python <skill_dir>/scripts/delete_page.py --page-id 123456

# Dry run — show what would be deleted without deleting
<skill_dir>/.venv/bin/python <skill_dir>/scripts/delete_page.py --file plan/old-design.md --dry-run

Never run delete without explicit user approval. Before executing, list every page that will be deleted (title and ID) and wait for the user to confirm. Deletion is irreversible unless the page is recovered from Confluence trash. When in doubt, use --dry-run first.

Validate only

<skill_dir>/.venv/bin/python <skill_dir>/scripts/validate_manifest.py

Verify hierarchy only

<skill_dir>/.venv/bin/python <skill_dir>/scripts/verify_hierarchy.py

Important rules

  1. Never publish or delete without showing the plan first and getting explicit user approval. Deletion is destructive and irreversible (except via Confluence trash recovery). When in doubt, use --dry-run on publish_page.py to preview changes before committing.
  2. Never print or log credentials. Only confirm that the environment variables are set.
  3. Publish parents before children so that parent IDs are available for child creation.
  4. The manifest file (.confluence-manifest.json) is auto-maintained by scripts. Do not edit it manually.
  5. If a page create fails, stop and report the error — do not continue with children of that page.
  6. Cross-page links are best-effort: if a target page is not in the manifest, the link is left as-is.
  7. Always use --dry-run before surgical edits. Review the semantic diff and section integrity check before pushing.
  8. Never revert a page without showing the dry-run plan first and getting explicit user approval. Revert creates a new version — the old version remains in history.
  9. When using surgical edit, prefer --check-sections to verify critical content survived the edit.
  10. Never use grep or cat on fetched Confluence HTML files — they are single-line files that will truncate in the terminal and produce unreadable output. Instead, save to a file with --output and read it using your IDE's file-reading tool, or write a small Python script to extract the specific section you need (e.g., find a table between two headings).

Markdown transformation details

The publish script performs these transformations automatically:

  • Markdown → Confluence storage format: Headings, tables, lists, inline code, bold/italic all convert to Confluence XHTML
  • Code blocks → Confluence code macros: Fenced code blocks with language tags become <ac:structured-macro ac:name="code"> with proper language highlighting
  • Mermaid diagrams → PNG attachments: ```mermaid blocks are rendered to PNG via mmdc (Mermaid CLI), uploaded as page attachments, and replaced with <ac:image> macros. If Node.js/npx is unavailable, diagrams fall back to plain code blocks (no failure)
  • Cross-page links → Confluence page links: Links like [Setup Guide](./setup.md) are resolved via the manifest and rewritten to <ac:link> macros pointing to the correct Confluence page by title. Unresolvable links (target not in manifest) are left as-is
  • Attachment links → Confluence attachment macros: Links using the attachment: scheme (e.g. [Slides](attachment:slides.pdf)) are converted to <ac:link><ri:attachment …/></ac:link> macros

Surgical edit

Apply targeted find/replace edits to a page's storage HTML without overwriting the entire page. Also supports structural element replacement (tables, sections, lists), markdown-to-HTML section replacement, and appending new sections.

# Simple find/replace (always dry-run first)
<skill_dir>/.venv/bin/python <skill_dir>/scripts/surgical_edit.py \
    --page 1079706804 --find "old text" --replace "new text" --dry-run

# Replace a section from markdown
<skill_dir>/.venv/bin/python <skill_dir>/scripts/replace_element.py \
    --page 1079706804 --heading "Testing" --element section \
    --new-md /tmp/new-section.md --dry-run

# Render existing mermaid code blocks to images
<skill_dir>/.venv/bin/python <skill_dir>/scripts/render_mermaid.py \
    --page 1079706804 --dry-run

Always use --dry-run first. Full usage details: references/SURGICAL_EDIT.md

Version management

Browse version history, diff two versions, fetch content at any version, or revert to a previous version.

# Diff version 56 against latest
<skill_dir>/.venv/bin/python <skill_dir>/scripts/diff_versions.py \
    --page 1079706804 --from-version 56

# List version history
<skill_dir>/.venv/bin/python <skill_dir>/scripts/page_versions.py \
    --page 1079706804 --list

# Revert (dry run first, then --confirm)
<skill_dir>/.venv/bin/python <skill_dir>/scripts/page_versions.py \
    --page 1079706804 --revert 56

Never revert without showing the dry-run plan first. Full usage details: references/VERSION_MANAGEMENT.md

Search (CQL)

Search Confluence content using CQL (Confluence Query Language):

# Search pages by title
<skill_dir>/.venv/bin/python <skill_dir>/scripts/search_pages.py \
    --cql 'type=page AND space=DOCS AND title~"API"'

# Search with limit and JSON output
<skill_dir>/.venv/bin/python <skill_dir>/scripts/search_pages.py \
    --cql 'type=page AND text~"deployment"' --limit 50 --format json

CQL is Atlassian's query language for Confluence. Common operators: =, ~ (contains), AND, OR, NOT. Useful fields: type, space, title, text, creator, lastModified, label, ancestor.

Comments

List and add comments on Confluence pages:

# List footer comments
<skill_dir>/.venv/bin/python <skill_dir>/scripts/page_comments.py list \
    --page-id 123456

# List inline comments
<skill_dir>/.venv/bin/python <skill_dir>/scripts/page_comments.py list \
    --page-id 123456 --inline

# List as JSON
<skill_dir>/.venv/bin/python <skill_dir>/scripts/page_comments.py list \
    --page-id 123456 --format json

# Add a footer comment (body is Confluence storage HTML)
<skill_dir>/.venv/bin/python <skill_dir>/scripts/page_comments.py add \
    --page-id 123456 --body "<p>This looks good. Ship it.</p>"

List spaces

Browse available Confluence spaces:

# List all spaces
<skill_dir>/.venv/bin/python <skill_dir>/scripts/list_spaces.py

# Filter by type
<skill_dir>/.venv/bin/python <skill_dir>/scripts/list_spaces.py --type global

# JSON output
<skill_dir>/.venv/bin/python <skill_dir>/scripts/list_spaces.py --format json

Future capabilities

These operations can be added to this skill in the future:

CapabilityDescription
Bulk renameRename Confluence pages when local titles change
Labels/tagsAuto-apply Confluence labels based on directory structure or markdown frontmatter
Page permissionsSet view/edit restrictions on published pages
Content appearanceSet page width (full-width vs default) via content properties

Troubleshooting

ProblemCauseFix
python3: command not foundPython not installedmacOS: brew install python3 / Linux: apt install python3
ModuleNotFoundError: atlassianDependencies not installedRun python3 <skill_dir>/scripts/confluence_setup_env.py
401 UnauthorizedBad credentialsVerify env vars are set and token has page write access
404 Page not foundWrong page ID in manifestRun discover_pages.py to rebuild manifest
Title conflictPage title already exists in spaceUse a unique title or update the existing page
Mermaid diagrams not renderingNode.js/npx not installedInstall Node.js or diagrams will fall back to code blocks

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.