Skip to content

Instantly share code, notes, and snippets.

@quiiver
Created March 19, 2026 21:54
Show Gist options
  • Select an option

  • Save quiiver/825f6026e825918498053be20fe397c3 to your computer and use it in GitHub Desktop.

Select an option

Save quiiver/825f6026e825918498053be20fe397c3 to your computer and use it in GitHub Desktop.
Claude Code /okr-update skill — weekly OKR status update for Jira

Generate a weekly OKR status update for a given Objective or Key Result ticket and post it as a comment.

Usage: /okr-update <TICKET-KEY> (e.g., /okr-update INFOKR-7)

Instructions

  1. Resolve the target ticket: Fetch the provided ticket using the Atlassian MCP getJiraIssue tool. Include the issuelinks field.

    • Atlassian cloud ID: d8febd08-c6e9-4c03-9c13-db37c2369ce5
  2. Find fulfilling epics: From the ticket's issue links, find all issues linked via the "Fulfills" relationship (inward: "is fulfilled by"). These are the epics that deliver on this OKR.

  3. Gather ticket data: For each fulfilling epic, query Jira for child issues that have been updated or created in the last 7 days:

    • Use JQL: parent = <EPIC-KEY> AND (status changed AFTER -7d OR created >= -7d) ORDER BY status ASC, updated DESC
    • Fetch summary, status, and updated fields
    • If there are multiple fulfilling epics, aggregate results across all of them
  4. Read the previous update: Fetch the latest comment on the target ticket to understand what was previously reported and maintain continuity.

  5. Synthesize tickets into themes: Group the raw ticket data into 2–4 meaningful themes or capability areas (e.g. "Helm chart standardization", "Observability", "On-prem readiness"). Do not list tickets one-by-one — synthesize them into outcomes.

  6. Determine status: Ask the user whether the OKR is:

    • ON TRACK (green)
    • AT RISK (yellow)
    • OFF TRACK (red)
  7. Draft the update for a VP or executive audience. Write at a strategic altitude — focus on outcomes, milestone progress, and risk, not individual task completion. Each theme bullet has a narrative summary followed by a sub-bullet list of the supporting ticket links. Each section should have 2–4 theme bullets max.

**Status**: <STATUS TEXT>

**Accomplished:**
- **<Theme or outcome>** — <1-2 sentence description of what was achieved and why it matters>
  - Ticket summary - [TICKET-KEY](link)
  - Ticket summary - [TICKET-KEY](link)

**In Flight:**
- **<Theme or capability area>** — <what is being worked on and what it unblocks>
  - Ticket summary - [TICKET-KEY](link)
  - Ticket summary - [TICKET-KEY](link)

**Upcoming / At Risk:**
- **<Theme or risk>** — <what's next or what's blocking progress, and the impact if delayed>
  - Ticket summary - [TICKET-KEY](link)
  1. Iterate with the user until they approve the content.

  2. Post the comment to the target ticket using the Atlassian MCP addCommentToJiraIssue tool with contentFormat: adf. The commentBody must be a JSON string containing the ADF document.

ADF Format

The comment must be posted as ADF (Atlassian Document Format) JSON to support native Jira status lozenges. Use this structure:

Status lozenge colors

  • ON TRACK: "color": "green"
  • AT RISK: "color": "yellow"
  • OFF TRACK: "color": "red"

Reference ADF structure

{
  "type": "doc",
  "version": 1,
  "content": [
    {
      "type": "paragraph",
      "content": [
        {"type": "text", "text": "Status", "marks": [{"type": "strong"}]},
        {"type": "text", "text": ": "},
        {"type": "status", "attrs": {"text": "AT RISK", "color": "yellow", "localId": "", "style": ""}},
        {"type": "text", "text": " "}
      ]
    },
    {
      "type": "paragraph",
      "content": [
        {"type": "text", "text": "Accomplished:", "marks": [{"type": "strong"}]}
      ]
    },
    {
      "type": "bulletList",
      "content": [
        {
          "type": "listItem",
          "content": [
            {
              "type": "paragraph",
              "content": [
                {"type": "text", "text": "Theme title", "marks": [{"type": "strong"}]},
                {"type": "text", "text": " — narrative summary sentence describing outcome and why it matters."}
              ]
            },
            {
              "type": "bulletList",
              "content": [
                {
                  "type": "listItem",
                  "content": [
                    {
                      "type": "paragraph",
                      "content": [
                        {"type": "text", "text": "Ticket summary - "},
                        {"type": "text", "text": "MZCLD-1234", "marks": [{"type": "link", "attrs": {"href": "https://mozilla-hub.atlassian.net/browse/MZCLD-1234"}}]}
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "type": "paragraph",
      "content": [
        {"type": "text", "text": "In Flight:", "marks": [{"type": "strong"}]}
      ]
    },
    {
      "type": "bulletList",
      "content": []
    },
    {
      "type": "paragraph",
      "content": [
        {"type": "text", "text": "Upcoming:", "marks": [{"type": "strong"}]}
      ]
    },
    {
      "type": "bulletList",
      "content": []
    }
  ]
}

Key ADF patterns

  • Bold text: {"type": "text", "text": "...", "marks": [{"type": "strong"}]}
  • Link: {"type": "text", "text": "TICKET-KEY", "marks": [{"type": "link", "attrs": {"href": "https://mozilla-hub.atlassian.net/browse/TICKET-KEY"}}]}
  • Status lozenge: {"type": "status", "attrs": {"text": "STATUS", "color": "green|yellow|red", "localId": "", "style": ""}}
  • Section header: paragraph node with bold text
  • Theme bullet with sub-bullets: bulletList > listItem > [paragraph (theme narrative), bulletList (ticket links)] nodes
  • Ticket sub-bullet: summary text followed by - and the ticket link (no checkmarks)

Key details

  • Atlassian cloud ID: d8febd08-c6e9-4c03-9c13-db37c2369ce5
  • Comment field name: commentBody (not body)
  • Content format: adf (not markdown)
  • Link type to follow: "Fulfills" (outward) / "is fulfilled by" (inward)
  • The commentBody value must be a JSON string of the ADF document
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment