CLI Tool


It's a good idea to customize your config file at ~/.config/tasklite/config.yaml before starting to use TaskLite.

Check out the example config file for infos about available settings.


For a full overview of all supported subcommands run:

tasklite help

Screenshot of CLI output of help command


To add a task run:

tl add Improve the TaskLite manual

It is also possible to immediately add tags when creating a task:

tl add Improve the TaskLite manual +tasklite +pc

And even to set certain fields:

tl add Buy milk +groceries due:2020-09-01 created:2020-08-27

Attention: The tags and special commands must be the last parameters, but their order doesn't matter.


Existing tasks can be easily edited in their YAML representation:

tl edit 01hwcw6s1kzakd5pje218zmtpt

This will open your default editor, as specified in the environment variables $VISUAL or $EDITOR. You can then easily edit existing fields and add new fields.

This feature allows for a powerful batch editing workflow. Use an SQL query to select a subsection of your tasks and then edit all of them one by one:

sqlite3 \
  ~/TaskLite/main.db \
  "SELECT ulid FROM tasks WHERE metadata LIKE '%sprint%'" \
| while read ulid; do tl edit $ulid; done

Context / Views

There is no first class support for views (or "context" in GTD slang), because it can be easily implemented with aliases / custom CLI commands and the SQL query API.

For example I have following work command in my $PATH:

#! /usr/bin/env bash

tasklite query \
  "(tags is null or tags not like '%feram%') \
    and state is 'Open' \
    order by priority desc, due_utc asc, ulid desc \
    limit 10"

Analyze and Filter Tasks

In order to further analyze and filter tasks TaskLite includes the ndjson command, which prints all tasks as newline delimited JSON objects.

This output can then easily be analyzed and filtered with standard UNIX tools. E.g. following example prints all tasks related to music:

tl ndjson | grep 'music' | jq


TaskLite features a comprehensive and robust JSON importer.

For example to import a GitHub issue simply run:

curl$OWNER/$REPO/issues/$NUM | tl import

Or to import a task from TaskWarrior:

task 123 export | tl import

In order to avoid data loss of fields which aren't directly supported by TaskLite, the whole imported JSON object is also stored in TaskLite's task metadata field. However, if the original JSON object already has a metadata field, its value is used instead.


An import object's tags field must be of type [string], while a notes field must be of type {ulid?: string, body: string}.


TaskLite does not properly support importing tasks which were created before 1970. While they can be imported, the creation date is set to 1970-01-01.


Use one of following commands:

  • tl csv
  • tl ndjson
  • tl backup - Creates a backup at $TaskLiteDir/backups/YYYY-MM-DDtHHMM.db

Custom Views

The export commands in combination with other common CLI tools like csvkit can also be used for custom views of tasks.

tl csv \
| csvgrep --column tags --match tasklite \
| head -n 6 \
| csvcut --columns ulid,body,tags \
| csvlook --max-column-width 30


| ulid                       | body                           | tags     |
| -------------------------- | ------------------------------ | -------- |
| 01chk64zwwjyybanvk7016hyyg | Add a burndown chart view      | tasklite |
| 01chk6c08h70xra2awd8dngtr7 | Add multi user support         | tasklite |
| 01chk6dxaxttwfyg019d3g3sze | Add a statistics view          | tasklite |
| 01chk6f3sq1mrskgkt1046fz7q | Add a calendar view            | tasklite |
| 01chk6vnm30ttvwc1qkasjaktm | Publish the TaskLite git re... | tasklite |


The metadata field allows you to store additional data for each task which is not yet covered by TaskLite's core fields. It is stored as a JSON object and therefore supports all JSON datatypes.

This is similar to Taskwarrior's User Defined Attributes.

Metadata is especially useful for importing and migrating external tasks without losing any information.

If you, for example, want to import following task.json file, you will notice that it contains a field kanban-state, which has no equivalent in TaskLite:

  "created_at": "2020-02-08T20:02:32Z",
  "body": "Buy milk",
  "kanban-state": "backlog"

However, you can still simply import it, as the additional field will be stored in the metadata object:

$ tl import < task.json
📥 Imported task "Buy milk" with ulid "01e0k6a1p00002zgzc0845vayw"

Inspecting it:

$ tl info 01e0k6a1p00002zgzc0845vayw
awake_utc: null
review_utc: null
state: null
repetition_duration: null
recurrence_duration: null
body: Buy milk
user: adrian
ulid: 01e0k6a1p00002zgzc0845vayw
modified_utc: 1970-01-01T00:00:00Z
group_ulid: null
closed_utc: null
priority_adjustment: null
  body: Buy milk
  kanban-state: backlog
  created_at: 2020-02-08T20:02:32Z
waiting_utc: null
ready_utc: null
due_utc: null
priority: 0.0


To access the the metadata key programmatically you can do following:

$ tl ndjson \
  | grep 01e0k6a1p00002zgzc0845vayw \
  | jq -r '.metadata["kanban-state"]'

Or leverage SQL:

$ tl runsql "
    SELECT json_extract(metadata, '\$.kanban-state')
    FROM tasks
    WHERE ulid == '01e0k6a1p00002zgzc0845vayw'
  " \
  | tail -n 1

This can also be used to update metadata fields:

tl runsql "
    UPDATE tasks
    SET metadata=(
      SELECT json_set(tasks.metadata, '\$.kanban-state', 'sprint')
      FROM tasks
      WHERE ulid == '01e0k6a1p00002zgzc0845vayw'
    WHERE ulid == '01e0k6a1p00002zgzc0845vayw'

Another great use-case is to automatically extract and store data from the body of the task.

E.g. you could set up a CRON job to automatically extract any GitHub link from the body and store it in an extra github_url metadata field:

UPDATE tasks
SET metadata = json_insert(
  ifnull(metadata, '{}'),
  substr(body, instr(body, ''),
      WHEN instr(substr(body, instr(body, '')), ' ') == 0
      THEN length(substr(body, instr(body, '')))
      ELSE instr(substr(body, instr(body, '')), ' ') - 1
WHERE body LIKE '%'

External Commands

Like Git, TaskLite also supports external commands. This allows you to easily extend TaskLite's functionality with your own scripts.

For this to work, simply add an executable script (chmod +x) with the prefix tasklite- to your $PATH

For example, to add a grin command which simply prints a smiley:

$ cat /usr/local/bin/tasklite-grin
#! /usr/bin/env bash

echo '😁' "$@"

$ tasklite grin Hi
😁 Hi