Skip to content

Repository files navigation

retro-reflect-bot

A command-line tool that reads your sprint notes (and, optionally, your team's GitHub activity) and uses Claude to write reflection cards into a Parabol Retrospective meeting — automatically, in the right column, with sources linked.

If your retros tend to start with an awkward five minutes of "…what happened this sprint again?" — this is for you.


What it does, in 30 seconds

  1. You drop notes into an inputs/ directory (markdown, plain text, or JSON — whatever you have).
  2. (Optional) You point it at one or more GitHub repos.
  3. You run three commands. The bot pulls everything together, asks Claude to draft cards that match your meeting's prompt columns, lets you review them, and submits them to the meeting.

Each card is short (1–3 sentences), tagged 🤖 so attendees know it's automated, and links to its source (a PR, an issue, etc.) when there's an honest URL to point at.


Your first run (5 minutes)

1. Install

git clone <this-repo> retro-reflect-bot
cd retro-reflect-bot
pnpm install
cp .env.example .env

Open .env and fill in two values:

  • PARABOL_PAT — a Parabol Personal Access Token with the MEETINGS_WRITE scope (find PAT settings in your Parabol account)
  • ANTHROPIC_API_KEY — your Claude API key from console.anthropic.com

2. Verify

pnpm cli doctor

You should see green checks for environment variables and the Parabol API. The gh CLI checks may show as warnings — that's fine unless you want to use --github.

3. Drop in some notes

mkdir -p inputs
cat > inputs/sprint-23.md <<'EOF'
# Sprint 23 notes

- Three production outages, all caused by a race condition in the billing
  worker. We finally fixed it on Wednesday with a transaction.
- The new onboarding flow shipped! Activation rate is up ~12% week-over-week.
- Code review felt slow. Two PRs sat for >3 days each.
EOF

4. The three commands

# Find your retro's URL — something like https://action.parabol.co/meet/m-12345
RETRO_URL="https://action.parabol.co/meet/m-12345"

pnpm cli gather "$RETRO_URL"
pnpm cli generate
pnpm cli submit

You'll see:

  • gather resolve the meeting, list its prompt columns, walk inputs/, and write a run state directory under out/.
  • generate ask Claude to draft cards (Pass 1), then review them for redundancy (Pass 2), then print them grouped by column.
  • submit ask Submit N cards to "Sprint 23 Retro"? [y/N] — type y, and the cards appear in the meeting.

That's it. Stop reading here unless you want to bring in GitHub activity or customize anything.


Bringing in GitHub activity

If your team works in GitHub, the bot can survey one or more repos for the same time period:

pnpm cli gather "$RETRO_URL" \
  --since "8 weeks ago" \
  --github your-org/your-repo \
  --github your-org/your-other-repo
pnpm cli generate
pnpm cli submit

This spins up a Claude agent that calls gh (read-only) to look at merged PRs, open PRs touched in the window, issues + comments, and releases. The agent decides what's worth drilling into; you'll see verbose progress like:

[github] iter 1: gh search prs --repo your-org/your-repo --merged ">=2026-03-11" --json number,title,url,mergedAt
[github]   ← 3,140 bytes
[github] iter 2: gh pr view 1842 --repo your-org/your-repo --comments
[github]   ← 8,927 bytes

To use this, install the GitHub CLI and authenticate it:

gh auth login

Important: when prompted, choose "Login with a web browser". SAML-enforced GitHub orgs typically reject classic Personal Access Tokens (ghp_*). The browser flow uses GitHub CLI's bundled OAuth App (gho_* token), which is accepted by virtually all org policies. pnpm cli doctor will warn you if your auth is using a classic PAT.


Editing between steps

The three commands share state under out/<run-id>/:

out/2026-05-06-143015/
├── meta.json              # written by gather
├── context.json           # written by gather
├── cards.json             # written by generate
└── submission-log.json    # written by submit

Want to drop a card you don't agree with? Open out/<run-id>/cards.json, delete it, save, then run submit. Same for context.json between gather and generate if you want to thin the corpus before the LLM sees it.

Each run is independent. gather mints a new run id; generate and submit default to the latest. Pass --run <id> if you want to act on a specific older run.


Common workflows

Just preview, don't submit:

pnpm cli submit --dry-run

Renders the cards and exits without touching Parabol.

Run from CI (no prompts):

pnpm cli submit --yes

Skips the interactive confirmation. Exit code is non-zero if any card failed to submit.

Different time window:

pnpm cli gather "$RETRO_URL" --since "2026-03-01" --until "2026-03-15"

--since and --until accept ISO dates (2026-03-01), compact durations (14d, 2w, 1m), or natural language ("last sprint", "8 weeks ago").

Save tokens with a smaller model:

pnpm cli generate --model claude-sonnet-4-6

The default is claude-opus-4-7, which produces the highest-quality cards but costs more per run. Sonnet is a good fallback when context is sparse or you're iterating.

Demo / redact proprietary content:

pnpm cli generate --amend-prompt "Redact proprietary information: replace account names, customer names, internal codenames, and trade secrets with bracketed placeholders like [CLIENT-A] or [PROJECT-X]. Be creative — preserve the shape of each observation but strip identifying detail."

--amend-prompt appends additional instructions to the system prompt for both the draft and critique passes, so redaction is applied uniformly. Useful when sharing the bot's output publicly (e.g., demos, screenshots, conference talks) without exposing your team's data. The amendment is not persisted to cards.json's metadata — re-runs require passing it again.

Skip the critique pass:

pnpm cli generate --skip-critique

Reduces generate to one LLM call. Useful when context is sparse and the critique pass would add latency without much benefit.


Reference

Commands

Command Purpose
doctor Verify env, PAT, optional gh install + auth
inspect <meeting-url> Print the meeting's prompt columns
gather <meeting-url> Run all data sources, write out/<run-id>/{meta,context}.json
generate Draft + critique cards via Claude, write cards.json
submit Render, confirm, submit each card via createReflection
revert Remove reflections from the meeting (by run, by content, or all)

gather flags

Flag Default Description
--inputs-dir <path> ./inputs Directory of input documents (.md, .txt, .json)
--since <when> 2 weeks ago Time window start
--until <when> now Time window end
--github <owner/repo> Survey a GitHub repo (repeatable for multi-repo)
--github-prompt <text> default Override the GitHub agent's mission
--model <name> claude-opus-4-7 Claude model id (used by GitHub agent)
--out-dir <path> ./out Run state directory

generate flags

Flag Default Description
--run <id> latest Run to operate on
--out-dir <path> ./out Run state directory
--model <name> claude-opus-4-7 Model id
--skip-critique off Skip the critique pass (one LLM call instead of two)
--amend-prompt <text> Extra instructions appended to the system prompt for both passes (e.g. redaction)

revert flags

Flag Default Description
--run <id> latest Run whose meeting to operate on (and, in default mode, whose submission-log scopes the deletion)
--out-dir <path> ./out Run state directory
--all off Remove every reflection in the meeting
--substring [text] — / retro-reflect-bot if bare Remove every reflection in the meeting whose plaintext content contains <text>
--yes off Skip the interactive confirm

--all and --substring are mutually exclusive. Without either, revert reads submission-log.json and removes only the reflections submitted in the named run — useful for "undo my last submit." --substring (bare) defaults to the bot's tag (retro-reflect-bot), which is handy when run state is gone but you want to clear only bot-generated cards.

# Undo the most recent submit
pnpm cli revert

# Remove anything the bot ever wrote in this meeting
pnpm cli revert --substring

# Remove every reflection (yours and others) — confirms first
pnpm cli revert --all

revert requires the meeting to still be in the Reflect or Group phase (Parabol's API rejects removals after the group phase ends).

submit flags

Flag Default Description
--run <id> latest Run to submit
--out-dir <path> ./out Run state directory
--dry-run off Render the cards and exit
--yes off Skip the interactive confirm

Card format

Cards use a small subset of markdown for inline rich formatting. The bot writes:

  • [anchor text](https://...) — inline links to PRs, issues, documents, etc. Used liberally for source-of-truth references.
  • **bold**, *italic*, `code` — emphasis where it helps readability.

The submitted card looks like this in the meeting (rendered):

Three production outages this sprint, all rooted in the billing-worker race condition. Fixed in PR #1842.

🤖 retro-reflect-bot

The 🤖 line is how attendees can tell at a glance which cards are bot-generated.

Environment variables

Variable Default Description
PARABOL_PAT Parabol PAT, must include MEETINGS_WRITE scope
ANTHROPIC_API_KEY Claude API key
PARABOL_BASE_URL https://action.parabol.co Override for self-hosted or staging

Troubleshooting

Parabol API rejected your PAT (HTTP 401/403) Your PAT is missing, expired, or doesn't include the MEETINGS_WRITE scope. Re-mint it in Parabol and update .env.

Meeting m-XXX Reflect phase is complete The bot only adds cards while the meeting is in the Reflect phase. Move the meeting back to Reflect (or run on a different meeting).

No runs found in ./out You need to run gather first. Each subsequent command (generate, submit) defaults to the latest run.

<Org> blocks classic Personal Access Tokens Your gh is authed with a classic PAT (ghp_*) and the org enforces SAML. Run gh auth logout && gh auth login and choose "Login with a web browser". If pnpm cli doctor still shows OAuth (gho_*) but you're hitting this error, check env | grep -E '^(GITHUB|GH)_TOKEN' — an environment variable with a classic PAT will override the stored OAuth credential. unset GITHUB_TOKEN GH_TOKEN for the session.

Model response hit max_tokens (8192) and was truncated Your gathered context produced more cards than fit in one Claude response. Narrow --since, thin inputs/, or pass --model claude-sonnet-4-6 for a more concise output.

Gathered NNN,NNN characters of content (> 200,000 soft limit) Informational. Generation will work but be slower and more expensive, and is more likely to hit max_tokens. Narrow --since or thin inputs/ if you want.

Long-running GitHub gather The agent can take a few minutes for active repos. If a single run goes longer than ~5 minutes, narrow --since or run with --github-prompt "<focused mission>".

Cards too long / truncated in the meeting Cards are capped at 2000 characters of stringified TipTap content. The bot shortens overflowing prose with an ellipsis and warns. If this happens often, lower the model output via --model claude-sonnet-4-6.


Architecture

If you want to understand or extend the code, the design spec lives at docs/superpowers/specs/2026-05-06-retro-reflect-bot-design.md. Per-sprint implementation plans are in docs/superpowers/plans/.

The short version: three commands sharing state on disk; a DataSource interface (files + GitHub today, anything else tomorrow); a two-pass LLM pipeline (draft → critique); the GitHub source is itself a Claude agent that calls gh as a sandboxed tool.


License

MIT.

About

An AI-driven bot to populate Parabol meeting activities with automated observations from your team's work

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages