COG-second-brain publish-to-confluence
Publish any markdown file from the vault to Confluence with format conversion and approval gate
git clone https://github.com/huytieu/COG-second-brain
T=$(mktemp -d) && git clone --depth=1 https://github.com/huytieu/COG-second-brain "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/publish-to-confluence" ~/.claude/skills/huytieu-cog-second-brain-publish-to-confluence && rm -rf "$T"
.claude/skills/publish-to-confluence/SKILL.mdCOG Publish to Confluence Skill
When to Invoke
- User wants to publish a document to Confluence
- User says "publish to Confluence", "push to wiki", "send to Confluence", "confluence publish"
- User has a markdown file they want to share with the team on Confluence
- After generating a PRD, release notes, or other document that should go to the wiki
Agent Mode Awareness
Check
in agent_mode
frontmatter:00-inbox/MY-PROFILE.md
- If
— no significant benefit for this skill (single sequential operation)agent_mode: team - If
— standard executionagent_mode: solo
Command: /publish-to-confluence
/publish-to-confluencePre-Flight Check
-
Read
— Confluence MUST be listed under Active Integrations00-inbox/MY-INTEGRATIONS.md- If Confluence is not active: Inform the user and stop.
Confluence is not in your active integrations. Would you like to: a) Set up Confluence integration (I'll add it to MY-INTEGRATIONS.md) b) Export the document in a Confluence-compatible format for manual upload - If Confluence is disabled: Skip silently per COG conventions. Suggest alternative publishing (HackMD, Notion) if active.
- If Confluence is not active: Inform the user and stop.
-
Get current timestamp: Run
using Bashdate '+%Y-%m-%d %H:%M'
Execution Strategy
Phase 1: Identify the Source Document
Determine what to publish:
Option A: User specifies a file path
Read the specified file from the vault.
Option B: User describes the document
Search for matching files: 1. Glob for likely matches in 04-projects/, 05-knowledge/, 01-daily/ 2. Present candidates and let user choose
Option C: Just-generated document If this skill is invoked right after generating a PRD, release notes, or other document, use that document.
Phase 2: Configure Publishing Target
Ask the user (if not already provided):
Where should this be published in Confluence? Required: - Space key: [CUSTOMIZE: YOUR-SPACE-KEY] (or let me search for spaces) - Parent page: [Page title or ID under which to nest this page] Optional: - Page title: [defaults to the document's H1 heading] - Labels: [Confluence labels to add] - Publish mode: "create new" or "update existing"
If the user doesn't know the space or parent page:
Use WebFetch to search Confluence: GET /wiki/rest/api/space?limit=50 - List available spaces for the user to choose GET /wiki/rest/api/content?spaceKey=[SPACE]&type=page&limit=25 - List pages in the space for parent page selection
Phase 3: Convert Markdown to Confluence Format
Convert the markdown document to Confluence storage format (XHTML):
Conversion rules:
| Markdown | Confluence Storage Format |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
| Code blocks | |
| Tables | |
| |
| |
| |
| Same with status |
| YAML frontmatter | Strip entirely (not displayed in Confluence) |
Important conversion notes:
- Strip YAML frontmatter — it should not appear in the Confluence page
- Preserve table structure carefully
- Convert relative vault links to plain text (they won't work in Confluence)
- Handle nested lists properly
- Preserve emoji characters as-is
Phase 4: Preview and Approval Gate
CRITICAL: NEVER publish without explicit user approval.
Present a summary to the user:
Ready to publish to Confluence: Document: [filename] Title: [page title] Space: [space key] Parent Page: [parent page title] Mode: [create new / update existing] Labels: [labels] Content preview (first 500 chars): [preview text] Estimated page size: [approximate word count] Proceed with publishing? (yes/no)
Wait for explicit "yes" before proceeding.
Phase 5: Publish
Create New Page
Use WebFetch to POST to Confluence REST API: POST [CUSTOMIZE: your-confluence-url]/wiki/rest/api/content Headers: Content-Type: application/json Authorization: [from configured credentials] Body: { "type": "page", "title": "[page title]", "space": { "key": "[SPACE_KEY]" }, "ancestors": [{ "id": "[PARENT_PAGE_ID]" }], "body": { "storage": { "value": "[converted XHTML content]", "representation": "storage" } }, "metadata": { "labels": [ { "prefix": "global", "name": "[label]" } ] } }
Update Existing Page
First, get the current page to obtain the version number: GET [CUSTOMIZE: your-confluence-url]/wiki/rest/api/content/[PAGE_ID]?expand=version Then update: PUT [CUSTOMIZE: your-confluence-url]/wiki/rest/api/content/[PAGE_ID] Body: { "type": "page", "title": "[page title]", "version": { "number": [current_version + 1] }, "body": { "storage": { "value": "[converted XHTML content]", "representation": "storage" } } }
Phase 6: Confirm and Update Vault
After successful publishing:
-
Confirm to the user:
Published successfully! Page: [Title] URL: [Confluence page URL] Space: [Space Key] Version: [version number] -
Update the source vault file (add published metadata to frontmatter):
confluence_url: "[page URL]" confluence_page_id: "[page ID]" confluence_space: "[space key]" published_at: "[timestamp]" confluence_version: [version number] -
Log the publication for future reference.
Re-Publishing (Update Flow)
If the vault file already has
confluence_page_id in its frontmatter:
This document was previously published to Confluence: URL: [confluence_url] Last published: [published_at] Would you like to: a) Update the existing Confluence page (increment version) b) Create a new page (separate copy) c) Cancel
Fallback Behavior
| Scenario | Behavior |
|---|---|
| Confluence not active | Stop and inform user; suggest alternative platforms |
| Confluence API fails | Save the converted XHTML to a file so user can manually paste it |
| Authentication failure | Inform user their Confluence credentials may need refreshing |
| Page already exists (same title) | Ask user: update existing, create with different title, or cancel |
| Very large document | Warn user about page size; suggest splitting into child pages |
| Complex markdown (unsupported elements) | Convert best-effort, warn about any elements that couldn't be converted |
Error Handling
- API 403 (Forbidden): User may lack write permissions to the target space
- API 404 (Not Found): Space key or parent page ID may be incorrect
- API 409 (Conflict): Page was modified by someone else; fetch latest version and retry
- Conversion failures: Fall back to plain text for elements that can't be converted
- Rate limits: Retry with backoff
- Network errors: Save converted content locally so no work is lost