performa

Version 2.6.5

performa — User Manual

English · Deutsch

performa is a small desktop app (macOS + Windows) for logging your work hours on Jira Cloud issues — with a timer, a weekly timesheet, reminders for forgotten worklogs, and a dashboard.

Contents

What is performa?

performa talks directly to your Jira Cloud site and writes native Jira worklogs. Because the entries land in Jira itself, they automatically appear in every tool that reflects Jira worklogs — including ActivityTimeline.

Two design principles worth knowing:

  • Your API token never touches the web layer. All Jira communication happens in the app's native (Rust) core; the token is stored in the operating system's credential store (macOS Keychain / Windows Credential Manager), not in a config file.
  • Billable by default. A worklog marked non-billable is stored with a leading ~ in its Jira comment — the ActivityTimeline convention — so the categorization survives round trips through Jira.

Getting started

Installation

Download the latest release from the project's GitHub Releases page:

  • macOS: .dmg (Apple Silicon)
  • Windows: .exe installer

Connecting to Jira

On first launch performa shows the connect screen. You need three things:

Field What to enter
Jira site Your Jira Cloud host, e.g. your-team.atlassian.net (with or without https://)
Email The email address of your Atlassian account
API token A personal Atlassian API token

Click Create an API token ↗ on the connect screen (or go to id.atlassian.com/manage-profile/security/api-tokens), create a token, and paste it into the field.

When you press Connect, performa verifies the credentials against Jira before saving them — a typo in the site or token produces an error message instead of a broken setup. On success the token is written to the OS keychain and the main window opens.

If the app ever fails to read the keychain at startup, it shows the error with a Retry button instead of getting stuck on "Loading…".

The interface at a glance

The main window consists of:

  • Header — the performa mark, your account email, a Settings link, and Sign out (asks for confirmation; signing out removes the token from the keychain).
  • Update banner — appears only when a newer release exists (Updates).
  • Timer bar — appears only while a timer is running (The timer).
  • Six tabs: Start, Todo, Log work, Timesheet, Missing worklog, Mentions. The app opens on Start.

Keyboard

Nearly everything in performa has a key. You do not have to learn them: hold ⌘ (Ctrl on Windows) and every action within reach names its own, as a small badge at the corner of its button. Let go and they are gone.

A badge drawn dimmed is a key that is real but will not fire this second — see When a key does nothing.

The shortcuts are written here with ⌘. On Windows, read Ctrl for every one of them; the keys themselves are the same.

Moving between views

⌘1 … ⌘6 the six tabs, in the order the sidebar lists them
⌘, Settings
⌘P the command palette
⌘R refresh whatever list you are on

Going back

Every screen with a Back control can also be left without aiming at it:

  • Escape, or ⌘[ / ⌘← (Alt+← on Windows).
  • Your mouse's back button, if it has one.
  • A two-finger swipe to the right on a trackpad.

All of them do the same one thing the Back control does: step out of exactly where you are. An open transition screen closes before the issue underneath it is left, and a trail of linked issues is walked back one at a time.

Forward goes the other way — the mouse's forward button, ⌘] / ⌘→ (Alt+→), or a swipe to the left. It re-enters what you just stepped out of, and only that: navigating anywhere else gives up the way forward.

If your mouse's back button appears to do nothing, look at its driver software. Logitech's Options+ and its equivalents take the thumb buttons over and send a swipe gesture rather than a button press; performa understands both, as long as the button is still set to Back.

Walking a list

On the Todo, Start, Mentions, Missing-worklog and Timesheet-week screens:

↑ ↓ move through the rows
Enter open the row you are on

The row you are on is washed and carries a coloured bar down its left edge. It follows the issue rather than the position, so re-sorting a column leaves you on the same issue even though it has moved. These are the only shortcuts without a modifier, because that is what every list everywhere answers to.

The Start tab has two lists — the due issues and the reminders under them — and ↓ crosses from the end of one into the start of the next.

In the Log work search box the arrows move through the results while you go on typing, so an issue can be found and picked without touching the mouse.

The selected row is read out to a screen reader as it moves.

The arrows are a shortcut, not the only way through. Every action a selected row offers — pin, open in Jira, start its timer, edit, log again — is also a button in that row, reachable with Tab and pressed with Enter or Space. The row shortcuts are bound to those very buttons: the badge you see when you hold ⌘ sits on the button the key presses.

Acting on what you are looking at

The same verb keeps the same key everywhere; what it acts on is whichever row you are on, or whatever is open in front of you.

⌘J open it in Jira, in the browser
⌘T start its timer — or stop the running one
⌘⇧T pause the running timer, or resume a paused one
⌘B pin it to the top of the Log-work list, or unpin it
⌘L log work on it
⌘E edit it — a worklog entry, or the issue view's field layout
⌘D log it again today
⌘K comment (⌘⇧K for a customer reply on a service-desk issue)
⌘U attach files
⌘I link a work item
⌘S submit the form in front of you
⌘Y switch the timesheet between week and month
⌘⇧← ⌘⇧→ the previous or next week or month

⌘S always means the form you are looking at. With a dialog open it submits that dialog, and the form behind it gets the key back when the dialog closes.

The command palette

⌘P opens a list of everything the app can do right now, searchable by name. Type a few letters, press Enter, and it runs.

Each entry shows its own shortcut beside it, so the palette is also the way to learn them — the ones you use often will stop needing it. Entries with no shortcut are reachable only here, which is the point: the Todo tab's five Sort by … columns are not worth five keys of their own, and appearance, text size and the handbook all live here rather than cluttering the window.

Escape closes it without leaving the view behind it.

Opening an issue by its key

Type an issue key — ABC-1234 — and the palette offers to open it, first in the list. It is what the query is rather than something it resembles, so it leads. Case does not matter: abc-1234 finds the same issue.

The issue opens in the app, over whichever tab you were on, and going back returns you there.

Searching

Search by text is always offered: pick it, type your words, press Enter, and every issue with those words in any field Jira searches comes back as an ordinary list — the same rows the Todo tab draws, so the arrow keys walk them and Enter opens one.

Searches of your own appear beside it as Search by …, named however you named them. See Settings → Searches for building one.

Both ask for the term in a second step. Picking the search empties the box, so what you typed to find the search is not mistaken for what you want to search for, and the hint underneath says what it is waiting for. Escape there goes back to the list of commands rather than out of the palette — having picked the wrong one of two searches, the other is one press away.

Views

A query of your own that names no search term is a view rather than a search: it already describes the issues it means, the way a filter on the site does. Those appear in the palette as View: … and need no second step — picking one shows its results straight away.

Everything after that is the same screen a search lands on: the same rows, the same keys, the same way back. Which of the two a query becomes is decided by the query alone — write %SEARCHTERM% somewhere in it and it asks for a term, leave it out and it runs as written — so turning one into the other is a matter of editing its JQL. See Settings → Searches.

A view you open every day can also sit in the sidebar. Star it in Settings → Searches and it appears under the tabs, in a group headed Views; one click shows its results, and its row stays highlighted while they are on screen. Only views can be starred. A search needs a term, and the sidebar has nowhere to type one.

Results say how many they found. Where Jira had more than the app asked for, they say first 100 and suggest narrowing the term: a full page is not proof there is nothing after it, and these searches deliberately include finished issues, so a long history reaches the limit as a matter of course.

When a key does nothing

  • You have typed something. A key that would throw unsaved words away — a tab switch, a refresh, going back — stands down while the box you are in has something in it, and its badge dims to say so. An empty box is no obstacle: a form that has just opened puts the cursor in its first field, and you can still leave.
  • The key belongs to the box. ⌘← is "start of line" in a text field, and Escape closes a mention list before it closes anything else.
  • A dialog is open. Only the dialog's own keys work; the screen behind it is not reachable until it closes.
  • The control is not on screen. A key exists only while its button does, so ⌘T stops a timer only while one is running, and ⌘I offers a link only while that form is closed.

Some chords never reach performa at all, because macOS claims them first: ⌘Q ⌘W ⌘H ⌘M ⌘Z ⌘X ⌘C ⌘V ⌘A. That is deliberate — it is what keeps copy and paste working in every box in the app.

Start tab (dashboard)

The Start tab is the landing page and shows four sections. Sections with nothing to show are hidden.

Due dates

Issues assigned to you whose due date lies between 7 days ago and 14 days ahead, soonest first. Issues already in a Done status category are excluded — an overdue issue only shows up here while it is still open.

Each issue carries a due badge:

  • overdue (red outline) — the due date has passed
  • today (highlighted) — due today
  • due … (neutral) — upcoming, with the weekday and date

The rows are full-featured issue rows:

  • ☆ / ★ pins the issue to the top of the Log work list (Logging work)
  • The issue type icon — Jira's own icon for Bug, Task, Story and the rest — sits in front of the key; hover it for the type's name. It can be switched off under Settings → Appearance
  • Clicking the issue key opens the issue in your browser
  • Clicking the summary jumps to the Log work tab with the log form already open for that issue
  • ▶ start starts a timer for the issue

This week

The same charts as the Timesheet's current week: per-day bars against your daily target and a progress ring against the weekly target, plus the total logged so far. It refreshes automatically whenever you log work.

Templates

Your saved worklog templates as one-click chips — see Templates. Hidden while you have none.

Missing worklogs

A preview of the current findings of the missing-worklog watcher. Clicking an item (or Open tab) jumps to the Missing worklog tab. Hidden when nothing is missing.

Todo tab

Everything that is currently waiting on you, most urgent first (then most recently updated). Two rules are combined:

  • DEV issues you raised yourself that are back in your court — i.e. every status except Fertig, Backlog, Rückfrage beantwortet, In Arbeit and Nicht umgesetzt.
  • Issues assigned to you in any project that have not reached a status where the ball is somewhere else — closed, cancelled, resolved, escalated, in commercial review, or waiting for the customer or DESIGNA Development.

The rows work like those on the Start tab (pin, open in browser, ▶ start for a timer), but are laid out as a table — the type icon (column T), issue key, summary, priority and status each in a column of their own, so you can scan down them. There are no due badges here; due dates are the Start tab's subject.

Sorting. Click a column heading to reorder the list by it. Each heading cycles through three states:

  1. ▲ ascending
  2. ▼ descending
  3. no arrow — back to the order Jira sent, i.e. the "most urgent first" above

Two of the columns sort by what you actually see rather than alphabetically: Prio goes by urgency (highest first when ascending), and Status groups by the label on the badge — so every status that reads Warten sits together, whatever it is called in the workflow behind it. Issues with nothing in the sorted column stay at the bottom in both directions, and issues that tie keep their urgency order. The sort applies to the list already on screen — Refresh keeps it — and resets when you leave the tab.

Clicking the summary opens the issue in the app — see The issue view. Clicking the issue key opens it in the browser instead.

The result is cached for a minute; Refresh fetches it from Jira again — useful right after you changed a status in the browser.

Statuses that should never appear on your list — a review queue, "waiting for customer" — are yours to choose per project under Settings → Todo. Issues Jira itself counts as done are dropped by the query regardless of what your workflow calls them.

The issue view

Opening an issue from the Todo or Mentions tab shows it inside performa rather than in the browser.

Reading. The issue key and summary sit at the top with the status picker in the corner. Below them a grid of fields, the description (clamped, with Show more when there is more), the attachments, the linked work items, and a timeline of everything that has happened — comments, status changes and worklogs interleaved, newest first. Long threads show only the newest comments and say so.

Changing a value. Double-click any value with a dotted underline to change it; a small editor opens over it. What is editable is decided by Jira, per issue — a field your permissions or the issue type do not allow is simply not offered.

Emptying a value. The editor's Clear button removes the value altogether. It is the only way to empty a field that has no text box to delete from — an assignee, a due date, a dropdown — and it works for the text ones too. Leaving the editor's box blank and pressing Save does not clear the field: a blank box means "left alone", so the change is refused instead. Clear is offered only where there is a value to remove and Jira does not insist on the field.

Moving it through the workflow. The status picker lists the statuses you can reach from where the issue is now. Some moves ask for more first (a resolution, an assignee); those open a form. A move needing something performa cannot fill in is shown but disabled, with a link out to Jira.

Comments. One row of buttons: Internal note and Reply to customer on a service-desk issue, or a single Comment everywhere else, and Log work. Picking one opens its fields below; picking it again closes them. Type @ in a comment to mention somebody — pick the name from the list, because only a picked name notifies anyone.

Attachments. Open one to download and view it, drop files on the window or use Attach files… to add them, and ✕ to remove one (with a confirmation — it is removed for everyone).

Linked work items. Under the attachments, the issues this one is linked to, grouped by relationship — blocks, is blocked by, relates to, whatever your site defines. Each row shows the key, the summary and the current status; the key opens that issue in the browser. Link work item… adds one: pick how it relates to this issue, then find the other issue by key or by words from its summary. ✕ removes a link — only the link goes, both issues stay.

Leaving it. The Back link in the corner returns to the list — as do Escape, your mouse's back button and a two-finger swipe right (Going back). After following a linked work item it goes back to the issue you came from rather than out to the list, one issue per step.

Arranging the fields. Arrange fields above the grid turns the layout over to you: drag a field by its ⠿ grip, resize it with the size button (one cell, two cells, or a full row for prose), remove it with ✕, and add any other field your Jira site has. Done returns to reading. The layout is yours and applies to every issue.

Logging work

The Log work tab is a two-step flow: find an issue, then fill in the worklog.

Finding an issue

The search field interprets your input in three ways:

Input Behavior
(empty) Your open issues (assigned to you, not Done), most recently updated first
An issue key such as ABC-123 Exact lookup of that issue
Any other text Full-text search across issue summaries and content

Search results update as you type (with a short debounce). The query itself is translated to JQL inside the app's native core — you never have to write JQL.

The results are the same issue rows as on the Start tab, type icon included.

Pinned issues (★) always appear at the top of the default list, separated by a heavier divider. Pin or unpin any issue with the star on its row; pins are stored locally on your machine — including the issue type, so a pinned row keeps its icon. A pin from before this version shows no icon until you unpin and pin it again. During an active text search the plain results are shown instead.

Each result row offers the same actions as on the dashboard: open in browser (key), select (summary), pin (star), and start a timer (▶).

The worklog form

After selecting an issue, fill in:

  • Time spent — Jira-style duration syntax:

    Input Meaning
    1h 30m 1 hour 30 minutes
    45m 45 minutes
    2h 2 hours
    1d 1 working day = 8 hours
    1w 1 working week = 5 days
    1.5h or 0,25h Decimals with dot or comma
    2 A bare number counts as hours

    A live hint below the field shows how the input was understood (e.g. = 1h 30m).

  • Date — defaults to today; future dates are not allowed.

  • Start time — defaults to the current time.

  • Comment (optional) — stored as the Jira worklog comment.

  • Non-billable — marks the entry non-billable (stored as a leading ~ in the Jira comment; see What is performa?). The checkbox resets for every newly selected issue so billability never leaks from a previous entry.

Press Log work to save. A success message confirms the entry, and the form clears for the next one.

My logged time

Below the form, the issue's history shows your previous worklogs on that issue (the 10 most recent, plus your total). This updates immediately after logging.

The same list appears under every form that logs time, so you always see what is already booked before adding to it: the log-work tab, the timer stop modal, the missing worklogs form, and the "Log again" modal in the timesheet. In the modals the list is capped in height and scrolls. On a missing-worklog finding it shows the issue the time will be logged on — which for a DEV escalation is the source issue, not the flagged one.

The timer

Start a timer with the ▶ start button on any issue row (Start tab or Log work tab). Only one timer runs at a time, but moving it is one click: while a timer runs (or is paused), every other row's button reads ▶ switch. Switching starts the new timer straight away and opens the log modal for the old one — filled in exactly as if you had pressed Stop — so filling it in costs the new timer nothing. Switch again before you are done and the next form simply waits its turn; no tracked time is dropped — not even by quitting, since waiting forms are back after a restart. ⌘T on a selected row only starts a timer when none exists; with one running it means Stop, so switching is the button's job.

Starting a timer also tries to move the issue to the "In Arbeit" status in Jira, using whatever transition currently leads there in that issue's workflow (matched case-insensitively, e.g. "IN ARBEIT" also counts). This is best-effort: if the issue is already in that status, or its workflow doesn't offer a direct transition to it, nothing happens — the timer still starts normally either way.

While running:

  • The timer bar above the tabs shows the issue and a live clock.
  • The system tray mirrors the timer.

Pause (in the timer bar, the tray, or ⌘⇧T) stops the clock without ending the timer — for lunch, or a call about something else. The bar's dot stops pulsing, the clock greys out and stands still, and the button now reads Resume. Resuming carries on from the same reading: paused time never counts. A paused timer is still the one timer, and still tracked time waiting to be logged — so it survives a restart and close protection asks about it just as it does about a running one.

Press Stop (in the timer bar or the tray) to finish. The log modal opens with:

  • Time spent prefilled with the elapsed time, rounded up to the next 15 minutes (minimum 15 minutes) — you can edit it freely before saving. Paused stretches are left out, and the rounding is applied once to the total, so a day of short breaks does not add up to extra quarter hours.
  • Date and start time prefilled from when the timer was first started — not from the last resume.

You can complete the worklog (comment, billability) and save, Discard the tracked time — discarding asks for confirmation, because the time would be lost — or press Later to park it as a draft and book it when you have the moment.

Idle time

A timer counts the clock, not the work, so one left running over lunch would book lunch. While a timer runs, performa watches how long the computer has had no input — keyboard, mouse, trackpad — and a closed lid or a sleeping machine counts too. Once there has been no input for longer than the idle setting (10 minutes unless you change it), it waits for you to come back, then brings its window forward and asks You were away: how long, from when to when, on which issue. Nothing is asked while you are away, and nothing at all while the timer is paused.

  • Keep — the time away was work (a meeting at the whiteboard); nothing changes. This is the default: Enter answers it.
  • Discard — take the time away out of the timer; it keeps running from now.
  • Draft — take it out, and park it on the same issue, to decide later.
  • Discard & stop — you were done for the day: the timer ends where you left, and the log form opens with only the time before that.

The timer is based on wall-clock time and survives app restarts: if you quit with a timer running (see Close protection) and reopen the app later, the timer resumes with the correct total elapsed time.

System tray / menu bar

performa adds an icon to the macOS menu bar / Windows system tray:

  • macOS: while a timer runs, a live readout appears next to the icon — ▶ ABC-123 12:34 (hours:minutes:seconds past an hour). While it is paused, the readout stands still behind a pause sign: ⏸ ABC-123 12:34.
  • Windows: tray icons cannot show text, so the same readout appears as the icon's hover tooltip instead. Everything else works identically.

The tray menu offers:

  • Pause timer / Resume timer (enabled only while there is a timer) — pauses or resumes it in place, without bringing the window forward
  • Stop timer… (enabled only while there is a timer, running or paused) — brings the window to the front and opens the regular log modal
  • Open performa — shows and focuses the window
  • Quit performa — quits the app; this goes through the normal close path, so close protection still applies

Timesheet

The Timesheet tab has two views, switched with Week / Month at the top. Your choice is remembered until you change it.

Week

Shows one week at a time.

  • Navigate with ← / →; the current week is the rightmost you can go (no future weeks). Labels show "This week", "Last week", or the date range.
  • Charts: per-day bars, each measured against that day's own target (a short dashed line marks it), and a ring showing the week's progress against the weekly target — the sum of the week's daily targets. A short Friday, a public holiday or a day off all count at their own size: a holiday has no target line at all, half a day off has half of one, and the ring's target shrinks to match. Hover a bar to see its time, its target and why. Saturday/Sunday are hidden by default but appear automatically when they contain logged time or have a target of their own — or always, if you switch the setting to full week.
  • Below, worklogs are grouped by day (newest day first) with per-day totals. Each row shows the issue key (click → browser), summary, comment, start time, duration, and a non-billable tag where applicable.

Row actions:

  • ↻ Log again today — opens a prefilled form (same issue, duration, comment, billability) with today's date and the current time: ideal for recurring entries. The modal also offers Save as template (Templates).
  • ✎ Edit — change any field of the existing worklog (duration, date, time, comment, billability).
  • 🗑 Delete — removes the worklog after a second, inline confirmation (✓ / ✕).

Month

A matrix: issues down the side, days across the top, hours in the cells. Built for filling in the gaps rather than reading history.

  • Columns are every weekday of the month, plus any Saturday or Sunday you actually booked time on — a worked weekend day is never hidden.
  • The header row carries each day's total, the right-hand column each issue's month total, and the top-left corner the whole month.
  • Hours read as decimals (1.5, 0.25) because a column is too narrow for 1h 30m; the full duration is in the cell's tooltip.
  • Each day's total is coloured by how full the day is, against its own target: red under three eighths of it, amber up to three quarters, green above — for an 8-hour day that is under 3 hours, 3 to 6, and above 6. Only days expected to hold work are judged — a weekend column and a day that hasn't happened yet stay uncoloured — and a public holiday or a whole day off reads grey, as off rather than behind. The day header's tooltip names the holiday or the kind of day off.

Clicking a cell opens everything booked on that issue on that day: each worklog with the familiar ↻ / ✎ / 🗑 buttons, plus + Add time to book more against the same issue and day. An empty cell opens the same window, ready to add the first entry. Future days are greyed out, the same rule the log form follows.

The + row under the header logs time on an issue that has no row yet: click the day, pick the issue, fill in the form. The day is already filled in for you.

Width: the month is the one view that uses the whole window. Every other view stops at a comfortable reading width, but here more width means more days on screen and more of each summary before the ellipsis, so a wide or maximised window is put to work — the day columns keep their size and the issue column takes the extra. The issue column also has its own key column, so the summaries all start at the same place down the table.

Rebuilding a day

Some days end with less booked than was worked, and by the next week nobody remembers what filled them. Rebuild a day puts what you did in Jira that day next to what you booked, so the gaps show.

Open it from the Rebuild a day row under the week's total — one button per day of the week so far, empty days included — or by clicking a day's header in the Month view. Days from the current and the previous month can be rebuilt.

The day reads in time order:

  • your comments, your status changes, issues you created, and issues handed to you — read from Jira when you open the day (once per day per session; nothing runs in the background)
  • what is already booked, greyed
  • the running timer and any parked time of that day

Anything you did on an issue with no time booked that day is marked and offers Log…: the ordinary log form, filled in with that issue, that day and that moment. Nothing is booked for you — the view never fills a gap on its own, because it knows what you did, not how long it took.

Comments can't be searched by author in Jira, so the view finds them on the issues you have recently viewed, watch, are assigned or reported. On a very busy day, or one a few weeks back, Jira can hold more than the view reads; it then says that some of what you did may be missing rather than calling the day complete.

Missing worklogs

The Missing worklog tab is a safety net for forgotten time entries.

What it flags: issues where you commented or changed the status within the last 24 hours, but have no worklog within about 3 hours of that activity. Activity from the last 10 minutes is not flagged yet (grace period — you may simply not have logged it yet). The check runs automatically every 15 minutes while you are signed in; Check now triggers it manually, and the tab shows when it last ran.

Each finding shows:

  • the issue and what you did — a quoted comment excerpt, or the status change (Old → New), with how long ago
  • a count badge on the tab; the tab blinks until you view it (viewing the tab acknowledges the current findings)
  • a desktop notification, fired once per finding (see FAQ if you don't see notifications)

Clicking a finding opens an inline log form, prefilled with the date and time of the flagged activity, so the resulting worklog covers it and the reminder clears on the next check.

Escalation issues: for issues in the DEV project, the time is logged on the linked escalation-source issue instead (the issue linked as "is an escalation for") — but only when that source issue is assigned to you. Somebody else's ticket never receives your hours: if the source belongs to a colleague or to nobody, the time stays on the DEV issue you were actually working. The form shows both issues so it's always clear where the time goes. When the source issue is on the list in its own right, the DEV row is left out — one worklog would clear both, and two rows for the same piece of work only add noise.

Parked time (drafts)

Sometimes the work comes before the ticket — somebody walks up with a problem, and the ticket arrives a day later, if at all. Parked time holds that time until there is somewhere to book it: a duration, when it happened, a note on what it was, and — once known — the issue it belongs on.

A draft is not a missing worklog. Those are found by scanning Jira; a draft is something you put down, so it never disappears on its own. It goes when you have booked all of it, or when you discard it (which asks first).

Parking time:

  • Park time… in the command palette opens the park form: duration, date, start time, a note and, optionally, the issue.
  • When a search in the issue picker finds nothing, the list offers No ticket yet — park it, with what you searched for as the note.
  • Start a timer without a ticket in the palette starts a timer that belongs to no issue — it asks what you are working on, and the tray shows it as ▶ No ticket 12:34. Stopping it parks its time straight away, without a form.
  • The log form that opens on Stop or on a switch has a Later button: the time is parked instead of logged.

Where it waits: in its own Parked time section at the top of the Missing worklog tab, with the total still to book. Drafts count towards the tab's badge, and every time you sign in — normally, every time the app starts — a desktop notification says how much is still parked. A draft that has waited a week or more turns amber and says how long.

Booking it: Book opens the ordinary log form, filled in from the draft — its note becomes the worklog comment. A draft without an issue asks for one first. Book less than the whole and the rest stays parked, starting where the booked part ended: that is how one stretch is split across several issues. Edit opens the park form on the draft; Discard removes it after a confirmation.

Drafts are kept on this computer only, like your other settings, and nothing about them reaches Jira until you book them.

Mentions

The Mentions tab is your Jira inbox for being tagged: every comment from the last 14 days in which somebody @-mentioned you.

How it finds them: a mention is matched by your account id in the comment itself, not by your name appearing in the text — so somebody merely writing your name is not a hit, and a mention on an issue you have nothing else to do with still is. The scan runs every 3 minutes while you are signed in; Check now triggers it manually, and the tab shows when it last ran.

What it can miss: Jira has no "my mentions" search, so performa first picks a bounded set of recently updated issues and then reads their comments. Two consequences: only a limited number of issues is opened per scan, and one of the two ways of picking them looks for your display name in the comment text — if that name changes, or the list of recent issues is longer than the scan can open, a mention can go unseen. When a scan is cut short this way the tab says so above the list. An empty list therefore means "nothing found where it looked", not "nothing exists".

Each row shows the issue, who wrote the comment, an excerpt, and how long ago it was. Clicking the row opens the issue in the app — see The issue view. Clicking the issue key opens it in the browser instead.

Read / unread: new mentions raise a count badge and make the tab blink. Opening the tab marks everything currently listed as read — for that one visit the rows stay marked (accent bar and dot) so you can still see what was new. Your own comments never appear, and a mention already read stays read across restarts.

A desktop notification is fired once per new mention.

Templates

Templates make recurring entries (daily standup, support duty, …) a one-click affair.

  • Create: in the Timesheet, press ↻ on any worklog and tick Save as template on the start tab before logging. The template stores the issue, duration, comment, and billability.
  • Use: on the Start tab, click a template chip. The log form opens prefilled — with today's date and the current time — and one confirmation logs it.
  • Remove: the ✕ on each chip deletes the template.

Templates are stored locally on your machine, not in Jira.

Settings

The Settings link in the header opens the same screen used for the first-run connection:

  • General — the connection to Jira (below), plus app-wide switches and Check for updates (see Updates).
  • Appearance — light / dark theme toggle, the accent colour, and Show issue type icons in lists (on by default; turning it off drops the icon from every issue row, and the T column from the Todo tab with it).
  • Work hours per day — one box per weekday, Monday first (0–24 h; 8 for Mon–Fri unless you change it). Each day of the timesheet is measured against its own weekday — a part-time Friday is a shorter Friday, not a lower average — and the weekly ring against the week's sum.
  • Public holidays — your German state. Its statewide legal holidays are then days off: no target, grey in the month view. Holidays only some towns keep (Mariä Himmelfahrt in parts of Bavaria, for instance), and days like 24 or 31 December that many contracts treat as half days, are not built in — mark those as days off yourself.
  • Days off — vacation, sick days and the like, as a whole or a half day: pick a date (or a stretch, with until, which skips weekends and holidays), how much of the day, and what kind, then Add. A day off takes its share off that day's target. The list shows the last two months and everything ahead; ✕ removes an entry. Like searches, days off are yours rather than a preview, so Cancel does not undo them.
  • Timesheet days — Mon–Fri (weekends hidden unless they contain logged time) or Full week.
  • Idle time — how many minutes without input before a running timer asks about the time away (10 by default; 0 turns it off). See Idle time.
  • Todo — which statuses the Todo tab hides, per project. Most sites use the same statuses everywhere, so the list carries a Copy to for filling the rest in at once.
  • Searches — searches of your own, each becoming Search by … in the command palette (⌘P). One row each: a Name and the JQL it runs, written exactly as you would write a filter in Jira, with %SEARCHTERM% where the text you type into the palette goes — for example project in (CTS, DEV, SD) AND "Plant Number[Short text]" ~ %SEARCHTERM% ORDER BY created ASC. Written on its own, %SEARCHTERM% is quoted for you; written inside quotes, the rest of that string is left as you wrote it, so "%SEARCHTERM%*" matches anything starting with what you type (DE_1979 then also finds DE_1979_03). Whatever you type is escaped on the way in, so a quote or a bracket in the term is searched for rather than read as JQL. A query without %SEARCHTERM% is a view instead of a search: it finds the same issues whatever you type, which is the point of one, so it is offered in the palette as View: … and runs the moment you pick it. A view also has a star next to its ✕: star it to keep it in the sidebar under the tabs, and click the star again to take it out. The JQL box says which of the two a query has become, and saves when you leave it or press Enter. Searches written before this took the JQL form (a field, Whole value and excluded projects) are converted to the equivalent JQL on first launch, so nothing needs re-entering. Searching plain text needs no setting up and is always offered.
  • Logging — the debug-log verbosity (Error, Warn, Info, or Debug; see Debug log) and an Open log folder button.
  • Credentials — change site, email, or token. Leaving the token field blank keeps the stored token, so you don't need to re-enter it to fix a typo in the email. Saving re-verifies against Jira.

Appearance (theme, accent, type icons), hours, the holiday state, the weekend toggle, and the log level apply instantly as a live preview — pressing Cancel restores the values from when you opened the screen. Searches are not part of that rollback: they are yours rather than a preview, and the ✕ on a row is what removes one.

Saved searches belong to the account they were written for — the fields and projects their JQL names mean nothing on another Jira — so signing in as somebody else starts with an empty list.

Which fields an issue shows is not here — that lives on the issue itself, under Arrange fields.

About (in the header) shows the version and how to get in touch.

Sign out (in the header, with confirmation) deletes the token from the OS keychain and returns to the connect screen.

Moving to another computer

Settings → General → Transfer settings copies your settings from one computer to another — between Windows and macOS too.

  1. On the old computer, press Export… and save the file (performa-settings-YYYY-MM-DD.json) somewhere you can reach from the new one.
  2. On the new computer, install performa and sign in first — the file does not contain your Jira login.
  3. Press Import…, pick the file, and confirm with Replace. performa restarts with the imported settings.

What travels: theme, accent, text size and the other display switches, work hours per weekday, holiday state, days off, idle time, Todo sorting and hidden statuses, templates, pins, saved searches, the issue field layout, parked time (drafts) and fun-mode achievements. Each setting in the file replaces yours; settings the file does not carry stay as they are.

What stays behind: your Jira login, a running timer, the log level, and which mentions and missing worklogs you have already seen.

  • Parked time is copied, not moved: the old computer keeps its drafts too, so book each one in one place only.
  • Another Jira account — if the file was exported from a different account (or doesn't say which), the confirmation warns you: saved searches, the field layout and hidden Todo statuses name that site's fields, projects and statuses and may not fit. You can still import.
  • A file that isn't a performa settings file, or one saved by a newer performa than yours, is refused and nothing changes.

Close protection

Quitting with unfinished business triggers a warning instead of silently losing data:

  • Timer still running — shows the issue and elapsed time; stop the timer to log it first, or Quit anyway to discard the tracked time.
  • Unlogged work pending — findings are waiting in the Missing worklog tab; go back and log them, or Quit anyway.

Before closing, performa re-checks Jira for unlogged work — silently, so a close with nothing pending just takes a moment longer; a dialog only appears when something turns up.

This applies to the window's close button and to Quit performa in the tray menu alike.

Updates

performa checks GitHub for a newer release once per hour. When one exists, a banner appears with:

  • Update & restart — downloads the update with a progress display, installs it, and relaunches the app
  • Release notes — opens the release page in your browser
  • ✕ — dismisses the banner for this version; the next release brings it back

The hourly check keeps running while Settings is open.

To check right away, open Settings → General → Updates and press Check for updates. The line below the button says what came back: that you're on the latest version (and when it checked), that a newer version is available, or why the check failed. If there is a newer version, Update & restart appears next to the button, so you can install it without leaving Settings. Checking this way also brings back a banner you dismissed for that version.

Debug log

performa keeps a rolling debug log on disk, useful when something doesn't behave as expected (e.g. a Jira call failing, or the timer's status nudge not finding a matching transition).

  • Location — a dedicated performa-logs folder inside your system's temp directory. Open it directly with the Open log folder button in Settings.

  • Rotation — one file per app launch, named performa_YYYYMMDD_HHMMSS.log; only the 3 most recent files are kept, older ones are deleted automatically at the next launch.

  • Level — set in Settings, from least to most verbose: Error (default) → Warn → Info → Debug. Raising it takes effect immediately, no restart needed, and also governs what the frontend forwards into the same file.

    • Error — only failures (a rejected Jira call, a failed transition, …).
    • Info — adds a trace of what you did and what performa did in response: which tab you switched to, every backend call performa made (what was requested, e.g. search_issues(query="bug"), how many results came back, and how long it took), signing out, starting/stopping the timer, and missing-worklog checks (and why they ran — a poll, Check now, or right after logging work).
    • Debug — adds internal detail below the level of a single backend call, e.g. how many candidate issues the missing-worklog scan considered before flagging any, or a cosmetic tray-sync hiccup.
  • Format — one line per event, matching Python's standard logging module:

    2026-07-22 15:10:26,618 - performa - INFO - performa 0.4.0 started
    2026-07-22 15:10:27,203 - performa - INFO - view: timesheet
    2026-07-22 15:10:28,410 - performa - INFO - list_worklogs(start=2026-07-20, end=2026-07-26) → 14 entr(y/ies) (312ms)
    2026-07-22 15:10:41,006 - performa - ERROR - Jira returned 401: Unauthorized
    

The log is local-only — see Data & privacy — and is never uploaded anywhere by performa itself. Your API token is never written to it; log lines can include issue keys and Jira error text, so treat the folder like any other local diagnostic data if you share it (e.g. in a bug report).

Data & privacy

Data Where it lives
API token OS keychain (macOS Keychain / Windows Credential Manager)
Site & email With the token in the keychain entry
Worklogs In Jira — performa stores no copy
Pins, templates, settings (theme, accent, type icons, hours, weekends, log level) Locally in the app's storage
Settings export (see Moving to another computer) Only where you save it — holds your settings plus your site and email, never the token
Issue type icons Locally in the app's storage — fetched from your Jira site once and kept so lists don't flicker on every launch
Timer state, seen/notified markers, dismissed update version Locally in the app's storage
Debug log (see Debug log) performa-logs folder in your system's temp directory

performa communicates only with your Jira Cloud site (all worklog operations) and GitHub (update check). There is no telemetry.

Troubleshooting & FAQ

"Jira returned 401/403" when connecting or logging. The token, email, or site is wrong, or the token was revoked. Create a fresh API token and re-enter it in Settings (site/email corrections don't require re-entering a valid token).

I don't get desktop notifications. The first notification triggers the operating system's permission prompt — if it was declined, allow notifications for performa in the OS settings (macOS: System Settings → Notifications). Note that unsigned development builds may appear under a different app identity than the packaged app.

Where is the tray clock on Windows? Windows tray icons can't display text next to the icon (a platform limitation). Hover the performa tray icon to see the running timer in the tooltip; all tray menu actions work normally.

Do my worklogs show up in ActivityTimeline? Yes. performa writes native Jira worklogs, which ActivityTimeline reflects automatically. The non-billable marker (~ prefix in the comment) follows ActivityTimeline's own convention.

The app shows "Could not read stored credentials". The OS keychain could not be read (e.g. it was locked). Unlock/log in to your OS keychain and press Retry.

Can I log time in the future? No — the date field is capped at today.

Can two timers run at once? No. Stop the running timer first; all other start buttons are disabled meanwhile.