TaskChampion implements the task storage and synchronization behind Taskwarrior. It includes an implementation with Rust and C APIs, allowing any application to maintain and manipulate its own replica. It also includes a specification for tasks and how they are synchronized, inviting alternative implementations of replicas or task servers.
See the documentation for more!
There are two crates here:
taskchampion(root of the repository) - the core of the toolxtask(private) - implementation of thecargo xtask msrvcommand
The Rust API, as defined in the docs, supports simple creation and manipulation of replicas and the tasks they contain.
The Rust API follows semantic versioning.
The pgwire storage backend uses SQLx compile-time query checks. CI verifies those
queries in offline mode using the committed .sqlx/ metadata.
After changing a sqlx::query!, sqlx::query_as!, or sqlx::query_scalar! call,
run this against a local backend schema and commit the updated .sqlx/ files:
./scripts/sqlx-prepare.shSet SQLX_POSTGRES_DATABASE_URL if your local database is not available at the
script default URL.
The ffi/ crate provides a UniFFI-based FFI layer for iOS and macOS consumption via SPM.
The public SwiftPM product remains TaskChampionFFI, so app code should still
use import TaskChampionFFI. The low-level binary target and release asset were
renamed from the legacy doubled-FFI name (TaskChampionFFIFFI) to
TaskChampionCore. Consumers that only add the TaskChampionFFI product do not
need code changes; consumers that referenced the binary target or release zip
directly should update those references to TaskChampionCore.xcframework.zip.
# macOS only: install cargo-swift once
cargo install cargo-swift@0.11.1 --locked
# Build the default static Swift package and TaskChampionCore XCFramework
./scripts/package_cargo_swift.sh
# Dynamic tags/releases are built with the same package shape:
TASKCHAMPION_FFI_LINKAGE=dynamic ./scripts/package_cargo_swift.sh target/cargo-swift-dynamicThis produces:
target/cargo-swift/TaskChampionFFI/TaskChampionCore.xcframework/— default static framework for iOS device, iOS simulator, and macOStarget/cargo-swift-dynamic/TaskChampionFFI/TaskChampionCore.xcframework/— dynamic framework when requestedtarget/cargo-swift/TaskChampionFFI/Sources/TaskChampionFFI/taskchampion_ffi.swift— generated Swift bindings
For local Xcode testing, point Package.swift at the built XCFramework instead
of the release zip:
./scripts/use_local_xcframework.sh target/cargo-swift/TaskChampionFFI/TaskChampionCore.xcframeworkRestore the release URL before committing release changes:
git restore Package.swift-
Add this repo as a git submodule:
git submodule add https://github.com/GuionAI/taskchampion.git vendor/taskchampion
-
Run the build script:
cd vendor/taskchampion cargo install cargo-swift@0.11.1 --locked ./scripts/package_cargo_swift.sh ./scripts/use_local_xcframework.sh target/cargo-swift/TaskChampionFFI/TaskChampionCore.xcframework -
In Xcode: Add Local Package → select
vendor/taskchampion/→ addTaskChampionFFIto your target. -
Import and use:
import TaskChampionFFI // Create a session once at login/startup let session = try FfiSession(executor: myExecutor, userId: userId) // All task operations are async let tasks = try await session.pendingTasks() let created = try await session.createTask(uuid: UUID().uuidString, description: "New task")