confluence-docs
Atlassian Confluence integration for enterprise documentation. Create and update pages via API, manage spaces and permissions, handle content migration, and sync between Markdown and Confluence.
Best use case
confluence-docs is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Atlassian Confluence integration for enterprise documentation. Create and update pages via API, manage spaces and permissions, handle content migration, and sync between Markdown and Confluence.
Teams using confluence-docs should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/confluence-docs/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How confluence-docs Compares
| Feature / Agent | confluence-docs | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Atlassian Confluence integration for enterprise documentation. Create and update pages via API, manage spaces and permissions, handle content migration, and sync between Markdown and Confluence.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Confluence Integration Skill
Atlassian Confluence integration for enterprise documentation.
## Capabilities
- Page creation and updates via API
- Space management and permissions
- Macro and template management
- Content migration (Markdown to Confluence)
- Attachment handling
- Label and metadata management
- Confluence Cloud and Server support
- Confluence-to-Markdown export
## Usage
Invoke this skill when you need to:
- Sync documentation to Confluence
- Migrate content between formats
- Manage Confluence spaces programmatically
- Automate page updates from CI/CD
- Export Confluence to Markdown
## Inputs
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| action | string | Yes | create, update, migrate, export |
| baseUrl | string | Yes | Confluence instance URL |
| spaceKey | string | Yes | Target space key |
| sourcePath | string | No | Source Markdown files |
| pageId | string | No | Specific page ID for updates |
| parentPageId | string | No | Parent page for hierarchy |
### Input Example
```json
{
"action": "migrate",
"baseUrl": "https://company.atlassian.net/wiki",
"spaceKey": "DOCS",
"sourcePath": "./docs",
"parentPageId": "123456"
}
```
## Configuration
### confluence.config.json
```json
{
"baseUrl": "https://company.atlassian.net/wiki",
"auth": {
"type": "token",
"email": "${CONFLUENCE_EMAIL}",
"token": "${CONFLUENCE_TOKEN}"
},
"space": {
"key": "DOCS",
"name": "Documentation"
},
"migration": {
"preserveStructure": true,
"convertTables": true,
"uploadImages": true,
"macroMapping": {
"note": "info",
"warning": "warning",
"code": "code"
}
},
"sync": {
"dryRun": false,
"updateExisting": true,
"createMissing": true,
"archiveRemoved": false
}
}
```
## API Integration
### Confluence REST API Client
```javascript
const ConfluenceClient = require('confluence-api');
class ConfluenceManager {
constructor(config) {
this.client = new ConfluenceClient({
username: config.email,
password: config.token,
baseUrl: config.baseUrl
});
}
// Create a new page
async createPage(spaceKey, title, content, parentId = null) {
const page = {
type: 'page',
title,
space: { key: spaceKey },
body: {
storage: {
value: content,
representation: 'storage'
}
}
};
if (parentId) {
page.ancestors = [{ id: parentId }];
}
return await this.client.postContent(page);
}
// Update existing page
async updatePage(pageId, title, content, version) {
const page = {
id: pageId,
type: 'page',
title,
version: { number: version + 1 },
body: {
storage: {
value: content,
representation: 'storage'
}
}
};
return await this.client.putContent(page);
}
// Get page by title
async getPageByTitle(spaceKey, title) {
const result = await this.client.getContentBySpaceKey(spaceKey, {
title,
expand: 'version,body.storage'
});
return result.results[0] || null;
}
// Upload attachment
async uploadAttachment(pageId, filePath, comment = '') {
const form = new FormData();
form.append('file', fs.createReadStream(filePath));
form.append('comment', comment);
return await this.client.createAttachment(pageId, form);
}
// Add labels
async addLabels(pageId, labels) {
const labelPayload = labels.map(name => ({
prefix: 'global',
name
}));
return await this.client.postLabels(pageId, labelPayload);
}
}
```
## Markdown to Confluence Conversion
### Converter
```javascript
const marked = require('marked');
class MarkdownToConfluence {
constructor(options = {}) {
this.options = options;
this.attachments = [];
}
convert(markdown, metadata = {}) {
// Parse front matter
const { content, frontMatter } = this.parseFrontMatter(markdown);
// Convert markdown to HTML
let html = marked.parse(content);
// Convert to Confluence storage format
html = this.convertToStorageFormat(html);
// Handle macros
html = this.convertMacros(html);
// Handle code blocks
html = this.convertCodeBlocks(html);
// Handle images
html = this.convertImages(html);
// Handle tables
html = this.convertTables(html);
return {
title: frontMatter.title || metadata.title,
content: html,
labels: frontMatter.tags || [],
attachments: this.attachments
};
}
convertMacros(html) {
// Convert admonitions to Confluence macros
const macroMap = {
'note': 'info',
'warning': 'warning',
'tip': 'tip',
'danger': 'warning'
};
for (const [mdType, confType] of Object.entries(macroMap)) {
const regex = new RegExp(`<div class="${mdType}">([\\s\\S]*?)</div>`, 'g');
html = html.replace(regex, (match, content) => {
return `<ac:structured-macro ac:name="${confType}">
<ac:rich-text-body>${content}</ac:rich-text-body>
</ac:structured-macro>`;
});
}
return html;
}
convertCodeBlocks(html) {
// Convert code blocks to Confluence code macro
return html.replace(
/<pre><code class="language-(\w+)">([\s\S]*?)<\/code><\/pre>/g,
(match, language, code) => {
const decodedCode = this.decodeHtml(code);
return `<ac:structured-macro ac:name="code">
<ac:parameter ac:name="language">${language}</ac:parameter>
<ac:plain-text-body><![CDATA[${decodedCode}]]></ac:plain-text-body>
</ac:structured-macro>`;
}
);
}
convertImages(html) {
// Convert images to Confluence attachments
return html.replace(
/<img src="([^"]+)" alt="([^"]*)"[^>]*>/g,
(match, src, alt) => {
if (src.startsWith('http')) {
// External image
return `<ac:image><ri:url ri:value="${src}" /></ac:image>`;
} else {
// Local attachment
const filename = path.basename(src);
this.attachments.push({ src, filename });
return `<ac:image><ri:attachment ri:filename="${filename}" /></ac:image>`;
}
}
);
}
convertTables(html) {
// Confluence uses standard HTML tables but needs specific attributes
return html.replace(/<table>/g, '<table class="wrapped">');
}
}
```
## Confluence to Markdown Export
### Exporter
```javascript
class ConfluenceToMarkdown {
constructor(client) {
this.client = client;
}
async exportSpace(spaceKey, outputDir) {
const pages = await this.getAllPages(spaceKey);
const structure = this.buildHierarchy(pages);
for (const page of pages) {
const markdown = await this.exportPage(page);
const filePath = this.getFilePath(page, structure, outputDir);
await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.writeFile(filePath, markdown);
}
return { exported: pages.length };
}
async exportPage(page) {
const content = page.body.storage.value;
// Convert Confluence storage format to Markdown
let markdown = this.convertToMarkdown(content);
// Add front matter
const frontMatter = {
title: page.title,
confluence_id: page.id,
last_modified: page.version.when
};
return `---
${yaml.stringify(frontMatter)}---
${markdown}`;
}
convertToMarkdown(storage) {
let md = storage;
// Convert code macro
md = md.replace(
/<ac:structured-macro ac:name="code"[^>]*>[\s\S]*?<ac:parameter ac:name="language">(\w+)<\/ac:parameter>[\s\S]*?<ac:plain-text-body><!\[CDATA\[([\s\S]*?)\]\]><\/ac:plain-text-body>[\s\S]*?<\/ac:structured-macro>/g,
(match, lang, code) => `\`\`\`${lang}\n${code}\n\`\`\``
);
// Convert info macro
md = md.replace(
/<ac:structured-macro ac:name="(info|warning|tip)"[^>]*>[\s\S]*?<ac:rich-text-body>([\s\S]*?)<\/ac:rich-text-body>[\s\S]*?<\/ac:structured-macro>/g,
(match, type, content) => `> **${type.toUpperCase()}:** ${this.stripHtml(content)}`
);
// Convert headings, lists, etc.
md = this.convertHtmlToMarkdown(md);
return md;
}
}
```
## Sync Workflow
### Bidirectional Sync
```javascript
async function syncDocumentation(config) {
const confluence = new ConfluenceManager(config);
const converter = new MarkdownToConfluence(config.migration);
// Get local files
const localFiles = await glob('docs/**/*.md');
// Get Confluence pages
const pages = await confluence.getSpaceContent(config.space.key);
const results = {
created: [],
updated: [],
skipped: [],
errors: []
};
for (const file of localFiles) {
try {
const markdown = await fs.readFile(file, 'utf8');
const converted = converter.convert(markdown, { file });
// Check if page exists
const existing = await confluence.getPageByTitle(
config.space.key,
converted.title
);
if (existing) {
if (config.sync.updateExisting) {
await confluence.updatePage(
existing.id,
converted.title,
converted.content,
existing.version.number
);
results.updated.push(file);
} else {
results.skipped.push(file);
}
} else if (config.sync.createMissing) {
await confluence.createPage(
config.space.key,
converted.title,
converted.content,
config.parentPageId
);
results.created.push(file);
}
// Upload attachments
for (const attachment of converted.attachments) {
await confluence.uploadAttachment(
existing?.id || results.created[results.created.length - 1].id,
attachment.src
);
}
} catch (error) {
results.errors.push({ file, error: error.message });
}
}
return results;
}
```
## Space Management
### Create Space
```javascript
async function createDocumentationSpace(config) {
const client = new ConfluenceManager(config);
const space = await client.client.postSpace({
key: config.space.key,
name: config.space.name,
description: {
plain: { value: config.space.description, representation: 'plain' }
},
permissions: [
{
subjects: { group: { name: 'confluence-users' } },
operation: { key: 'read', target: 'space' }
}
]
});
// Create home page
await client.createPage(
config.space.key,
'Home',
'<h1>Welcome to Documentation</h1>',
null
);
return space;
}
```
## Workflow
1. **Configure** - Set up Confluence credentials and space
2. **Convert** - Transform Markdown to Confluence format
3. **Sync** - Upload/update pages via API
4. **Attachments** - Upload images and files
5. **Labels** - Apply labels for organization
6. **Verify** - Check page rendering
## Dependencies
```json
{
"devDependencies": {
"confluence-api": "^1.4.0",
"marked": "^12.0.0",
"gray-matter": "^4.0.0",
"form-data": "^4.0.0"
}
}
```
## CLI Commands
```bash
# Sync Markdown to Confluence
node scripts/confluence-sync.js --config confluence.config.json
# Export Confluence to Markdown
node scripts/confluence-export.js --space DOCS --output ./exported
# Create new space
node scripts/confluence-space.js create --key NEWDOCS --name "New Documentation"
```
## Best Practices Applied
- Use page templates for consistency
- Organize with parent pages
- Apply labels for discoverability
- Keep source of truth in Git
- Sync on merge to main branch
- Handle attachments properly
## References
- Confluence REST API: https://developer.atlassian.com/cloud/confluence/rest/
- Storage Format: https://confluence.atlassian.com/doc/confluence-storage-format-790796544.html
- confluence-api npm: https://www.npmjs.com/package/confluence-api
## Target Processes
- knowledge-base-setup.js
- docs-pr-workflow.js
- content-strategy.jsRelated Skills
storybook-docs
Storybook integration for UI component documentation. Configure docs addon, generate component documentation from stories, write MDX documentation, and integrate with design systems.
sphinx-docs
Sphinx documentation system expertise for technical and API documentation. Configure projects, autodoc for Python APIs, intersphinx for cross-project linking, extensions, and multiple output formats.
mkdocs-material
MkDocs with Material theme expertise for Python-centric documentation. Configure navigation, plugins, multi-language support, PDF export, and advanced Material theme features.
docs-analytics
Documentation usage analytics and insights. Integrate with Google Analytics, Algolia analytics, and custom tracking to measure documentation effectiveness, identify content gaps, and optimize user journeys.
docs-accessibility
Documentation accessibility validation and remediation. Check WCAG 2.1 compliance, validate alt text, analyze heading hierarchy, verify color contrast, and generate accessibility reports.
asyncapi-docs
AsyncAPI specification handling for event-driven API documentation. Parse, validate, and generate documentation for message-based APIs including Kafka, MQTT, WebSocket, and AMQP systems.
docs-site-generator
Generate documentation sites using Docusaurus, MkDocs, or VuePress
embedded-docs
Embedded firmware documentation generation and maintenance using Doxygen and related tools. Expert skill for API documentation, hardware interface documentation, memory maps, and integration with documentation systems.
homologation-docs
Type approval documentation and certification management
process-builder
Scaffold new babysitter process definitions following SDK patterns, proper structure, and best practices. Guides the 3-phase workflow from research to implementation.
babysitter
Orchestrate via @babysitter. Use this skill when asked to babysit a run, orchestrate a process or whenever it is called explicitly. (babysit, babysitter, orchestrate, orchestrate a run, workflow, etc.)
yolo
Run Babysitter autonomously with minimal manual interruption.