argument-hint: "[confluence-page-url]" description: Run a remote retrospective backed by a Confluence page. Loads the page, detects its phase (collect, vote, discuss), and directs the user to the next action — collect entries, cluster and prioritize them, gather votes, or present the discussion agenda. name: retro allowed-tools:
- mcp__Atlassian__*
Retro
Drive a team retrospective through a single Confluence page.
Roles
- Host. The caller who creates the page. Recorded in
# Host. Only the host writes the body and triggers phase transitions. - Participant. Anyone else running
/retro <url>. Posts a footer comment for entries or ballots. Never modifies the body.
The host is also a participant: they post their own entries and ballot as comments alongside everyone else.
Workflow
Open every invocation with one short joke (one or two lines) about software development, productivity, remote work, debugging, or related dev-life topics. Pick a fresh joke each call — don't repeat the same joke on the same page. Then proceed.
1. Resolve the Page
Accept a page URL from ${ARGUMENTS}. When none is supplied, find the latest retro and decide whether to reuse it or create the next one.
Run searchConfluenceUsingCql with space = "ENGHEADLESS" AND parent = "2151056423" AND title ~ "Retro" to list pages under Retrospectives, parse titles matching Retro <integer>, and pick the highest number M.
If a Retro <M> exists and its # Status is Collect or Vote, the retro is still in progress — use it.
Otherwise create Retro <N> (where N = M + 1, or N = 0 when no retro exists) in that same Retrospectives folder with the body below, where <host> is the caller's name from atlassianUserInfo and <accountId> is the caller's account_id. Read the page URL from the create response, then update the body to replace <page-url> with it.
To participate, run the following in your terminal:
```bash
claude plugin marketplace add liferay-headless/liferay-headless
claude plugin install liferay-headless@liferay-headless
claude plugin update liferay-headless@liferay-headless
claude "/retro <page-url>"
```
# Status
Collect
# Host
<host> (`<accountId>`)
2. Detect Role
Resolve the caller via atlassianUserInfo. Read # Host from the body. The caller is the host iff their account_id matches the parenthesized id under # Host. Otherwise they are a participant.
3. Run the Phase
Read the Status line under # Status and run the matching phase for the caller's role. Only the host can advance the phase, and only with explicit confirmation. After each phase action, wait for the caller's next message, refetch the page via getConfluencePage, and re-run this step.
1. Collect
Raw thoughts are collected from the team. Each thought batch is one footer comment on the page.
All callers (host and participants). Prompt the caller for thoughts one at a time. Tell them: "Send each thought as a separate message; reply next when you're done." Append each reply to an in-memory list as one bullet, verbatim. When the caller replies next, post one footer comment via createConfluenceFooterComment containing every accumulated bullet in order:
retro:entry
- Pair programming on the auth refactor caught a ton of edge cases early.
- Standup runs over by ten minutes most days.
Wording is preserved verbatim. Identity is captured by Confluence as the comment's createdBy — never write a name into the comment body.
After posting, tell the caller their entries are recorded and to send any message to check progress. The host may reply close to close collection.
Host (close). When the host asks to close collection, do all of the following in one body update:
Fetch every footer comment via
getConfluencePageFooterComments. Filter to comments whose body begins withretro:entry. Each bulleted line under that header is one entry; the participant is the comment'screatedBy.displayName.Cluster the entries, then build the
# Analysissection:- Group near-duplicate or thematically related entries into clusters.
- Tag each cluster as Went Well (prefix
A) or Did Not Go Well (prefixB) and assign a stable sequential ID per prefix (A1,A2, ...,B1,B2, ...). IDs must not change once published — they anchor voting and ranking. - Record the cluster's Frequency: distinct participants who raised it (count by comment author, not by bullet).
- Score each cluster on Severity (1 to 3) based on language intensity and stated impact.
- Assign a Champion: the participant whose thought best captures the cluster's theme. If multiple thoughts are equally representative, pick the one with the most concrete detail or strongest stated impact. The champion opens the cluster's discussion in the meeting.
- Enumerate every thought in the cluster verbatim under
Thoughts. Preserve original wording exactly. Do not attribute thoughts to authors in the list.
The
# Analysissection format:# Analysis ## Went Well 1. **A1 — Faster CI** - Frequency: 2. - Severity: 2. - Champion: Jane Doe. - Summary: CI changes delivered measurable speedups. - Thoughts: - "CI is way faster after the cache tweaks." - "PR builds went from 12 to 4 minutes." ## Did Not Go Well 1. **B1 — Standup Overruns** - Frequency: 1. - Severity: 2. - Champion: Carol King. - Summary: Daily standup consistently runs long. - Thoughts: - "Standup runs over by ten minutes most days."Refetch the page via
getConfluencePageto capture the freshest body, then write a new body: keep# Host, set# StatustoVote, append# Analysis. Then continue to the Vote phase.
2. Vote
Voting is open. Each ballot is one footer comment.
All callers (host and participants). Walk the caller through every cluster from # Analysis in ID order (A1, A2, ..., B1, ...). For each, present:
- The cluster ID and theme.
- The one-line summary.
Prompt for an integer between 1 and 10 — "how much do you want to discuss this in the meeting" (1 = skip, 10 = must discuss). Reject anything outside that range and ask again. Collect every rating before posting — partial ballots are not allowed.
Post one footer comment via createConfluenceFooterComment:
retro:vote
- A1: 6
- B1: 8
After posting, tell the caller their vote is recorded and to send any message to check progress. The host may reply close to close voting.
Host (close). When the host asks to close voting:
Fetch every footer comment, filter to
retro:vote. If a participant (bycreatedBy.accountId) posted more than one ballot, ignore all of theirs — voting is one-shot.Sum each cluster's ratings. Rank by:
- Rating sum, descending.
Frequency × Severity, descending.- Cluster ID, ascending.
Build the
# Agendasection as a ranked list of every cluster with average rating, the champion as opener, and a discussion prompt:# Agenda 1. **B1 — Standup Overruns** (avg 7.0) — Champion: Carol King opens. What format keeps standup at fifteen minutes? 1. **A1 — Faster CI** (avg 6.5) — Champion: Jane Doe opens. What's the next bottleneck to attack?Refetch the page, then write a new body: keep
# Hostand# Analysis, set# StatustoDiscuss, append# Agenda. Then continue to the Discuss phase.
3. Discuss
The agenda is published and the meeting is ready. For each item in order, the listed champion opens the discussion with their thought; the team then debates. The page is read-only by convention once Status is Discuss.
Host (finish). When the host replies finish, open the next retro page so thoughts can start accumulating immediately:
- Read the current page's title to extract its number
N(e.g.Retro 7→N = 7). - Create a new page titled
Retro <N+1>in the same space and parent as the current page, with the standard Collect body from step 1 (using the current host's identity in# Host). Replace<page-url>in the body with the new page's URL. - Report the new URL and tell the host to share it with the team.
Participants who reply finish are told only the host can close the retro.