Install
$ agentstack add skill-totallygreg-claude-mp-confluence-pages ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Confluence Page Management
Purpose
This skill fills the write gap in the official Atlassian plugin. The official plugin provides read/search via atlassian:search-company-knowledge but cannot create, update, move, or delete pages.
> Rule: Always check if an official Atlassian plugin skill can handle the request first. Only use this skill for page CRUD and storage format generation.
Configuration
Set these variables before use (or define in a .local.md file):
| Variable | Description | Example | |---|---|---| | CONFLUENCE_BASE_URL | Instance base URL | https://confluence.example.com | | CONFLUENCE_TOKEN | PAT or keychain key | $(keychainctl get CLAUDE_CONFLUENCE) | | CONFLUENCE_USER | Your username | jdoe | | CONFLUENCE_SPACE | Default space key | ~jdoe | | CONFLUENCE_HOME_PAGE | Personal home page ID | 559735676 |
CONFLUENCE_BASE_URL="https://confluence.example.com"
CONFLUENCE_TOKEN=$(keychainctl get CLAUDE_CONFLUENCE)
All API calls use Bearer auth:
curl -s \
-H "Authorization: Bearer $CONFLUENCE_TOKEN" \
-H "Content-Type: application/json" \
"$CONFLUENCE_BASE_URL/rest/api/..."
API Operations
Search (CQL)
curl -s -H "Authorization: Bearer $CONFLUENCE_TOKEN" \
"$CONFLUENCE_BASE_URL/rest/api/content/search?cql=title+%7E+%22search+term%22&limit=10&expand=space,ancestors"
Common CQL: title ~ "term", space = "KEY" AND title ~ "term", ancestor = PAGE_ID, type = page AND lastModified > now("-7d")
Get Page
curl -s -H "Authorization: Bearer $CONFLUENCE_TOKEN" \
"$CONFLUENCE_BASE_URL/rest/api/content/PAGE_ID?expand=body.storage,version"
Create Page
cat > /tmp/confluence-page.json Content in storage format",
"representation": "storage"
}
}
}
EOF
curl -s -X POST \
-H "Authorization: Bearer $CONFLUENCE_TOKEN" \
-H "Content-Type: application/json" \
-d @/tmp/confluence-page.json \
"$CONFLUENCE_BASE_URL/rest/api/content"
rm /tmp/confluence-page.json
Update Page
Must increment version number. Fetch current version first.
cat > /tmp/confluence-update.json Updated content",
"representation": "storage"
}
}
}
EOF
curl -s -X PUT \
-H "Authorization: Bearer $CONFLUENCE_TOKEN" \
-H "Content-Type: application/json" \
-d @/tmp/confluence-update.json \
"$CONFLUENCE_BASE_URL/rest/api/content/PAGE_ID"
rm /tmp/confluence-update.json
Move Page
Same space — change parent
curl -s -X PUT \
-H "Authorization: Bearer $CONFLUENCE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ancestors": [{"id": NEW_PARENT_PAGE_ID}]}' \
"$CONFLUENCE_BASE_URL/rest/api/content/PAGE_ID"
Cross-space move — workaround required
> Known issue: Confluence Data Center does not reliably support cross-space moves via the REST API. The PUT /content/{id} endpoint with a different space.key often returns a generic error (Could not update Content of type), even when you have write access to both spaces. The /content/{id}/move/append/{targetId} endpoint may not exist on older DC versions.
Workaround: create in target space, redirect old page, then delete it.
# Step 1: Fetch the source page body
SOURCE_PAGE=$(curl -s -H "Authorization: Bearer $CONFLUENCE_TOKEN" \
"$CONFLUENCE_BASE_URL/rest/api/content/SOURCE_PAGE_ID?expand=body.storage")
# Step 2: Create new page in target space (use Python + temp file for large bodies)
python3 -c "
import json, sys
d = json.loads('''$SOURCE_PAGE''') # or read from file
payload = {
'type': 'page',
'title': d['title'],
'space': {'key': 'TARGET_SPACE_KEY'},
'ancestors': [{'id': TARGET_PARENT_ID}],
'body': d['body']
}
with open('/tmp/confluence-move.json', 'w') as f:
json.dump(payload, f)
"
curl -s -X POST \
-H "Authorization: Bearer $CONFLUENCE_TOKEN" \
-H "Content-Type: application/json" \
-d @/tmp/confluence-move.json \
"$CONFLUENCE_BASE_URL/rest/api/content"
rm /tmp/confluence-move.json
# Step 3: Update old page with redirect (optional, helps anyone with bookmarks)
curl -s -X PUT \
-H "Authorization: Bearer $CONFLUENCE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"version": {"number": CURRENT_VERSION + 1},
"title": "Old Title - MOVED",
"type": "page",
"body": {"storage": {
"value": "This page has movedThis page has been moved to new location.",
"representation": "storage"
}}
}' \
"$CONFLUENCE_BASE_URL/rest/api/content/SOURCE_PAGE_ID"
# Step 4: Delete old page when ready
curl -s -X DELETE \
-H "Authorization: Bearer $CONFLUENCE_TOKEN" \
"$CONFLUENCE_BASE_URL/rest/api/content/SOURCE_PAGE_ID"
Recommended approach for cross-space moves:
- Fetch source page content (body + title)
- Create new page in target space under desired parent
- Update old page title to "… - MOVED" with redirect link
- Delete old page once confirmed
Delete Page
curl -s -X DELETE \
-H "Authorization: Bearer $CONFLUENCE_TOKEN" \
"$CONFLUENCE_BASE_URL/rest/api/content/PAGE_ID"
Storage Format
Page content uses Confluence Storage Format (XHTML with ac: namespace macros). See references/storage-format.md for the full macro reference including panels, status badges, code blocks, layouts, emoticons, and page trees.
Key rules:
- Use the Write tool to create temp JSON files for large payloads
- Escape special characters:
&–—•’ - Never use raw
&,–,—in storage format
Response Parsing
curl -s ... | python3 -c "
import sys, json
d = json.load(sys.stdin)
if 'id' in d:
base = d.get('_links',{}).get('base','')
webui = d.get('_links',{}).get('webui','')
print(f'OK — Page ID: {d[\"id\"]}, Version: {d.get(\"version\",{}).get(\"number\",\"?\")}, URL: {base}{webui}')
else:
print(f'Error: {d.get(\"message\", json.dumps(d))}')
"
Best Practices
- Draft in personal space first — move to team space when ready
- Use temp files for payloads — avoids shell quoting issues with XML
- Always fetch version before updating — stale versions cause 409 conflicts
- Clean up temp files —
rm /tmp/confluence-*.jsonafter API calls - Use the official plugin for search —
atlassian:search-company-knowledgeis better for finding pages
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: totallyGreg
- Source: totallyGreg/claude-mp
- License: MIT
- Homepage: https://github.com/totallyGreg/claude-mp
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.