<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>
[](https://github.com/umpire274/rTimelogger/actions/workflows/ci.yml)
[](https://github.com/umpire274/rTimelogger/releases)
[](https://codecov.io/gh/umpire274/rTimelogger)
[](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
| `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**
| `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
### βοΈ Holiday vs National holiday
| 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
---
### π 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:
| `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
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
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
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
----------------------------------------------------------------------------------------
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).