name: confluence description: 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. metadata: tags: confluence, wiki, page, comment, feedback, atlassian
When to Use
Use this skill when:
- User wants to read or search Confluence pages
- User wants to update a page (e.g., add release notes, fix grammar, restructure content)
- User wants to create a new page in a Confluence space
- User wants to address, reply to, or act on comments left on a page
- User references a Confluence URL (
your-org.atlassian.net/wiki)
Prerequisites
hurlinstalled:brew install hurljqinstalled:brew install jq- Credentials file set up: see
README.md <SKILLS_DIR>: the root skills directory (e.g.,~/.config/opencode/skills/for opencode,~/.claude/skills/for claude-code)
Core Safety Principles
- Fetch before modifying. Always read the current page content and capture the version number before any update. Confluence requires the current version to prevent conflicts.
- Show before writing. Display proposed content for approval. Confluence has no built-in undo for API writes.
- Never write without explicit approval. Create, update, and reply operations must be approved by the user before executing.
- Check for existing replies before proposing a reply to a comment thread to avoid duplicates.
- Do not resolve or delete comments unless the user explicitly requests it.
Workflow
Step 1: Confirm credentials
[[ -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.
Step 2: Identify the target page
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}'
Step 3: Read page content
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 pages
Step 4: Prepare the new content
For 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 blocks
Present the proposed content and get explicit approval before proceeding.
Step 5: Execute the write operation
Warning: hurl templates do not JSON-escape
{{body}}. Confluence storage format HTML always contains double quotes in XML attributes (e.g.ac:local-id="...",href="..."). Passing such content via--variable body=...produces malformed JSON and the request fails with HTTP 400.For any body containing HTML attributes, use Python instead:
- Build the body string in Python
- Serialize the full payload with
json.dumps()(handles all escaping)- Send with
urllib.request(stdlib) orrequestsReserve the hurl templates for simple plain-text bodies with no double quotes.
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>"
Page URL
After creating or updating, the page is accessible at:
https://your-org.atlassian.net/wiki/spaces/<SPACE_KEY>/pages/<page_id>
When to Load Full References
Simple operations (read a page by ID, title search, fetch comments) — no reference needed.
Load references/api-commands.md for:
- Advanced CQL queries
- Pagination through large result sets
- Ancestor/children page traversal
- Label management
- Space ID lookup details
- Fetching a single comment by ID
- Troubleshooting 400/403/409 errors
Address Comments Workflow
Step A: Fetch all comments
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}'
Step B: Assess each comment
For each comment/thread, decide:
- Content change needed — the comment suggests an edit to the page body (proceed with the update workflow)
- Reply needed — the comment asks a question or raises a point that warrants acknowledgment
- Both — apply the change and reply confirming it was addressed
- No action — already resolved, off-topic, or acknowledged in the thread
Present the full assessment to the user before proposing any action.
Step C: Draft and present proposed actions
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.
Step D: Execute approved actions
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).
Example Usage
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:
- Confirms credentials are set
- Extracts page ID
987654from the URL - Fetches current content and version with
hurlGET on/pages/987654?body-format=storage - Drafts updated storage-format body incorporating the new items
- Shows the proposed changes for approval
- Runs
hurl update-page.hurlwithversion=<current+1> - Returns the page URL to confirm success
User: "Create a new page under the Architecture space for the new payments service we just defined"
Agent:
- Confirms credentials
- Searches for the Architecture space to get its
spaceId - Optionally prompts for a parent page or uses the space root
- Drafts the page content in storage format based on what the user described
- Shows the draft for approval
- Runs
hurl create-page.hurlwith the space ID and content
User: "Address the comments on https://your-org.atlassian.net/wiki/spaces/ENG/pages/987654/v2.5+Release+Notes"
Agent:
- Confirms credentials
- Extracts page ID
987654from the URL - Fetches footer comments and inline comments for that page
- For each comment with replies, fetches the full thread
- Assesses each comment: content change, reply, or no action needed
- Presents the full batch of proposed replies and/or page edits for approval
- Executes approved replies via
reply-to-comment.hurland page updates viaupdate-page.hurl