Die Entwicklung von Performa und was ich dabei gelernt habe

Zeiterfassung in Jira gehört nicht zu meinen Lieblingsaufgaben. Browser auf, Ticket suchen, Zeit eintragen, speichern und am Ende der Woche merken, dass irgendwo ein paar Stunden fehlen. Im Juli habe ich mich deshalb hingesetzt und angefangen, mir selbst ein kleines Tool dafür zu bauen. Daraus ist Performa geworden.

Was ist Performa?

Performa ist eine Desktop-App für macOS und Windows, mit der ich meine Zeiten in Jira Cloud buche. Ich starte für ein Ticket einen Timer, der auch in der Menüleiste läuft, und beim Stoppen wird auf die nächste Viertelstunde aufgerundet und direkt gebucht. Dazu kommen eine Wochen- und Monatsansicht meiner Buchungen, eine Liste mit Kommentaren, in denen ich erwähnt wurde, und ein Hintergrund-Check, der mich erinnert, wenn ich an einem Ticket gearbeitet, aber keine Zeit gebucht habe. Inzwischen kann ich in Performa auch Tickets bearbeiten, kommentieren und weiterschieben, sodass ich Jira im Browser nur noch selten öffne.

Gebucht wird über die normale Worklog-API von Jira. Dadurch tauchen die Zeiten auch automatisch in ActivityTimeline auf, wo bei uns die Stundenzettel landen, ohne dass ich dafür etwas extra bauen musste.

Von 0.1 bis 2.5

Der erste Commit war am 15. Juli 2026. Eigentlich wollte ich nur ein Fenster mit Login, Ticketsuche und einem Formular zum Buchen. Vier Tage später war Version 1.0 fertig, inklusive Handbuch auf Deutsch und Englisch. Danach kam immer noch eine Kleinigkeit dazu und mittlerweile bin ich bei Version 2.5 mit 58 Releases und gut 300 Commits. Für ein kleines Formular ist das ganz schön viel geworden.

Die Technik

Performa basiert auf Tauri v2. Der Kern ist in Rust geschrieben, die Oberfläche in React und TypeScript. Im Gegensatz zu Electron bringt Tauri keinen eigenen Browser mit, sondern nutzt die WebView, die das Betriebssystem sowieso schon hat. Dadurch sind die Installer nur etwa 5 bis 10 MB groß.

Eine Entscheidung, die ich ganz am Anfang getroffen habe und die sich durch das ganze Projekt zieht: Die gesamte Kommunikation mit Jira passiert im Rust-Backend. Das Frontend kennt den API-Token nicht, es ruft nur Funktionen im Backend auf. Der Token selbst liegt im Schlüsselbund des Betriebssystems, also im macOS-Schlüsselbund bzw. in der Windows-Anmeldeinformationsverwaltung. So bleiben die Zugangsdaten aus der Oberfläche raus und ich musste mich nebenbei nie mit CORS-Problemen herumschlagen.

Gebaut und veröffentlicht wird alles über GitHub Actions. Ich pushe einen Tag, die Pipeline baut die Pakete für macOS und Windows und hängt sie an ein Release. Die installierten Apps schauen stündlich nach und holen sich das Update dann von selbst.

Was nicht so glatt lief

Ein paar Sachen haben mich mehr Zeit gekostet als gedacht. Der Such-Endpunkt /rest/api/3/search, den fast jedes Tutorial benutzt, wurde von Atlassian abgeschaltet. Den Nachfolger /search/jql findet man erst, wenn man weiß, wonach man suchen muss. Dann hatte ich eine Zeit lang zwei Timer, einen im Fenster und einen in der Menüleiste, die langsam auseinanderliefen. Für eine Zeiterfassungs-App nicht ideal. Und weil Performa im Hintergrund regelmäßig nach Erwähnungen und fehlenden Buchungen sucht, gingen anfangs viel zu viele Anfragen an Jira raus. Mit etwas Caching und parallelen Abfragen ist das inzwischen deutlich besser.

Was ich gelernt habe

Am meisten hat mir geholfen, klein anzufangen und schnell etwas auszuliefern. Version 1.0 nach vier Tagen ging nur, weil die erste Version wirklich nur das Nötigste konnte. Alles andere kam danach, Release für Release, und wurde direkt im Alltag getestet. Weil ich die App jeden Tag selbst benutze, merke ich sofort, was fehlt oder nervt.

Genauso froh bin ich, dass ich Sicherheit von Anfang an mitgedacht habe. Den Token nie in die Oberfläche zu lassen, war am Anfang etwas mehr Arbeit. Dafür musste ich später nichts umbauen, und auch bei mehreren Sicherheits-Reviews ist nichts Ernstes aufgetaucht.

Was ich so nicht erwartet hätte: Klare Begriffe sparen später eine Menge Ärger. Irgendwann habe ich angefangen, ein kleines Glossar im Projekt zu pflegen. Was genau ist eine Erwähnung? Was ist eine fehlende Buchung? Was unterscheidet einen Kommentar von einer Erwähnung oder einen Workflow-Übergang von einer einfachen Statusänderung? Das klingt erst mal nach Bürokratie, hat mir aber oft geholfen. Erwähnungen und fehlende Buchungen sehen im Code zum Beispiel fast gleich aus, bedeuten aber etwas ganz anderes. Das eine ist jemand, der etwas von mir will, das andere eine Erinnerung an meine eigene Arbeit. Wer die beiden im Code zusammenwirft, hat später ein Problem.

Einen großen Teil von Performa habe ich zusammen mit Claude als Coding-Assistent geschrieben, inklusive nächtlicher Läufe für Refactoring und Sicherheits-Checks. Das hat das Tempo enorm erhöht. Gelernt habe ich aber vor allem, dass die Kontrolle bei mir bleiben muss. Große Änderungen auf einmal kann ich nicht vernünftig prüfen, also arbeite ich in kleinen Schritten und committe erst, wenn ich mir das Ergebnis angeschaut habe.

Außerdem lohnt sich Automatisierung auch dann, wenn man allein an einem Projekt arbeitet. Bei jedem Pull Request laufen Tests, Linter, Formatierung und ein Windows-Build. Dependabot kümmert sich um Updates, die Abhängigkeiten werden regelmäßig auf Sicherheitslücken geprüft, und Releases baut die Pipeline. Das klingt für ein Projekt, an dem nur ich arbeite, übertrieben. Ohne das wären 58 Releases in drei Monaten aber nicht drin gewesen.

Und zum Schluss: Rust ist gar nicht so gruselig. Der Compiler ist streng und Clippy manchmal noch strenger. Aber wenn es einmal kompiliert, funktioniert es erstaunlich oft auch einfach.

Ob sich der ganze Aufwand gelohnt hat, nur um bequemer Stunden zu buchen? Wahrscheinlich nicht, aber Spaß gemacht hat es trotzdem.