Open it at Apps → UndoTrail, or from a project’s sidebar for a single project.
How a report is built
A report happens in two stages, and it helps to know which is which.
| Stage | What happens | Cost |
|---|---|---|
| Load | The app asks Jira which work items match your scope, then reads their change history | One or more calls to Jira; press Run to start, Cancel to stop |
| Refine | Every filter under the results narrows what has already been loaded | Instant, no calls to Jira |
So changing a project, the JQL or the dates needs another Run, because the dates decide which work items Jira sends back. Changing Changed by, Changed by group, Field, Search, a transition filter or an exclusion does not.
Loading is done in batches, in your browser, under your own Jira permissions: work items are found 1,000 at a time, then their history is read 1,000 work items per changelog call. That is why a large report shows a rising count rather than a spinner. Cancel stops the load as soon as the current request to Jira returns. If Jira asks the app to slow down, it waits for the time Jira asks for (at most a minute per wait) and carries on, up to six attempts, and says so on screen.
Scope: which work items to load
The scope panel is at the top. More options reveals the rest.
| Control | Notes |
|---|---|
| Projects | The first choice: pick one or more projects, each shown as a chip with its own ×. Empty means All projects, and All projects in the list goes back to that. The explorer opens on the projects you last used (remembered in this browser); a share link’s projects win. On a project page this is fixed to that project. |
| Dates | Preset or custom range (see below) |
| Max work items | 1,000, 5,000 (the default), 10,000 or 25,000. If more match, the report says so and suggests narrowing. |
| Work item keys | Type or paste keys, separated by commas, spaces or new lines, for example OPS-1, OPS-2. Keys are upper-cased for you. An entry that isn’t a key (ASDFASF, or a typo like OPS 4) is named under the box, and so is a key that matches no work item you can see; Run waits until they’re fixed |
| Saved filter | Any Jira saved filter you can see |
| Sprints | Loaded when you open More options, from up to 10 boards (50 sprints each) for the project page’s project or the first selected project. Closed sprints are marked (closed). Empty on sites without Jira Software. |
| JQL (combined with everything above) | Joined to everything above using AND. Validated as you type. |
Everything you choose is compiled into one JQL query, shown next to the Run button so you can check it or copy it into Jira’s own search. For example:
project in ("OPS") AND key in (OPS-1, OPS-2) AND updated >= "2026-09-01" AND updated <= "2026-09-30 23:59" AND (issuetype = Bug) ORDER BY updated DESC
If nothing at all narrows the search (no scope, and a custom date range with both dates empty), the app falls back to updated >= -30d. Any ORDER BY in your own JQL is stripped, because the app sets its own.
JQL validation
JQL is checked against Jira’s own parser (strict validation) just over half a second after you stop typing. Jira’s error message is shown under the box, and Run stays disabled until the query parses. If the check itself cannot run, the app lets you press Run anyway and Jira reports the problem when the search executes.
Dates
| Preset | Meaning |
|---|---|
| Today, Yesterday | Whole local days |
| This week, Last week | ISO weeks, Monday to Sunday |
| This month, Last month | Whole calendar months |
| Last 7 / 30 / 90 days | Counting back from today, inclusive |
| Custom range | Two dates, inclusive, either one optional |
Ranges are whole days in your browser’s time zone: the first day starts at 00:00:00.000 and the last day ends at 23:59:59.999. A range that spans a daylight-saving change can be out by the offset difference at one end, because one fixed offset is used for the whole range.
The date range does two jobs. It narrows which work items are fetched, because updated >= and updated <= clauses are added to the JQL, and it filters which changes are shown. A work item changed inside the range has always been updated since, so nothing in range is missed.
Activity view and table view
Switch with the Activity / Table control above the results.
Activity shows one row per field change: When, Work item, Field, From, To, By. It is the view for reading what happened.
Table shows one row per change moment, with fields as columns. If someone changed three fields in one edit, that is one row with three filled cells. Where one edit both added and removed values of the same field, the cell shows the removed values on the left and the added values on the right. Each field column keeps a readable width, so a report with many fields scrolls sideways rather than squeezing values onto several lines; the When, Work item and Updated by columns stay frozen while you scroll.
Both views show 50 rows per page. The activity view has First, Prev, Next and Last buttons plus a Go to page box. The table view has Prev and Next, and counts its rows as change moments.
In the activity view:
- Click a person’s name to show only their changes. Click it again to show everyone.
- Press the ⟷ button beside a change to step through that field’s history on that work item, one change at a time, with a before-and-after word diff. The arrow keys move between changes and Esc closes it.
- Hover over a work item key for a preview of the item.
Column manager (table view)
Press Columns (n of m) above the table.
- Every field that appears in the loaded history is listed, with the number of rows that have a value in that column.
- Columns are ordered by how often the field changed, so the busy fields come first.
- Select all and Select none sit at the top of the list.
- With many columns, Jump to column takes you straight to one.
- The choice is part of the report, so it is saved with a view and travels in a share link.
Sorting
In the activity view, click a column heading to sort.
- The first click sorts the way the column reads: When newest first, text columns (work item, field, values, person) A to Z. The second click reverses it, and the third removes that sort.
- Shift-click a second heading to add it as a secondary sort. A saved view or share link keeps up to five sort keys.
- Work item keys sort naturally, so
OPS-9comes beforeOPS-10. - The default sort is newest change first.
Grouping
Tick Group by work item in the activity view. Rows are gathered under a heading per work item showing its key, summary and number of changes in the report. Ticking it also switches the sort to work item ascending, then newest change first.
Badges
| Badge | Meaning |
|---|---|
| Created | A synthetic row marking when the work item was created. Jira’s change history has no entry for creation, so the app adds one from the created field, attributed to the reporter. |
| Latest | The most recent change to that field on that work item within the report’s date range. If one edit changed several values of the same field, all of them are marked. |
| New | The work item itself was created inside the report’s date range. |
| BULK | One person or automation changed the same field on at least 5 different work items within 10 seconds of the first of those changes. Created rows are never marked BULK. |
BULK is how automation runs and Jira bulk edits stand out. Tick Bulk changes only to see nothing else, and see Revert for undoing one.
Diffs
Some changes are shown as a word-level difference rather than as two values:
- Summary, Description, Environment, any field whose name contains “comment”, and long custom text fields (over 30 characters, and not purely numeric or a date).
- Only when there is both an old and a new value. A value set from empty, or cleared, is shown as old → new.
- The text is shown once, across the From and To columns: unchanged words as they are, removed words struck through, added words marked, in place. Screen readers hear “removed” and “added” before each.
- Text longer than about 200 characters is cut to the changed parts, with a few words either side and … for the unchanged text between. Show full text opens the whole diff, and Show changes only folds it again. Exports always carry both full values.
List fields (labels, components, fix versions, affects versions, Sprint, watchers) are shown as chips. Values that stayed are plain, removed values are marked on the left, added values are marked on the right.
Time-tracking fields (original estimate, remaining estimate, time spent and their totals) are shown as durations with the difference, for example 30m → 2h (+1h 30m), in the time format an administrator sets on the admin page.
Everything else is shown as old → new, with a dash where there was no value.
Jira’s change history stores plain text for rich-text fields, so a description diff shows the words that changed, not the formatting.
Refine filters
These sit between the saved-view bar and the results, and apply instantly. All of them combine: a change must pass every filter you set.
| Filter | Behaviour |
|---|---|
| Changed by | One or more people, with counts. A Me shortcut selects you. |
| Changed by group | Changes by members of one or more Jira groups. Type in Find a group to narrow the list; up to 20 groups |
| Field | One or more fields, with counts |
| Search | Free text over key, summary, field name, old value, new value and author |
| Bulk changes only | Keeps only rows marked BULK |
| Transitions (any field) | See below |
| Exclude… | Opens the NOT filters |
An empty list means no filter, and says All. Once you’ve picked something, a Clear button beside the list removes every choice at once; each chip also has its own ×.
Group membership is looked up by the app, because reading it needs a Jira permission most people do not have. Only account IDs come back, and they are only used to keep or drop changes already on your screen. A group of more than 5,000 members cannot be read in full, and the app says so rather than quietly narrowing the report.
NOT filters
Press Exclude… to reveal three exclusions (press Hide exclusions to fold them away again):
- Not changed by: one or more people. The Me shortcut works here too.
- Not these fields: one or more fields.
- Text to exclude: a row is dropped if any of these words appears anywhere in it.
An empty exclusion list says None: nothing is excluded. Remove exclusions one at a time with each chip’s ×.
Exclusions are saved with a view and carried in a share link.
Transition filters, on any field
Press + Add transition. Each filter has a field (or Any field) and a pattern.
| You type | It matches |
|---|---|
In Progress → Done |
Changes from exactly “In Progress” to exactly “Done” |
→ Done |
Any change into “Done” |
In Progress → |
Any change out of “In Progress” |
* → Done |
The same as → Done; * means “any” |
~prog → ~done |
~text matches any value containing that text |
In Progress -> Done |
-> works the same as → |
Matching ignores case. This is not limited to status: choose any field in the dropdown, or leave it on Any field to match a value change anywhere. Add several transition filters and a row is kept if it matches any of them, for example → Done or → Closed.
If a pattern has no arrow, the app says so under the box and shows the forms it accepts.
Search and match counts
When the search box has text, the number of matching changes is shown beside it and the matching words are highlighted in keys, summaries, field names, people and plain values. Word diffs, list chips and durations are not highlighted. Quoted phrases stay together, so "in progress" bug needs both the phrase and the word. Every term must appear somewhere in the row for it to be kept.
Field names
Fields are named the way Jira’s own screens name them: Status, Assignee, Remaining Estimate, and your site’s current name for each custom field, even where Jira’s history records an internal id such as status or timeestimate. The filters, the table, transitions and exports all use these names; exports also keep the id in a Field ID column. Searching for an id (for example timeestimate) still finds the field’s changes.
Changes that didn’t change anything
Jira records a change even when the old and new value are the same, for example a transition to the status a work item was already in (Backlog → Backlog), often made by a bulk edit or an automation rule. There is nothing to see or undo in them, so they are hidden and left out of every count. A line under the summary says how many were hidden, with an example, and Show them brings them back, marked No change and without a revert tick box. Hide them puts them away again. The choice is saved with a view and carried in a share link, and exports follow what is on screen.
Reading the summary line
Above the results: 1,234 changes across 56 work items, counting the changes on screen after filtering and the work items they belong to. When filters leave some loaded work items with nothing to show, the line says so: 8 changes across 7 of 22 work items. Screen readers hear the same line when the report loads and again whenever a filter changes it. If the JQL matched more work items than the Max work items setting, a warning is added saying where the load stopped, for example Stopped at 5,000 work items, so a truncated report is never mistaken for a complete one.
A load also stops at 150,000 changes, which is as much as a browser tab can work with comfortably. The report says so when it does.
When a report is empty
Instead of a blank screen, the app says which stage removed everything, using the counts collected while loading. For example:
- No work items match your JQL, with your JQL repeated, a reminder that you only see projects you can browse, and advice to remove clauses one at a time.
- No changes in the chosen period (for example No changes in the last 30 days), with the number of changes that do exist outside the range.
- The Changed by filter removed all 431 changes, naming the filter that emptied the report, how many rows reached it, and which later filters may also need loosening.
The Reports tab
The Reports tab turns the same scope and dates into three summaries. Set the scope on the Changes tab, then open Reports and press Run report.
| Report | What it shows |
|---|---|
| Time in value | For one field (Status by default): the total and average time spent in each value, then a row per work item and value with the time and how many times it was entered. Time runs from each change to the next; the value held now runs to the end of the date range. The stretch before the first loaded change is not counted, because creation is not a change |
| Change counts | Changes by field (with work items and people), by author, and by work item. The screen shows the top 50 work items; the export has them all |
| Status over time | For one field: how many work items held each value at the end of each day, rebuilt backwards from each item’s most recent loaded change, as a stacked chart. Ranges longer than 120 days are grouped by week |
Durations use the time format an administrator sets on the admin page. The Time in value detail table shows the first 500 rows on screen; the export has them all. The chart can be saved with Download SVG or Download PNG. Exports from this tab are described in Exports.
The Reports tab needs an active subscription.
Limitations
- Reports read Jira’s change history. Jira does not record everything: comment text, worklog detail and some app-managed fields never appear in the changelog. Comment edits are covered separately by comment history.
- History is only available for work items you can browse in Jira. A report is always a view through your own permissions, never more.
- Rich-text history is plain text, so diffs cannot show formatting changes.
- Loading stops at the Max work items figure you chose, up to 25,000, or at 150,000 changes. The report says when it did.
- Date ranges use one fixed UTC offset, so a range crossing a daylight-saving change can be out by that offset at one end.
- The Reports and Security scanner tabs load their own copy of the history, so Run report and Run scan there are separate loads from the Changes tab.
- Selecting rows to revert works in the activity view, not the table view.
- Status over time counts only work items whose field changed in the loaded history, because a value that never changed cannot be placed on a date from the changes alone.