Skip to main content

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​

{
"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​

NameTypeDefaultDescription
always_enabledbooleanfalseshow Not tracking while idle with the default template
annotation_max_lengthint48annotation's Unicode character limit; <= 0 disables it
commandstringtimewthe Timewarrior executable to use
ellipsisstring\u2026suffix for truncated annotations, included in the limit
tag_formatstring#%sGo format string applied to each tag
tag_separatorstring 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)​

default template
{{ 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​

NameTypeDescription
.Activebooleanwhether an open interval is being tracked
.Annotationstringinterval annotation, limited by annotation_max_length
.Durationstringelapsed duration, truncated to seconds, e.g. 1h30m0s
.Starttime.Timeopen interval's start in UTC
.Tagsstringformatted 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 }}