Counts your Jira tickets by status every morning and posts the breakdown to Slack, with a short read on what stands out.
Uses
ClaudeJira
Slack
Daily Jira status report to Slack
Every morning at 08:30, your Jira tickets are counted by status category, To Do, In Progress and Done, broken down by the status names your project uses and by assignee, and the breakdown is posted as one Slack message. Done covers a recent window rather than all time, so it says something about this morning.
You get one message with the counts and, when there is something worth saying, up to three lines on what stands out, such as work piling up in one column or a queue concentrated on one person. Every number is counted by paging through Jira rather than taken from a first page, and a count that hit the paging ceiling is marked as a floor, not passed off as a total. The AI only comments on the finished figures, never produces one, and if that comment fails the report still goes out with its numbers intact.
Before the first run you need a Slack channel to post to. It can cover every project your Jira connection can see or be scoped to one board.
slackChannelId to blank.Set slackChannelId to blank.jiraProjectKey to blank.Set jiraProjectKey to blank.doneLookbackDays to 7.Set doneLookbackDays to 7.maxPagesPerStatus to 10.Set maxPagesPerStatus to 10.assigneeLimit to 10.Set assigneeLimit to 10.reportTitle to Daily Jira status report.Set reportTitle to Daily Jira status report.pageSize to 100.Set pageSize to 100.projectFilter to blank.Set projectFilter to blank.projectLabel to all visible projects.Set projectLabel to all visible projects.jiraProjectKey isn't emptyIf jiraProjectKey isn't emptyprojectFilter to project = jiraProjectKey AND .Change projectFilter to project = jiraProjectKey AND .projectLabel to jiraProjectKey.Change projectLabel to jiraProjectKey.doneWindow to -doneLookbackDaysd.Set doneWindow to -doneLookbackDaysd.reportDate.Make today's date readable as “November 2, 2026” and save it as reportDate.todoJql to projectFilterstatusCategory = To Do ORDER BY updated DESC.Set todoJql to projectFilterstatusCategory = To Do ORDER BY updated DESC.todoIssues to an empty list.Set todoIssues to an empty list.todoToken to blank.Set todoToken to blank.todoPages to 0.Set todoPages to 0.todoMore to true.Set todoMore to true.todoMore is yes and todoPages is less than maxPagesPerStatus:While todoMore is yes and todoPages is less than maxPagesPerStatus:todoJql. Save it as todoPage.Find issues matching todoJql. Save it as todoPage.todoIssues and todoPage.issues into one list and save it as todoIssues.Combine todoIssues and todoPage.issues into one list and save it as todoIssues.todoPages.Add 1 to todoPages.todoNextToken to todoPage.next_page_token.Set todoNextToken to todoPage.next_page_token.todoNextToken is emptyIf todoNextToken is emptytodoMore to false.Change todoMore to false.todoToken to todoNextToken.Change todoToken to todoNextToken.todoTruncated to todoMore.Set todoTruncated to todoMore.inProgressJql to projectFilterstatusCategory = In Progress ORDER BY updated DESC.Set inProgressJql to projectFilterstatusCategory = In Progress ORDER BY updated DESC.inProgressIssues to an empty list.Set inProgressIssues to an empty list.inProgressToken to blank.Set inProgressToken to blank.inProgressPages to 0.Set inProgressPages to 0.inProgressMore to true.Set inProgressMore to true.inProgressMore is yes and inProgressPages is less than maxPagesPerStatus:While inProgressMore is yes and inProgressPages is less than maxPagesPerStatus:inProgressJql. Save it as inProgressPage.Find issues matching inProgressJql. Save it as inProgressPage.inProgressIssues and inProgressPage.issues into one list and save it as inProgressIssues.Combine inProgressIssues and inProgressPage.issues into one list and save it as inProgressIssues.inProgressPages.Add 1 to inProgressPages.inProgressNextToken to inProgressPage.next_page_token.Set inProgressNextToken to inProgressPage.next_page_token.inProgressNextToken is emptyIf inProgressNextToken is emptyinProgressMore to false.Change inProgressMore to false.inProgressToken to inProgressNextToken.Change inProgressToken to inProgressNextToken.inProgressTruncated to inProgressMore.Set inProgressTruncated to inProgressMore.doneJql to projectFilterstatusCategory = Done ORDER BY updated DESC.Set doneJql to projectFilterstatusCategory = Done ORDER BY updated DESC.doneLookbackDays is greater than 0If doneLookbackDays is greater than 0doneJql to projectFilterstatusCategory = Done AND (resolved >= doneWindow OR (resolved IS EMPTY AND updated >= doneWindow)) ORDER BY updated DESC.Change doneJql to projectFilterstatusCategory = Done AND (resolved >= doneWindow OR (resolved IS EMPTY AND updated >= doneWindow)) ORDER BY updated DESC.doneIssues to an empty list.Set doneIssues to an empty list.doneToken to blank.Set doneToken to blank.donePages to 0.Set donePages to 0.doneMore to true.Set doneMore to true.doneMore is yes and donePages is less than maxPagesPerStatus:While doneMore is yes and donePages is less than maxPagesPerStatus:doneJql. Save it as donePage.Find issues matching doneJql. Save it as donePage.doneIssues and donePage.issues into one list and save it as doneIssues.Combine doneIssues and donePage.issues into one list and save it as doneIssues.donePages.Add 1 to donePages.doneNextToken to donePage.next_page_token.Set doneNextToken to donePage.next_page_token.doneNextToken is emptyIf doneNextToken is emptydoneMore to false.Change doneMore to false.doneToken to doneNextToken.Change doneToken to doneNextToken.doneTruncated to doneMore.Set doneTruncated to doneMore.todoIssues, inProgressIssues, doneIssues, todoTruncated, inProgressTruncated, doneTruncated, doneLookbackDays, assigneeLimit, pageBudget, projectLabel, reportDate, and reportTitle and save it as counts.Run Python code on todoIssues, inProgressIssues, doneIssues, todoTruncated, inProgressTruncated, doneTruncated, doneLookbackDays, assigneeLimit, pageBudget, projectLabel, reportDate, and reportTitle and save it as counts.aiRead to blank.Set aiRead to blank.aiErrorIf a step below fails, save the error as aiErrorwhat stands out note at the bottom of a team's daily Jira status report.Ask Claude: 'You are writing the short what stands out note at the bottom of a team's daily Jira status report.
The figures below were counted from Jira, they are correct, and the report already prints them. Your job is only to say what they mean.
Rules:
- Never repeat a number the report already shows, and never state a number that is not in the facts below. Do not do arithmetic of your own: express a ratio in words (roughly three times, about half) rather than a figure you worked out.
- Comment on shape, not size: where work is piling up, a status that is unusually crowded, work concentrated on one person, an empty in-progress column, a backlog growing while nothing finishes.
- At most three bullets, one line each, plain Slack-friendly text. No heading, no preamble, no sign-off.
- A quiet day is a real answer. If nothing here is worth a team's attention, reply with exactly NOTHING_NOTABLE and nothing else.
Today's figures:
counts.facts'. Save it as analysis.
Maximum response length: 500analysis.response_text and save it as verdict.Trim analysis.response_text and save it as verdict.verdict isn't empty and verdict doesn't start with NOTHING_NOTABLE (ignoring…If verdict isn't empty and verdict doesn't start with NOTHING_NOTABLE (ignoring…aiRead to verdict.Change aiRead to verdict.aiError.message.Show in the output: Posting the counts without a written read: aiError.message.slackText to counts.report.Set slackText to counts.report.aiRead isn't emptyIf aiRead isn't emptyslackText to counts.reportChange slackText to counts.report
*What stands out*
aiRead.slackChannelId. Save it as posted.Send a message to slackChannelId. Save it as posted.slackTextposted.Show in the output: posted.