opencode/skills/confluence/SKILL.md
Read, write, and respond to comments on Confluence pages via the REST API v2. Use when the user wants to fetch page content, search pages, update a page, create a new page, or address comments and suggestions left by others.
npx skillsauth add msegoviadev/dotfiles confluenceInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when:
your-org.atlassian.net/wiki)hurl installed: brew install hurljq installed: brew install jqREADME.md<SKILLS_DIR>: the root skills directory (e.g., ~/.config/opencode/skills/ for opencode, ~/.claude/skills/ for claude-code)[[ -f ~/.config/hurl/confluence/default.env ]] && echo "ok" || echo "credentials file not found: ~/.config/hurl/confluence/default.env"
If missing, stop and guide the user to set up the credentials file from the Prerequisites section.
From a URL — extract the page ID from the path:
https://your-org.atlassian.net/wiki/spaces/SPACE/pages/123456789/Page+Title
^^^^^^^^^^ page ID
By title search — find the page ID when only a title is known:
cat > $TMPDIR/hurl_req.hurl << 'EOF'
GET {{base_url_confluence}}/api/v2/pages
[QueryStringParams]
title: {{title}}
body-format: storage
limit: 5
[Options]
user: {{email}}:{{token}}
cacert: {{cacert}}
EOF
hurl --variables-file ~/.config/hurl/confluence/default.env \
--variable title="<title>" \
$TMPDIR/hurl_req.hurl | jq '.results[] | {id, title, spaceId}'
List pages in a space (use the space key visible in Confluence URLs):
# First get the spaceId from the space key
cat > $TMPDIR/hurl_req.hurl << 'EOF'
GET {{base_url_confluence}}/api/v2/spaces
[QueryStringParams]
keys: {{space_key}}
[Options]
user: {{email}}:{{token}}
cacert: {{cacert}}
EOF
hurl --variables-file ~/.config/hurl/confluence/default.env \
--variable space_key="<SPACE_KEY>" \
$TMPDIR/hurl_req.hurl | jq '.results[] | {id, key, name}'
# Then list pages in that space
cat > $TMPDIR/hurl_req.hurl << 'EOF'
GET {{base_url_confluence}}/api/v2/pages
[QueryStringParams]
spaceId: {{space_id}}
limit: 25
[Options]
user: {{email}}:{{token}}
cacert: {{cacert}}
EOF
hurl --variables-file ~/.config/hurl/confluence/default.env \
--variable space_id="<space_id>" \
$TMPDIR/hurl_req.hurl | jq '.results[] | {id, title}'
cat > $TMPDIR/hurl_req.hurl << 'EOF'
GET {{base_url_confluence}}/api/v2/pages/{{page_id}}
[QueryStringParams]
body-format: storage
[Options]
user: {{email}}:{{token}}
cacert: {{cacert}}
EOF
hurl --variables-file ~/.config/hurl/confluence/default.env \
--variable page_id="<page_id>" \
$TMPDIR/hurl_req.hurl | jq '{id, title, version: .version.number, body: .body.storage.value, spaceId}'
The response includes:
id — needed for updatesversion.number — required for the update requestbody.storage.value — current page content in Confluence storage format (HTML-like XML)spaceId — needed for creating child pagesFor updates: take the existing storage-format body, apply the requested changes, and show a diff or the full new content to the user for approval.
For creates: draft the page content in storage format. Common elements:
<p>Paragraph text</p><h1>Heading 1</h1>, <h2>Heading 2</h2><ul><li>Item</li></ul> / <ol><li>Item</li></ol><ac:structured-macro ac:name="code"><ac:plain-text-body><![CDATA[...]]></ac:plain-text-body></ac:structured-macro> for code blocksPresent the proposed content and get explicit approval before proceeding.
Gotchas when using Python for writes:
- hurl templates don't JSON-escape
{{body}}— use Python +json.dumps()for any body with HTML attributes- Use
subprocess.run(['curl', '-s', '-k', '-u', ...])— do NOT useurllib.requestorrequests: pyenv Python uses Homebrew OpenSSL which lacks corporate proxy certs (Cisco Umbrella); systemcurluses SecureTransport/macOS Keychain and works- Don't pass
--cacertto curl — SecureTransport handles trust from the Keychain automatically- Write the JSON payload to a temp file and pass with
-d @path; usedir=os.environ.get('TMPDIR', '/tmp')for the temp dir (sandbox restriction)- Token in the credentials file may contain
=signs — parse withline.split('=', 1)notcut -d= -f2
Creating a page — use the create template. Requires spaceId and optionally parentId:
hurl --variables-file ~/.config/hurl/confluence/default.env \
<SKILLS_DIR>/confluence/templates/create-page.hurl \
--variable space_id="<space_id>" \
--variable parent_id="<parent_page_id>" \
--variable title="<Page Title>" \
--variable body="<storage format content>"
Updating a page — use the update template. The version must be current version + 1:
hurl --variables-file ~/.config/hurl/confluence/default.env \
<SKILLS_DIR>/confluence/templates/update-page.hurl \
--variable page_id="<page_id>" \
--variable title="<Page Title>" \
--variable version=<current_version_plus_one> \
--variable version_message="<short description of change>" \
--variable body="<storage format content>"
After creating or updating, the page is accessible at:
https://your-org.atlassian.net/wiki/spaces/<SPACE_KEY>/pages/<page_id>
The Confluence UML macro embeds a code macro inside a uml macro:
<ac:structured-macro ac:name="uml" ac:schema-version="1" data-layout="default">
<ac:rich-text-body>
<ac:structured-macro ac:name="code" ac:schema-version="1">
<ac:plain-text-body><![CDATA[
@startuml
... diagram source ...
@enduml
]]></ac:plain-text-body>
</ac:structured-macro>
</ac:rich-text-body>
</ac:structured-macro>
Color syntax gotchas:
:text; <<#color>> — stereotype at the end, no #color: prefix#color:text; prefix syntax now triggers deprecation warnings in the plugin:line1\nline2; <<#cce5ff>>\n in a note right: text\nmore becomes a real newline and breaks PlantUML's single-line note syntax — use \\n insteadSimple operations (read a page by ID, title search, fetch comments) — no reference needed.
Load references/api-commands.md for:
There are two comment types. Fetch both:
Footer comments (page-level discussion):
cat > $TMPDIR/hurl_req.hurl << 'EOF'
GET {{base_url_confluence}}/api/v2/pages/{{page_id}}/footer-comments
[QueryStringParams]
body-format: storage
limit: 50
[Options]
user: {{email}}:{{token}}
cacert: {{cacert}}
EOF
hurl --variables-file ~/.config/hurl/confluence/default.env \
--variable page_id="<page_id>" \
$TMPDIR/hurl_req.hurl | jq '.results[] | {id, author: .author.displayName, body: .body.storage.value, replies: ._links.replies}'
Inline comments (tied to specific text):
cat > $TMPDIR/hurl_req.hurl << 'EOF'
GET {{base_url_confluence}}/api/v2/pages/{{page_id}}/inline-comments
[QueryStringParams]
body-format: storage
limit: 50
[Options]
user: {{email}}:{{token}}
cacert: {{cacert}}
EOF
hurl --variables-file ~/.config/hurl/confluence/default.env \
--variable page_id="<page_id>" \
$TMPDIR/hurl_req.hurl | jq '.results[] | {id, author: .author.displayName, body: .body.storage.value, status}'
For each comment that has replies, fetch the thread:
cat > $TMPDIR/hurl_req.hurl << 'EOF'
GET {{base_url_confluence}}/api/v2/comments/{{comment_id}}/replies
[QueryStringParams]
body-format: storage
[Options]
user: {{email}}:{{token}}
cacert: {{cacert}}
EOF
hurl --variables-file ~/.config/hurl/confluence/default.env \
--variable comment_id="<comment_id>" \
$TMPDIR/hurl_req.hurl | jq '.results[] | {id, author: .author.displayName, body: .body.storage.value}'
For each comment/thread, decide:
Present the full assessment to the user before proposing any action.
Collect all proposed replies and/or page edits into a single batch. Show them to the user for approval:
📝 Proposed Actions (2)
━━━ Comment #abc123 (footer) ━━━
Author: Jane Doe
Comment: "The deployment steps are missing the rollback procedure."
→ Action: Reply + page update
→ Reply: "Good catch — added a Rollback section under Deployment Steps."
→ Page change: [show diff of added section]
━━━ Comment #def456 (inline) ━━━
Author: Bob Smith
Comment: "Should this be idempotent?"
→ Action: Reply only
→ Reply: "Yes, this operation is idempotent. Added a note to clarify."
Wait for user to approve/reject each proposed action.
Post an approved reply:
hurl --variables-file ~/.config/hurl/confluence/default.env \
<SKILLS_DIR>/confluence/templates/reply-to-comment.hurl \
--variable comment_id="<comment_id>" \
--variable reply_text="<p>Reply text here.</p>"
Apply page changes: follow Step 3-5 of the main workflow (fetch version, prepare content, run update-page.hurl).
User: "Update the release page at https://your-org.atlassian.net/wiki/spaces/ENG/pages/987654/v2.5+Release+Notes with these new items: ..."
Agent:
987654 from the URLhurl GET on /pages/987654?body-format=storagehurl update-page.hurl with version=<current+1>User: "Create a new page under the Architecture space for the new payments service we just defined"
Agent:
spaceIdhurl create-page.hurl with the space ID and contentUser: "Address the comments on https://your-org.atlassian.net/wiki/spaces/ENG/pages/987654/v2.5+Release+Notes"
Agent:
987654 from the URLreply-to-comment.hurl and page updates via update-page.hurldevelopment
Best practices for Remotion - Video creation in React
tools
Interact with Jira using the jira CLI. View, create, transition, assign, and comment on issues. Use when the user mentions Jira, issue keys, sprints, or ticket work.
development
Review GitLab merge requests by analyzing code changes and posting inline comments. Always shows comments for approval before posting and checks for duplicates. Use when reviewing someone else's MR.
development
Respond to feedback on your own merge request. Fetches discussions, proposes replies and code changes, and asks for approval before posting anything. Use when addressing review comments on your MR.