Announcing taskchampion-rb

by Tim Case

I have been working on taskchampion-rb, a Ruby binding for TaskChampion, the task database engine that powers Taskwarrior. The goal is straightforward: make TaskChampion’s durable, synchronizable task storage available to Ruby programs without making Ruby developers leave the shape and idioms of Ruby behind.

TaskChampion itself is written in Rust. It provides the storage and sync model behind modern Taskwarrior: local-first task replicas, operations that can be synchronized between clients, and a data model designed for task properties such as status, priority, tags, dates, annotations, user defined attributes, dependencies, and history. taskchampion-rb wraps that core and exposes it as a native Ruby gem.

With the v0.9.0 release, the gem has grown far enough that it is useful for real experiments and early applications. This release adds support for removing and updating task annotations, filling in one more piece of the task editing workflow.

What it does

At its core, taskchampion-rb lets Ruby code open a TaskChampion replica, create and modify tasks, commit those changes, query stored tasks, and sync task data through TaskChampion’s storage model.

The API is intentionally Ruby-shaped. Methods use snake_case, predicate methods end in ?, status and access-mode values are exposed in a way that feels natural from Ruby, and missing values come back as nil.

For example:

require "taskchampion"
require "securerandom"

replica = Taskchampion::Replica.new_on_disk("tasks", true, :read_write)
operations = Taskchampion::Operations.new

task = replica.create_task(SecureRandom.uuid, operations)
task.set_description("Try taskchampion-rb", operations)
task.set_status(Taskchampion::Status.pending, operations)
task.set_priority("H", operations)
task.add_tag(Taskchampion::Tag.new("ruby"), operations)
task.add_annotation("Created from Ruby", operations)

replica.commit_operations(operations)

That operations object is important. Task changes are collected as operations and then committed to the replica, matching TaskChampion’s underlying model. This makes the Ruby API a wrapper around the real data engine rather than a parallel reimplementation of task storage.

What it is good for

taskchampion-rb is useful anywhere Ruby needs to work with Taskwarrior- style task data directly.

It can be used to build command-line tools that read or modify a task database, automation scripts that create tasks from external systems, small web applications for viewing or triaging tasks, background jobs that process task metadata, or integration code that needs the same task storage semantics as Taskwarrior.

Because it uses TaskChampion underneath, the gem is especially interesting for local-first tools. A Ruby application can work against an on-disk replica, make changes offline, and sync those changes later. It can also use in-memory replicas for tests, experiments, and short-lived workflows.

The gem already supports the pieces needed for a broad task workflow:

That last point matters for native bindings. The Rust core has its own ownership and safety constraints, and the Ruby wrapper makes those constraints explicit. Objects such as replicas, tasks, and operation collections belong to the thread that created them. If they are used from another thread, the gem raises a Taskchampion::ThreadError instead of allowing surprising shared-state behavior.

Why build it

Taskwarrior has a long history as a reliable power-user task tool, and TaskChampion is the reusable engine that makes its newer storage model available outside the Taskwarrior binary itself. Ruby has a strong tradition of small tools, integration scripts, web apps, and developer- friendly libraries. taskchampion-rb is meant to connect those worlds.

I want Ruby developers to be able to build against TaskChampion without having to shell out to another command, parse command output, or maintain a separate task database format. A Ruby program should be able to open a replica, inspect tasks, apply changes, and sync them using the same core engine that Taskwarrior uses.

Where it stands

This is still an early project, but v0.9.0 is a useful milestone. The core binding structure is in place, the main task and replica APIs are available, operations are exposed, sync workflows are represented, and annotations can now be added, updated, and removed.

There is still work ahead: broader API coverage, more documentation, cross-platform polish, and the kind of hardening that comes from real applications using the gem. But the shape is there now. Ruby can talk to TaskChampion directly, and that opens the door to a much wider set of Taskwarrior-compatible tools.

The project is available on GitHub at https://github.com/timcase/taskchampion-rb.