rtimelogger 0.8.8

A simple cross-platform CLI tool to track working hours, lunch breaks, and calculate surplus time
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
<h1 style="text-align: left; display: flex; align-items: center;">
  <img src="res/rtimelogger.svg" width="90" style="vertical-align: middle; margin-right: 8px;" alt="rTimelogger Logo"/>
  rTimelogger
</h1>

[![Build Status](https://github.com/umpire274/rTimelogger/actions/workflows/ci.yml/badge.svg)](https://github.com/umpire274/rTimelogger/actions/workflows/ci.yml)
[![Latest Release](https://img.shields.io/github/v/release/umpire274/rTimelogger)](https://github.com/umpire274/rTimelogger/releases)
[![codecov](https://codecov.io/gh/umpire274/rTimelogger/graph/badge.svg)](https://codecov.io/gh/umpire274/rTimelogger)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**rTimelogger** is a cross-platform **command-line time tracking tool** written in Rust.
It tracks working time using **IN / OUT events**, supports multiple locations, lunch rules, working gaps,
and computes **expected exit time** and **daily surplus** accurately.

---

## πŸš€ What's new in **v0.8.8**


### πŸ“ Notes support for events


You can now attach **free-text notes** to working pairs to describe activities, context, or important details.

- New `notes` field added to `events` table (TEXT)
- New CLI option: `--notes "<text>"`
- Supported in both **add** and **edit** modes
- If `--pair` is omitted in edit mode, notes are applied to the **last pair of the day**
- Notes are displayed only when using `--details`

**Output example:**

```text
NOTES
------------------------------------------------------------------------
Meeting with client for MVP planning and technical discussion
```

- Notes are automatically wrapped at 72 characters
- Output is visually consistent with CLI layout

---

## πŸš€ What's new in **v0.8.7**


### πŸ› Fixed β€” TGT calculation with non-work gaps (v0.8.7)


The `TGT` (target exit time) calculation was incorrect when non-working gaps were present between pairs.

- **Before**: `TGT = first_in + expected_work_time` (gaps ignored β†’ mismatch with Ξ”WORK)
- **After**: `TGT = first_in + expected_work_time + total_non_work_gaps` (consistent)
- `Ξ”WORK` is now always computed as `OUT βˆ’ TGT`, removing implicit double-counting
- No database or schema changes required

### πŸ€’ Sick Leave marker day (v0.8.6)


A new day position **Sick Leave** (`S`) has been introduced.

- Use `--pos s` to mark a sick leave day
- Optional `--to <DATE>` to apply sick leave over a date range (the command `DATE` is the start)
- Weekends, national holidays and dates already containing events are automatically skipped
- Sick Leave days do not contribute to Ξ”WORK totals and display `--:--` for all time fields

### βž• Show target exit on IN event (v0.8.5)


After adding an `IN` event, the calculated **target exit time (TGT)** is now immediately displayed in the output,
so you always know when you need to leave.

### πŸ“‹ National Holiday rendering improvements (v0.8.4)


- The `meta` field (e.g. holiday name) is now shown **instead of** `--:--` placeholders for National Holiday days
- The holiday row layout adapts dynamically to the current table width and weekday display mode
- Meta values are Unicode-safe: filtered, concatenated, and truncated with a trailing `…` when needed

### πŸ“₯ JSON / CSV holiday import (v0.8.3)


See the **Import data** section below for full documentation.

---

## ✨ Features


* Event-based time tracking (IN / OUT)
* Multiple working positions:

    * `O` Office
    * `R` Remote
    * `C` Client / On-site
    * `N` National holiday
    * `H` Holiday
    * `S` Sick Leave
    * `M` Mixed
* Automatic calculation of:

    * expected exit
    * daily surplus
* Configurable lunch rules
* Event mode with:

    * pairing
    * per-pair summaries
    * JSON output
    * unmatched detection
* Internal audit log
* Safe database migrations with automatic backups
* Cross-platform (Linux, macOS, Windows)

---

## πŸ“¦ Installation


### πŸ¦€ Cargo (recommended)


```bash
cargo install rtimelogger
```

### 🐧 Arch Linux (AUR)


```bash
yay -S rtimelogger
# or

paru -S rtimelogger
```

### 🍺 Homebrew (macOS / Linux)


```bash
brew tap umpire274/tap
brew install rtimelogger
```

### πŸ§πŸ“¦ Linux (Debian / Ubuntu)


Starting from **v0.8.0**, rTimelogger provides an official **`.deb` package**.

You can install it directly from the GitHub Releases page:

```bash
sudo dpkg -i rtimelogger_<version>_amd64.deb
```

To verify integrity, download the corresponding `.sig` file and verify it with GPG (see below).

```bash
sha256sum -c rtimelogger_<version>_amd64.deb.sha256
gpg --verify rtimelogger_<version>_amd64.deb.sig
```

If dependencies are missing, complete the installation with:

```bash
sudo apt --fix-broken install
```

### πŸ§πŸ”§ Other Linux distros


You can still use the prebuilt tarball:

```bash
tar -xvf rtimelogger-<version>-x86_64-unknown-linux-gnu.tar.gz
sudo mv rtimelogger /usr/local/bin/
```

### 🍎 macOS


You can use the prebuilt tarballs for Intel or Apple Silicon:

```bash
tar -xvf rtimelogger-<version>-x86_64-apple-darwin.tar.gz
sudo mv rtimelogger /usr/local/bin/
```

or

```bash
tar -xvf rtimelogger-<version>-aarch64-apple-darwin.tar.gz
sudo mv rtimelogger /usr/local/bin/
```

### πŸͺŸ Windows


Download the prebuilt zip file, extract it, and move `rtimelogger.exe` to a directory in your `PATH`, e.g.,
`C:\Windows\System32\` or create a dedicated folder like `C:\Program Files\rtimelogger\` and add it to your system
`PATH`.

---

## βš™οΈ Configuration


Initialize configuration and database:

```bash
rtimelogger init
```

Example `rtimelogger.conf`:

```yaml
database: /home/user/.rtimelogger/rtimelogger.sqlite
default_position: O
min_work_duration: 8h
lunch_window: 12:30-14:00
min_duration_lunch_break: 30
max_duration_lunch_break: 90
separator_char: "-"
show_weekday: None   # None | Short | Medium | Long
```

Override database path at runtime:

```bash
rtimelogger --db /custom/path/db.sqlite <command>
```

---

## 🧭 Main commands overview


| Command  | Description                                |
|----------|--------------------------------------------|
| `init`   | Initialize DB and config                   |
| `add`    | Add or edit IN / OUT events                |
| `list`   | Show sessions, events, or details          |
| `del`    | Delete events or pairs (with confirmation) |
| `backup` | Backup database (optional compression)     |
| `export` | Export data (CSV / JSON / XLSX / PDF)      |
| `db`     | Database utilities                         |
| `config` | Manage configuration file                  |
| `log`    | Show internal audit log                    |

---

## βž• Add work sessions β€” `rtimelogger add`


```bash
rtimelogger add <DATE> [OPTIONS]
```

Examples:

```bash
rtimelogger add 2025-12-15 --in 09:00
rtimelogger add 2025-12-15 --out 17:30
rtimelogger add 2025-12-15 --in 09:00 --lunch 30 --out 17:30
rtimelogger add 2025-12-15 --edit --pair 1 --out 18:00
rtimelogger add 2025-12-15 --out 10:30 --work-gap
rtimelogger add 2025-12-15 --edit --pair 2 --no-work-gap
rtimelogger add 2025-12-25 --pos n
rtimelogger add 2025-03-10 --pos s
rtimelogger add 2025-03-10 --pos s --to 2025-03-14
```

### πŸ“Œ Day positions


rTimelogger supports multiple day positions to describe how a working day (or non-working day) is classified.

**Supported positions**

| Code | Name             | Description                                                   |
|------|------------------|---------------------------------------------------------------|
| `O`  | Office           | Regular office working day                                    |
| `R`  | Remote           | Remote working day                                            |
| `C`  | On-site          | Working day at customer site                                  |
| `M`  | Mixed            | Mixed working locations                                       |
| `H`  | Holiday          | Personal holiday (counts against personal leave allowance)    |
| `N`  | National holiday | Public holiday (does **not** affect personal leave allowance) |
| `S`  | Sick Leave       | Sick day (non-working marker, does not reduce holiday budget) |

### βž• Adding a national holiday


To mark a **public/national holiday**, use the `add` command with the national position.

```bash
rtimelogger add 2025-12-25 --pos n
```

or

```bash
rtimelogger add 2025-12-25 --pos national
```

**Behavior**

- No `--in`, `--out`, `--lunch`, or `--work-gap` parameters are allowed
- The day is recorded as a non-working public holiday
- The day does not contribute to worked time
- The day does not reduce personal holiday allowance

### πŸ“‹ List output behavior


**National holiday days**

In both standard and compact list views:

- All time-related fields are displayed as `--:--`
- Target end (`TGT`) is not computed
- Worked delta (`Ξ”WORK`) is neutral (`-`)
- The day is clearly labeled as **National holiday**

Example:

```text
2025-12-25 (Thu) | National holiday | --:-- | --:-- | --:-- | --:-- | -
```

### βš–οΈ Holiday vs National holiday


| Aspect                   | Holiday (`H`) | National holiday (`N`) |
|--------------------------|---------------|------------------------|
| Working day              | ❌             | ❌                      |
| Counts as personal leave | βœ…             | ❌                      |
| Expected time            | ❌             | ❌                      |
| Ξ”WORK contribution       | ❌             | ❌                      |
| Requires time entries    | ❌             | ❌                      |

---

### πŸ€’ Adding a sick leave day


To mark a **sick leave day**, use the `add` command with the sick leave position.

```bash
rtimelogger add 2025-03-10 --pos s
```

To mark a **sick leave range** (e.g. a week), add the `--to` option:

```bash
rtimelogger add 2025-03-10 --pos s --to 2025-03-14
```

**Behavior**

- No `--in`, `--out`, `--lunch`, or `--work-gap` parameters are allowed
- The day (or range) is recorded as a non-working sick leave marker
- Weekends, national holidays, and dates that already contain events are automatically skipped
- Sick leave days do not contribute to worked time and are not deducted from personal holiday allowance

**Output example**

```text
2025-03-10 (Mon) | Sick Leave | --:-- | --:-- | --:-- | --:-- | -
```

---

### πŸ“ Adding notes to a pair


You can attach notes when creating or editing a pair:

```bash
rtimelogger add 2025-12-15 --in 09:00 --notes "Morning setup and backlog review"
```

Edit an existing pair:

```bash
rtimelogger add 2025-12-15 --edit --pair 1 --notes "Extended debugging session"
```

Edit without specifying a pair:

```bash
rtimelogger add 2025-12-15 --edit --notes "End of day summary"
```

➑️ Notes will be applied automatically to the last available pair.

**Behavior**

- Notes are stored as plain text
- They are optional
- They do not affect time calculations

---

## πŸ“‹ Listing sessions β€” `rtimelogger list`


The `list` command displays saved work sessions, supporting multiple layouts and levels of detail.

### **Basic usage**:


```bash
rtimelogger list                     # current month
```

Shows the sessions for the current month using the default tabular layout.

### πŸ“… **Supported periods**


```bash
rtimelogger list --period 2025-12
rtimelogger list --period 2025
rtimelogger list --period 2025-12-01
rtimelogger list --period 2025-12-01:2025-12-31
rtimelogger list --period all
```

### πŸ“† **Weekday display**


The weekday is shown inside the date column, using the format:

```text
YYYY-MM-DD (Mo)
YYYY-MM-DD (Monday)
```

The format is controlled by the show_weekday configuration option:

| Value    | Output example        |
|----------|-----------------------|
| `none`   | `2025-12-19`          |
| `short`  | `2025-12-19 (Mo)`     |
| `medium` | `2025-12-19 (Mon)`    |
| `long`   | `2025-12-19 (Monday)` |

### πŸ“Š Standard output


```bash
rtimelogger list --period 2025-12
```

Example:

```text
DATE (WD)        | POSITION        |  IN   | LNCH  |  OUT  |  TGT  |  Ξ”WORK
---------------------------------------------------------------------------
2025-12-19 (Fr)  | Remote          | 08:55 | 00:30 | 18:27 | 17:01 | -02h04m
```

**Columns explained**:

- **IN** – first check-in of the day
- **LNCH** – total lunch break duration
- **OUT** – last check-out
- **TGT** – planned exit time (minimum required work time)
- **Ξ”WORK** – worked surplus or deficit

### 🧾 Pair details (--details)


```bash
rtimelogger list --period 2025-12-19 --details
```

Displays the **individual** IN/OUT pairs for the selected day. It is available **only** for single-day periods or
`--today`.

**Output example**:

```text
DETAILS
PAIR |  IN   |  OUT  | WORKED | LUNCH | POSITION | WG
------------------------------------------------------
  1  | 08:55 | 09:37 | 00h42m |  0m   | Remote   |
  2  | 13:07 | 18:27 | 04h50m | 30m   | Remote   |
```

**Columns explained**:

- **PAIR** – pair index
- **IN** / **OUT** – timestamps for the pair
- **WORKED** – worked time for the pair
- **LUNCH** – lunch break for the pair
- **POSITION** – position for the pair
- **WG** – working gap indicator (πŸ”— for working gap, βœ‚οΈ for non-working gap)

#### πŸ“ Notes rendering


When notes are present, an additional section is displayed:

Λ†Λ†text
NOTES
------------------------------------------------------------------------
Fixed production bug, performed root cause analysis and deployed patch
Λ†Λ†Λ†

**Behavior**

- Notes are shown only in `--details` mode
- Automatically wrapped at 72 characters
- Preserves indentation and CLI formatting

### πŸ“¦ Compact view (--compact)


```bash
rtimelogger list --period 2025-12 --compact
```

Shows a condensed, single-line-per-day view, suitable for long periods.

Example:

```text
DATE (WD)        | POSITION | IN / LNCH / OUT       | TGT   | Ξ”WORK
--------------------------------------------------------------------
2025-12-19 (Fr)  | Remote   | 08:55 / 00:30 / 18:27 | 17:01 | Ξ” -02h04m
2025-12-22 (Mo)  | Holiday  | --:-- / --:-- / --:-- | --:-- | Ξ” -
```

**Characteristics**:

- compact horizontal layout
- weekday forced to short format
- no pair details

> ⚠️ `--compact` **cannot be combined** with `--details`

### Events listing (--events)


```bash
rtimelogger list --period 2025-12-15 --events
```

Displays the raw IN / OUT events for the selected day.

**Output example**:

```text
EVENTS:

     Date Time     | Type |    Lunch     |     Position     | Source | Pair | Work Gap
----------------------------------------------------------------------------------------
β†’ 2025-12-19 08:55 |   in | lunch  0 min | Remote           |  cli   |   1  |
             09:37 |  out | lunch  0 min | Remote           |  cli   |   1  |
             13:07 |   in | lunch  0 min | Remote           |  cli   |   2  |
             18:27 |  out | lunch 30 min | Remote           |  cli   |   2  |
```

### πŸ–οΈ Holiday days


Days marked as **Holiday**:

- display no time values (--:--)
- do not affect surplus calculations
- are rendered as neutral rows

### βž• Period total


At the end of the output, a cumulative total is always displayed:

```text
Ξ£ Total Ξ”WORK: +02h04m
```

The total accounts for:

- lunch breaks
- work gaps
- holidays (neutral contribution)

### πŸ”’ JSON output (--json)


```bash
rtimelogger list --period 2025-12 --json
```

Outputs the data in JSON format for easy integration with other tools or scripts.

---

## πŸ—‘οΈ Delete data β€” `rtimelogger del`


```bash
rtimelogger del 2025-12-15
rtimelogger del --pair 2 2025-12-15
```

All deletions require confirmation and automatically reindex pairs.

---

## πŸ’Ύ Backup database β€” `rtimelogger backup`


```bash
rtimelogger backup --file /abs/path/backup.sqlite
rtimelogger backup --file /abs/path/backup.sqlite --compress
```

* confirmation before overwrite
* ZIP on Windows
* TAR.GZ on Linux/macOS

---

## πŸ“€ Export data β€” `rtimelogger export`


```bash
rtimelogger export --format pdf --file /abs/path/report.pdf --range 2025-12
```

Supported formats:

* `csv`
* `json`
* `xlsx`
* `pdf`

Output path must be **absolute**.

---

## Import data (JSON / CSV)


Starting from **v0.8.3**, rTimelogger supports importing work sessions and holidays from external files.  
This feature is designed to simplify **preventive data entry**, especially for **national holidays**.

The import system is safe by default and provides a full **dry-run mode**.

---

### Supported formats


#### JSON


Flexible JSON structures are supported. The following formats are valid:

**Root object with `holidays`:**

```json
{
  "year": 2026,
  "holidays": [
	{
	  "date": "2026-01-01",
	  "name": "New Year"
	},
	{
	  "date": "2026-01-06",
	  "name": "Epiphany"
	}
  ]
}
```

**Root object with `days`:**

```json
{
  "days": [
	{
	  "date": "2026-05-01",
	  "position": "N",
	  "name": "Labour Day"
	}
  ]
}
```

**Root array of day objects:**

```json
[
  {
	"date": "2026-12-25",
	"name": "Christmas Day"
  }
]

```

**Notes**:

- `position` is optional:
    - if omitted, it defaults to `NationalHoliday`
- `name` is optional and stored in the event `meta` field

#### CSV


CSV files must include a header row.

Example:

```csv
date,position,name
2026-01-01,N,New Year
2026-01-06,N,Epiphany
2026-04-25,N,Liberation Day
```

**Notes**:

- `position` must be a valid location code (`N`, `H`, `O`, `R`, `C`, `M`)
- name is optional

### Import command


```bash
rtimelogger import --file <path> [options]
```

**Options**

- `--file <path>` : Path to the input file (required)

- `--format <json|csv>` : Input format (default: json)

- `--dry-run` : Simulate the import without modifying the database (strongly recommended)

- `--replace` : Replace existing events for conflicting dates (dangerous)

- `--source <label>` : Logical label describing the origin of imported data. The final stored value will include the
  format automatically (e.g. import (from json))

### Import behavior


- Only Holiday and NationalHoliday positions are accepted by default.
- Dates with existing work events are skipped unless --replace is used.
- Imported holidays:
    - do **not** affect the vacation balance
    - are treated as regular timeline entries

- Each import generates a detailed summary:
    - total rows
    - imported
    - skipped
    - conflicts
    - invalid rows

### Example (dry-run)


```bash
rtimelogger import \
  --file holidays_2026.json \
  --format json \
  --dry-run
```

### Example (apply import)


```bash
rtimelogger import \
  --file holidays_2026.csv \
  --format csv \
  --source calendar
```

### Metadata and traceability


- Imported events store additional information in the meta field (JSON).
- The source field tracks the origin of the data:
    - CLI entries β†’ cli
    - Imports β†’ import (from json) / import (from csv)

This ensures full traceability of all events.

---

## πŸ—„οΈ Database utilities β€” `rtimelogger db`


```bash
rtimelogger db --info
rtimelogger db --check
rtimelogger db --vacuum
rtimelogger db --migrate
```

---

## βš™οΈ Configuration management β€” `rtimelogger config`


```bash
rtimelogger config --print
rtimelogger config --edit
rtimelogger config --migrate
```

Missing fields are added automatically with defaults.

---

## πŸ“œ Internal audit log β€” `rtimelogger log`


```bash
rtimelogger log --print
```

Shows timestamped internal operations (add, del, migrate, backup, …).

---

## πŸ”„ Upgrading from older versions


If you are upgrading from **0.7.x or earlier**, read:

➑️ **[UPGRADE-0.7-to-0.8.md](UPGRADE-0.7-to-0.8.md)**

This document explains:

* schema changes
* migration behavior
* removed legacy features
* important behavioral differences

---

## πŸ“š Documentation


* πŸ“„ [CHANGELOG.md]CHANGELOG.md
* πŸ”„ [UPGRADE-0.7-to-0.8.md]UPGRADE-0.7-to-0.8.md

---

## πŸ“œ License


MIT License – see [LICENSE](LICENSE).