Metadata-Version: 2.4
Name: worklog-markdown
Version: 0.2.0
Summary: Work log parser and time aggregator
Requires-Python: >=3.11
Requires-Dist: confuk
Requires-Dist: openpyxl
Requires-Dist: pandas
Requires-Dist: rich
Requires-Dist: tabulate
Requires-Dist: typer
Description-Content-Type: text/markdown

# worklog

Parse Obsidian-style Markdown work logs and produce time-summary tables, broken down by project and day.

## Installation

Requires Python 3.11+. Install with `pip` or `pipx`:

```bash
pip install worklog-md
```

Install with [uv](https://docs.astral.sh/uv/):

```bash
uv sync
```

The `worklog` command is then available via `uv run worklog`.

## Work log format

Each file is a Markdown document. Days are delimited by H1 headings containing an ISO date. Entries live under a `## Work Log` subsection (configurable).

```markdown
# 2026-01-05

## Work Log

- 8:30 - 9:30 Morning standup [project:: Alpha]
- 10:00 - 11:30 [[Feature branch|Feature work]] [project:: Beta]
- 1h Code review [project:: Alpha]
- 20m Email triage [project:: Alpha] [worklog:: skip-comments]
- 30m Off-the-record meeting [project:: Beta] [worklog:: skip]
```

### Entry formats

Time can be expressed as a clock range or a duration:

| Format | Example |
| --- | --- |
| Clock range | `8:30 - 9:30` |
| Hours | `1h` |
| Minutes | `20m` |
| Hours and minutes | `1h30m` or `1h 30m` |

### Inline tags

All tags use Obsidian's inline field syntax `[key:: value]`.

| Tag | Effect |
| --- | --- |
| `[project:: Name]` | Required. Associates the entry with a project column. |
| `[worklog:: skip-comments]` | Time is counted but the description is omitted from the comments cell. |
| `[worklog:: skip]` | Entry is ignored entirely — no time, no comments. |

### Obsidian wiki-links

Wiki-links in descriptions are resolved automatically:

- `[[some page\|human readable]]` → `human readable`
- `[[some page]]` → `some page`

### Obsidian comments

`%% ... %%` blocks (both inline and multi-line) are stripped before parsing.

## Configuration

The config file can be TOML, JSON, or YAML. All keys are optional.

```toml
[schema]
# Explicit project list determines column order and filters out anything else.
# Omit to auto-detect all projects that appear in the log files.
projects = ["Alpha", "Beta"]

# Cell values: "hours" (default, decimal) or "minutes" (integer)
time_unit = "hours"

[parser]
# H2 heading that marks the work log section. Default: "Work Log"
work_log_heading = "Work Log"
```

## Usage

```text
worklog [OPTIONS] FILES...
```

| Option | Short | Description |
| --- | --- | --- | --- |
| `--config PATH` | `-c` | Config file path (`.config/worklog.toml` by default) |
| `--format TEXT` | `-f` | Stdout format: `markdown` (default), `csv`, `tsv` |
| `--output PATH` | `-o` | Write to file; format inferred from extension |

Supported output extensions: `.csv`, `.tsv`, `.md`, `.xlsx`.

### Examples

Print a Markdown table to stdout:

```bash
uv run worklog 2026-01.md -c worklog.toml
```

Combine multiple log files:

```bash
uv run worklog jan.md feb.md mar.md -c worklog.toml
```

Export to Excel:

```bash
uv run worklog 2026-01.md -c worklog.toml -o report.xlsx
```

Write CSV to stdout:

```bash
uv run worklog 2026-01.md -c worklog.toml -f csv
```

### Output schema

| Column | Content |
| --- | --- |
| `date` | ISO date string (`YYYY-MM-DD`) |
| `<project>` | Total hours (or minutes) logged for that project on that day |
| `comments` | Descriptions from all entries, grouped by project: `[Alpha] task A; task B \| [Beta] task C` |

## Running tests

```bash
uv run pytest
```

## Project layout

```text
worklog/
  models.py      — LogEntry and DayLog dataclasses
  parser.py      — Markdown parser (comment stripping, wiki-link resolution, entry parsing)
  aggregator.py  — Builds the pandas DataFrame from parsed day logs
  cli.py         — Typer CLI (entry point: worklog command)
tests/
  test_parser.py
  test_aggregator.py
```
