Timewarrior
What
Display Timewarrior tracking status, active tags, annotation and elapsed time.
The segment is hidden when no interval is active unless always_enabled is set to true.
With always_enabled: true, the default template displays Not tracking while idle.
By default it displays a tracking icon, tags prefixed with # and joined by spaces, and an annotation separated by
" | ".
Use tag_format to format each tag with a Go format string; %s is replaced by the tag.
Untagged tracking uses \u2205; annotations longer than 48 Unicode characters end with \u2026.
Only open intervals are collected; completed intervals are ignored.
Requirements
Requires Timewarrior 1.3.0 or newer, which provides active-interval JSON, annotations, and interval IDs. Prefer the latest supported Timewarrior release.
Sample Configuration
- json
- yaml
- toml
{
"type": "timewarrior",
"style": "diamond",
"trailing_diamond": "",
"foreground": "#cdd6f4",
"background": "#000000",
"template": "{{ if .Active }} {{ if .Tags }}{{ .Tags }}{{ else }}{{ \"∅\" }}{{ end -}}\n{{ if .Annotation }} | {{ .Annotation }}{{ end }}\n{{- else }} Not tracking {{ end }}",
"options": {
"annotation_max_length": 48
}
}
type: timewarrior
style: diamond
trailing_diamond:
foreground: "#cdd6f4"
background: "#000000"
template: |-
{{ if .Active }} {{ if .Tags }}{{ .Tags }}{{ else }}{{ "∅" }}{{ end -}}
{{ if .Annotation }} | {{ .Annotation }}{{ end }}
{{- else }} Not tracking {{ end }}
options:
annotation_max_length: 48
type = "timewarrior"
style = "diamond"
trailing_diamond = ""
foreground = "#cdd6f4"
background = "#000000"
template = "{{ if .Active }} {{ if .Tags }}{{ .Tags }}{{ else }}{{ \"∅\" }}{{ end -}}\n{{ if .Annotation }} | {{ .Annotation }}{{ end }}\n{{- else }} Not tracking {{ end }}"
[options]
annotation_max_length = 48
Options
| Name | Type | Default | Description |
|---|---|---|---|
always_enabled | boolean | false | show Not tracking while idle with the default template |
annotation_max_length | int | 48 | annotation's Unicode character limit; <= 0 disables it |
command | string | timew | the Timewarrior executable to use |
ellipsis | string | \u2026 | suffix for truncated annotations, included in the limit |
tag_format | string | #%s | Go format string applied to each tag |
tag_separator | string | | text between tags |
annotation_max_length and ellipsis are applied to .Annotation when interval data is collected.
Tags, the untagged label, and separators are never truncated. The limit counts characters, not terminal cells.
tag_format and tag_separator format and join the tags before exposing them as .Tags.
The default template uses a fixed | separator before an annotation; customize the template to change it.
The ellipsis is shortened if it alone exceeds the limit. An empty ellipsis truncates without a suffix.
The segment checks timew get dom.active and, while tracking, reads the open interval using timew get dom.active.json.
This includes intervals started on a previous day without exporting any history.
Elapsed time updates when the prompt renders. Avoid segment caching if you need current tracking status and duration.
Missing executables, command failures and malformed output hide the segment, even with always_enabled.
Template (info)
{{ if .Active }} {{ "\\uf252" }} {{ if .Tags }}{{ .Tags }}{{ else }}{{ "\u2205" }}{{ end -}}
{{ if .Annotation }} | {{ .Annotation }}{{ end }}
{{- else }} Not tracking {{ end }}
Customize the template to change the icon or colors, include duration, or change the idle label.
The default template displays Not tracking while idle when always_enabled: true.
Properties
| Name | Type | Description |
|---|---|---|
.Active | boolean | whether an open interval is being tracked |
.Annotation | string | interval annotation, limited by annotation_max_length |
.Duration | string | elapsed duration, truncated to seconds, e.g. 1h30m0s |
.Start | time.Time | open interval's start in UTC |
.Tags | string | formatted tags joined by tag_separator |
When idle, interval properties have their zero values.
With always_enabled: true, the default template displays Not tracking; custom templates can change that label.
If tracking stops between the status check and the JSON lookup, the lookup can fail and hide the segment,
even with always_enabled. Any completed interval returned by the lookup is discarded without populating its data.
Examples
Use your palette and the default template:
[[blocks.segments]]
type = "timewarrior"
style = "diamond"
foreground = "p:darktext"
background = "p:black"
trailing_diamond = "\ue0c8"
[blocks.segments.options]
annotation_max_length = 48
ellipsis = "\u2026"
tag_format = "[%s]"
tag_separator = " "
This requires darktext and black entries in your theme's palette.
Show the annotation when present, falling back to tags:
{{ if .Active }}{{ if .Annotation }}{{ .Annotation }}{{ else }}{{ .Tags }}{{ end }} {{ .Duration }}{{ end }}
Show an idle indicator with always_enabled: true:
{{ if .Active }}{{ "\\uf252" }} {{ .Tags }}{{ else }}Not tracking{{ end }}