Multi-team operation timer and report generator for fire departments.
DrillWatch tracks the operational times of individual firefighters and entire crews — for example teams operating under self-contained breathing apparatus (SCBA) or chemical protective suits (HazMat) — during training exercises and drills. It runs many independent stopwatches simultaneously, groups personnel into crews with synchronized start/pause/stop, and generates professional PDF reports with your department's own letterhead, ready to archive or print.
Built as free software for volunteer fire departments: fully offline, no accounts, no cloud, no tracking. Your personnel data never leaves the machine.
- ⏱️ Independent multi-timers — one precise stopwatch per firefighter, with start, pause, resume, and stop. Timing is based on
performance.now(), immune to system-clock changes. - 👥 Crew (Trupp) management — group personnel into crews (attack crew, water crew, hose crew, …) and start, pause, or stop an entire crew synchronously with a single click, sharing one timestamp so there is zero drift between members.
- 🔁 Multiple attempts per person — every run is recorded with start time, end time, and duration; a history dialog shows all attempts.
- 📋 Exercise management — organize sessions by exercise with type, date, group, and instructor; exercise types are fully customizable.
- 📄 PDF reports with your letterhead — one click generates an A4 report grouped by crew and person. Upload your department's logo and name in the settings and every report carries your letterhead.
- 📊 Excel import & export — import personnel rosters from
.xlsxfiles (with header detection, group detection, and duplicate checking) and export results back to Excel. - 💾 Crash recovery — running timers are persisted continuously; if the app or machine goes down mid-exercise, elapsed times are restored on restart.
- ↩️ Undo/redo — snapshot-based undo for destructive actions.
- 🔒 Offline & private by design — all data lives in a local SQLite database in your Documents folder. No network access, GDPR-friendly.
- ⌨️ Keyboard shortcuts — drive timers without touching the mouse.
Safety note: DrillWatch is a training and documentation aid. It is not a certified SCBA air-management or personnel-accountability system and must not replace your department's official respiratory protection monitoring (Atemschutzüberwachung).
Exercise view with a live crew timer — the standard crew layout (Gruppenführer, Maschinist, Melder, Angriffs-/Wasser-/Schlauchtrupp) with per-person timers and synchronized crew controls:
Multiple crews timing in parallel — each crew runs independently; members within a crew share one synchronized clock:
| Creating an exercise | Adding a custom crew |
|---|---|
![]() |
![]() |
Download the latest installer from the Releases page:
DrillWatch_x.y.z_x64-setup.exe— standard Windows installerDrillWatch_x.y.z_x64_en-US.msi— MSI package for managed deployments
Windows SmartScreen: the installers are not code-signed (signing certificates are expensive for a free project), so Windows may show an "unknown publisher" warning on first launch. Click More info → Run anyway. You can always audit the source code in this repository and build the app yourself.
Prerequisites:
- Node.js 20+
- Rust (stable toolchain)
- Tauri v2 system prerequisites for your platform
git clone https://github.com/madebylup/drillwatch.git
cd drillwatch
npm install
# Run in development mode
npm run tauri dev
# Build the release bundle + installers
npm run tauri buildThe installers are written to src-tauri/target/release/bundle/.
- Set up your department — open Settings and enter your department's name and upload its logo. Both appear in the app header and on every PDF report.
- Create an exercise — choose a type (e.g. SCBA drill), date, group, and instructor.
- Add personnel — type names in manually or import a roster from Excel.
- Organize crews — create crews and assign members; standard crew layouts can be seeded automatically.
- Run timers — start individuals or whole crews; pause and resume as needed.
- Export — generate a PDF report or Excel sheet and archive or print it.
All data is stored locally in Documents/DrillWatch/drillwatch.db.
DrillWatch reads the first worksheet of an .xlsx/.xls file and understands two layouts:
| Layout | Column A | Column B |
|---|---|---|
| Simple list | Name | — |
| Numbered list | Number (1, 2, 3, …) | Name |
The numbered layout is detected automatically when column A of the first row is a number; names are then read from column B.
Rows are classified automatically:
- Persons —
Lastname, FirstnameorFirstname Lastname - Group headers — a single word on its own row (e.g. a station, district, or department name). All persons below it are assigned to that group until the next header — this is how you track which fire department a trainee belongs to when several departments train together. The group appears in exports and reports.
- Header rows — a first row like
NameorTeilnehmeris recognized and skipped - Placeholders — rows like
frei,---, orn/aare ignored - Duplicates — repeated names are flagged for review
Example of a multi-department roster:
Name ← header row (skipped)
Musterstadt ← group header: department/station 1
Mueller, Hans ← assigned to "Musterstadt"
Meier, Anna
Nachbardorf ← group header: department/station 2
Schmidt, Peter ← assigned to "Nachbardorf"
Before anything is imported, a review dialog shows how every row was classified; you can re-classify rows, change a person's group, and deselect entries.
| Layer | Technology |
|---|---|
| Desktop shell | Tauri 2 (Rust) |
| UI | React 19, TypeScript, Tailwind CSS 4, shadcn/ui |
| State | Zustand |
| Persistence | SQLite via tauri-plugin-sql |
| Export | jsPDF + SheetJS |
| Tests | Vitest + Testing Library |
- Feature-based structure —
src/features/{timer,trupps,persons,exercises,export,settings,persistence,attempts}each bundle their UI, Zustand store, and SQLite repository. - Pure timer engine —
src/features/timer/timer-engine.tsmodels the timer as a pure state machine (idle → running ⇄ paused → stopped), fully unit-tested and independent of React. Synchronized crew actions pass a single shared timestamp throughstartTimerAt/pauseTimerAt/stopTimerAtso crew members can never drift apart. - Repository layer — all SQL is parameterized and lives in
*-repository.tsmodules; components never touch the database directly.
The user interface is currently German, as the software was built for German volunteer fire departments (crew names follow the German Löschgruppe structure). Internationalization is on the roadmap — contributions welcome!
Bug reports, feature requests, and pull requests are welcome — see CONTRIBUTING.md.
DrillWatch is free software licensed under the GNU General Public License v3.0. You may use, study, modify, and redistribute it; derivative works must remain under the same license.



