From sdlc
Manage Confluence pages at yourcompany.atlassian.net via the REST API v2. Use this skill whenever the user wants to fetch, view, search, create, edit, or update a Confluence page — including pasting a Confluence URL and asking to edit it, asking about page content, listing pages in a space, or pushing local changes back. Trigger on any mention of Confluence pages, Confluence URLs (yourcompany.atlassian.net/wiki), page IDs, Confluence spaces, or requests like "update the confluence page", "fetch the PRD from confluence", "push my changes to confluence". Also trigger when the user asks to create a new Confluence page or search for existing pages.
npx claudepluginhub nexussema/omg-marketplace --plugin sdlcThis skill uses the workspace's default tool permissions.
You are working in an Atlassian PM workspace. Confluence is managed entirely via the **REST API v2** — ACLI does NOT support Confluence.
Guides TDD-style skill creation: pressure scenarios as tests, baseline agent failures, write docs to enforce compliance, verify with RED-GREEN-REFACTOR.
Guides idea refinement into designs: explores context, asks questions one-by-one, proposes approaches, presents sections for approval, writes/review specs before coding.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
You are working in an Atlassian PM workspace. Confluence is managed entirely via the REST API v2 — ACLI does NOT support Confluence.
Credentials and instance URL are read from environment variables. Users must set these in their shell profile (see README for setup):
# Read credentials from environment (set in ~/.zshrc, ~/.bashrc, etc.)
ATLASSIAN_EMAIL="${ATLASSIAN_EMAIL}"
ATLASSIAN_API_TOKEN="${ATLASSIAN_API_TOKEN}"
ATLASSIAN_INSTANCE="${ATLASSIAN_INSTANCE:-yourcompany.atlassian.net}"
If the env vars are not available in the subprocess, fall back to reading from the shell profile:
ATLASSIAN_EMAIL="${ATLASSIAN_EMAIL:-$(grep 'export ATLASSIAN_EMAIL' ~/.zshrc ~/.bashrc ~/.bash_profile 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_API_TOKEN="${ATLASSIAN_API_TOKEN:-$(grep 'export ATLASSIAN_API_TOKEN' ~/.zshrc ~/.bashrc ~/.bash_profile 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_INSTANCE="${ATLASSIAN_INSTANCE:-$(grep 'export ATLASSIAN_INSTANCE' ~/.zshrc ~/.bashrc ~/.bash_profile 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//' || echo 'yourcompany.atlassian.net')}"
https://${ATLASSIAN_INSTANCE}/wiki/api/v2-u "$ATLASSIAN_EMAIL:$ATLASSIAN_API_TOKEN"/wiki/rest/api) returns 401When the user pastes a Confluence URL, the page ID is the numeric segment:
https://{instance}/wiki/spaces/myproject/pages/3711631361/Page+Title
^^^^^^^^^^^
This is the page ID
Use when the user shares a Confluence URL or page ID and wants to view or edit it.
Step 1 — Fetch and save locally:
ATLASSIAN_EMAIL="${ATLASSIAN_EMAIL:-$(grep 'export ATLASSIAN_EMAIL' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_API_TOKEN="${ATLASSIAN_API_TOKEN:-$(grep 'export ATLASSIAN_API_TOKEN' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_INSTANCE="${ATLASSIAN_INSTANCE:-$(grep 'export ATLASSIAN_INSTANCE' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//' || echo 'yourcompany.atlassian.net')}"
PAGE_ID="<id>"
SLUG="<descriptive-slug>" # e.g. PRD-AI-Agent-Platform or Functional-Requirements
curl -s -u "$ATLASSIAN_EMAIL:$ATLASSIAN_API_TOKEN" \
"https://$ATLASSIAN_INSTANCE/wiki/api/v2/pages/$PAGE_ID?body-format=storage" \
| python3 -c "
import json, sys
d = json.load(sys.stdin)
body = d['body']['storage']['value']
title = d['title']
version = d['version']['number']
print(f'Title: {title}')
print(f'Version: {version}')
open(f'Confluence/$SLUG.html', 'w').write(body)
print('Saved.')
"
The storage XHTML is saved to Confluence/<slug>.html in the workspace root.
Step 2 — Edit:
Edit the .html file directly using the Edit tool. Confluence storage format is XHTML — use standard HTML tags (<p>, <h1>, <ul>, <li>, <table>, <ac:structured-macro> for Confluence macros).
Step 3 — Push back:
${CLAUDE_PLUGIN_ROOT}/scripts/push-confluence-page.sh Confluence/<slug>.html <PAGE_ID> "brief description of changes"
The push script handles version incrementing automatically.
ATLASSIAN_EMAIL="${ATLASSIAN_EMAIL:-$(grep 'export ATLASSIAN_EMAIL' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_API_TOKEN="${ATLASSIAN_API_TOKEN:-$(grep 'export ATLASSIAN_API_TOKEN' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_INSTANCE="${ATLASSIAN_INSTANCE:-$(grep 'export ATLASSIAN_INSTANCE' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//' || echo 'yourcompany.atlassian.net')}"
curl -s -u "$ATLASSIAN_EMAIL:$ATLASSIAN_API_TOKEN" \
"https://$ATLASSIAN_INSTANCE/wiki/api/v2/spaces/<spaceId>/pages?limit=50" \
| python3 -c "
import json, sys
d = json.load(sys.stdin)
for p in d.get('results', []):
print(f\"{p['id']}\t{p['title']}\")
"
To get the spaceId for your confluence, use the List Spaces command below first.
ATLASSIAN_EMAIL="${ATLASSIAN_EMAIL:-$(grep 'export ATLASSIAN_EMAIL' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_API_TOKEN="${ATLASSIAN_API_TOKEN:-$(grep 'export ATLASSIAN_API_TOKEN' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_INSTANCE="${ATLASSIAN_INSTANCE:-$(grep 'export ATLASSIAN_INSTANCE' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//' || echo 'yourcompany.atlassian.net')}"
curl -s -u "$ATLASSIAN_EMAIL:$ATLASSIAN_API_TOKEN" \
"https://$ATLASSIAN_INSTANCE/wiki/api/v2/spaces" \
| python3 -c "
import json, sys
d = json.load(sys.stdin)
for s in d.get('results', []):
print(f\"{s['id']}\t{s['key']}\t{s['name']}\")
"
Use CQL (Confluence Query Language) to search by title or content. Note: search uses the v1 endpoint (the v2 search endpoint is not fully available).
ATLASSIAN_EMAIL="${ATLASSIAN_EMAIL:-$(grep 'export ATLASSIAN_EMAIL' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_API_TOKEN="${ATLASSIAN_API_TOKEN:-$(grep 'export ATLASSIAN_API_TOKEN' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_INSTANCE="${ATLASSIAN_INSTANCE:-$(grep 'export ATLASSIAN_INSTANCE' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//' || echo 'yourcompany.atlassian.net')}"
QUERY="<search term>"
curl -s -u "$ATLASSIAN_EMAIL:$ATLASSIAN_API_TOKEN" \
"https://$ATLASSIAN_INSTANCE/wiki/rest/api/content/search?cql=space=space+AND+title+~+\"$QUERY\"&limit=10" \
| python3 -c "
import json, sys
d = json.load(sys.stdin)
for r in d.get('results', []):
print(f\"{r['id']}\t{r['title']}\")
"
curl -s -u "$ATLASSIAN_EMAIL:$ATLASSIAN_API_TOKEN" \
"https://$ATLASSIAN_INSTANCE/wiki/api/v2/pages/<id>/children" \
| python3 -c "
import json, sys
d = json.load(sys.stdin)
for p in d.get('results', []):
print(f\"{p['id']}\t{p['title']}\")
"
Build the payload and POST it:
ATLASSIAN_EMAIL="${ATLASSIAN_EMAIL:-$(grep 'export ATLASSIAN_EMAIL' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_API_TOKEN="${ATLASSIAN_API_TOKEN:-$(grep 'export ATLASSIAN_API_TOKEN' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//')}"
ATLASSIAN_INSTANCE="${ATLASSIAN_INSTANCE:-$(grep 'export ATLASSIAN_INSTANCE' ~/.zshrc ~/.bashrc 2>/dev/null | head -1 | sed 's/.*=\"//;s/\".*//' || echo 'yourcompany.atlassian.net')}"
python3 -c "
import json
payload = {
'spaceId': '<spaceId>',
'parentId': '<parent-page-id>', # optional; omit if top-level
'title': 'Page Title Here',
'body': {
'representation': 'storage',
'value': '<p>Your HTML content here.</p>'
}
}
json.dump(payload, open('/tmp/cf_create.json', 'w'))
print('Payload written.')
"
curl -s -u "$ATLASSIAN_EMAIL:$ATLASSIAN_API_TOKEN" \
-X POST \
-H "Content-Type: application/json" \
-d @/tmp/cf_create.json \
"https://$ATLASSIAN_INSTANCE/wiki/api/v2/pages" \
| python3 -c "
import json, sys
d = json.load(sys.stdin)
if 'id' in d:
print(f\"Created page ID: {d['id']}\")
print(f\"Title: {d['title']}\")
else:
print('Error:', json.dumps(d, indent=2))
"
Always confirm with the user before deleting.
curl -s -u "$ATLASSIAN_EMAIL:$ATLASSIAN_API_TOKEN" \
-X DELETE \
"https://$ATLASSIAN_INSTANCE/wiki/api/v2/pages/<id>"
$ATLASSIAN_INSTANCE env var (defaults to yourcompany.atlassian.net)Confluence/ in the project root${CLAUDE_PLUGIN_ROOT}/scripts/push-confluence-page.sh <file.html> <page_id> "message" (auto-increments version)status: "current" is required in update payloads — omitting it returns 400