Skip to content

moonD4rk/things3

Folders and files

NameName
Last commit message
Last commit date

Latest commit

�?

History

43 Commits
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?
�?

Repository files navigation

things3

Go CI codecov Go Reference Go Report Card License

Go library and CLI for Things 3 on macOS. Read tasks from the Things 3 SQLite database, create and update items via Things URL Scheme, and query your task list from the terminal.

Features

  • Unified client - Single NewClient() entry point for all operations
  • Database queries - Read-only access to the Things 3 SQLite database with fluent query builder and type-safe filters
  • URL Scheme - Create todos, projects, and batch operations; update existing items with automatic authentication token management
  • CLI - Query tasks, projects, areas, and tags from the terminal with JSON/YAML output
  • Interface-based API - All public methods return interfaces for clean, testable code

CLI

A command-line tool for querying your Things 3 tasks from the terminal.

Installation

Homebrew (recommended):

brew install moond4rk/tap/things3

Go:

go install github.com/moond4rk/things3/cmd/things3@latest

Note: Requires CGO enabled (uses go-sqlite3). macOS only.

Manual: Download pre-built binaries from GitHub Releases. If macOS shows "Apple could not verify", remove the quarantine attribute:

xattr -d com.apple.quarantine /path/to/things3

Commands

things3 list <view>            # List tasks from a view
things3 search <query>         # Search tasks by title
things3 search --uuid <prefix> # Search tasks by UUID prefix
things3 version                # Print version information

Available views: inbox, today, upcoming, anytime, someday, logbook, deadlines, projects, areas, tags

Global Flags

Flag Short Description
--json -j Output as JSON
--yaml -y Output as YAML
--limit -n Max items to display (0 for unlimited)

The logbook view also supports --days (-d) to limit results to recent N days (default: 30, 0 for all).

Examples

things3 list today              # Today's tasks
things3 list inbox --json       # Inbox as JSON
things3 list logbook --days 7   # Recent 7 days
things3 search meeting          # Search by title
things3 search --uuid 4fthuhgF  # Search by UUID prefix
things3 list areas --yaml       # Areas as YAML
things3 list projects -n 5      # First 5 projects

Output Formats

Default (table):

STATUS   UUID      TYPE     TITLE
[x]      4fthuhgF  project  Task title | 2024-01-15 | #tag1 #tag2
[ ]      WZR4hDw5  todo     Another task | due:2024-02-01
[-]      gjUph7Jz  todo     Canceled task | 2024-01-10

Status indicators: [ ] incomplete, [x] completed, [-] canceled.

JSON (--json): Full task objects as a JSON array.

YAML (--yaml): Full task objects in YAML format.

Library

Installation

go get github.com/moond4rk/things3

Note: Requires CGO enabled (uses go-sqlite3). macOS only.

Quick Start

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/moond4rk/things3"
)

func main() {
    client, err := things3.NewClient()
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    ctx := context.Background()

    // Get today's tasks
    today, _ := client.Today(ctx)
    for _, task := range today {
        fmt.Printf("- %s\n", task.Title)
    }

    // Create a new todo
    client.AddTodo().
        Title("Buy groceries").
        Notes("Milk, eggs, bread").
        When(things3.Today()).
        Execute(ctx)
}

API Overview

Query Operations

Convenience Methods
client.Inbox(ctx)                      // Tasks in Inbox
client.Today(ctx)                      // Today's tasks
client.Upcoming(ctx)                   // Scheduled future tasks
client.Anytime(ctx)                    // Anytime tasks
client.Someday(ctx)                    // Someday tasks
client.Logbook(ctx)                    // Completed/canceled tasks
client.Trash(ctx)                      // Trashed tasks
client.Todos(ctx)                      // All incomplete to-dos
client.Projects(ctx)                   // All incomplete projects
client.Deadlines(ctx)                  // Tasks with deadlines
client.Search(ctx, "query")            // Search tasks
client.CreatedWithin(ctx, DaysAgo(7))  // Tasks from last 7 days
Fluent Query Builder
// Type-safe status filtering
tasks, _ := client.Tasks().
    Type().Todo().
    Status().Incomplete().
    All(ctx)

// Date filtering
tasks, _ := client.Tasks().
    StartDate().Future().
    Deadline().OnOrBefore(time.Now().AddDate(0, 0, 7)).
    All(ctx)

// Filter by area, project, or tag
tasks, _ := client.Tasks().
    InArea("area-uuid").
    InTag("work").
    All(ctx)

// Get single task or count
task, _ := client.Tasks().WithUUID("task-uuid").First(ctx)
count, _ := client.Tasks().Status().Completed().Count(ctx)
Areas and Tags
// Get all areas with their tasks
areas, _ := client.Areas().IncludeItems(true).All(ctx)

// Get all tags
tags, _ := client.Tags().All(ctx)

Add Operations

Create Todo
client.AddTodo().
    Title("Task title").
    Notes("Task notes").
    When(things3.Today()).              // today's date
    Deadline(time.Date(2024, 12, 31, 0, 0, 0, 0, time.Local)).
    Tags("work", "urgent").
    ChecklistItems("Step 1", "Step 2").
    List("Project Name").               // or ListID("project-uuid")
    Reveal(true).
    Execute(ctx)
Create Project
client.AddProject().
    Title("New Project").
    Notes("Project description").
    Area("Work").                       // or AreaID("area-uuid")
    Tags("important").
    Deadline(time.Date(2024, 12, 31, 0, 0, 0, 0, time.Local)).
    Todos("Task 1", "Task 2", "Task 3"). // child todos
    Execute(ctx)

Update Operations

Update operations automatically manage authentication tokens.

// Update a todo
client.UpdateTodo("todo-uuid").
    Title("Updated title").
    Completed(true).
    AddTags("done").
    Execute(ctx)

// Update a project
client.UpdateProject("project-uuid").
    Notes("Updated notes").
    Canceled(true).
    Execute(ctx)

Show Operations

client.Show(ctx, "item-uuid")                    // Show specific item
client.ShowList(ctx, things3.ListToday)          // Show Today view
client.ShowSearch(ctx, "urgent tasks")           // Show search results

// Complex navigation
client.ShowBuilder().
    List(things3.ListInbox).
    Filter("work", "urgent").
    Execute(ctx)

Batch Operations

// Create multiple items at once
client.Batch().
    AddTodo(func(t things3.BatchTodoConfigurator) {
        t.Title("Task 1").Tags("work")
    }).
    AddTodo(func(t things3.BatchTodoConfigurator) {
        t.Title("Task 2").When(things3.Today())
    }).
    AddProject(func(p things3.BatchProjectConfigurator) {
        p.Title("New Project").Notes("Description")
    }).
    Reveal(true).
    Execute(ctx)

Configuration

// Use custom database path
client, _ := things3.NewClient(
    things3.WithDatabasePath("/path/to/main.sqlite"),
)

// Enable SQL logging for debugging
client, _ := things3.NewClient(
    things3.WithPrintSQL(true),
)

// Control Things app focus behavior
client, _ := things3.NewClient(
    things3.WithForeground(),        // Bring Things to foreground (default for show)
    things3.WithBackground(),        // Run in background without stealing focus
)

// Preload authentication token
client, _ := things3.NewClient(
    things3.WithPreloadToken(),
)

Database Discovery

The database path is resolved in order:

  1. Custom path via WithDatabasePath()
  2. THINGSDB environment variable
  3. Default: ~/Library/Group Containers/JLMPQHK86H.com.culturedcode.ThingsMac/Things Database.thingsdatabase/main.sqlite

Types

// Task types
things3.TaskTypeTodo     // 0 - To-do item
things3.TaskTypeProject  // 1 - Project
things3.TaskTypeHeading  // 2 - Heading

// Status
things3.StatusIncomplete // 0
things3.StatusCanceled   // 2
things3.StatusCompleted  // 3

// Start bucket
things3.StartInbox    // 0
things3.StartAnytime  // 1
things3.StartSomeday  // 2

// Date helper functions
things3.Today()       // returns today's date at midnight
things3.Tomorrow()    // returns tomorrow's date at midnight

// Scheduling methods (called on builders)
.When(time.Time)      // schedule for specific date
.WhenEvening()        // schedule for this evening
.WhenAnytime()        // schedule for anytime (no specific date)
.WhenSomeday()        // schedule for someday (indefinite future)

// List IDs for navigation
things3.ListInbox
things3.ListToday
things3.ListUpcoming
things3.ListAnytime
things3.ListSomeday
things3.ListLogbook
things3.ListTrash

References

License

Apache License 2.0

About

Go library for Things 3 on macOS - database access and URL Scheme support

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages