A deterministic task + dependency tracker for coding agents (SQLite + Pydantic, MCP + CLI).
Project description
tackit
A deterministic task + dependency tracker built for coding agents — with a CLI for humans too.
One local SQLite file is the single source of truth for a project's build plan: its tasks, their dependencies, and their reconciliation state. The agent fetches small slices on demand instead of re-reading monolithic plan documents, so project truth survives across sessions and context-window compaction, and a change to one task is traceable to everything that depends on it. A typed boundary refuses malformed data, and a reconcile-on-change discipline surfaces what each change invalidates.
Status: alpha (0.1.0). Data model, interfaces, and sync design are settled and implemented; 98% test coverage. Expect rough edges.
Contents
Everyone: Why it exists · Install · CLI for humans · Testing · License
🤖 Agents — read these, especially during install (a critical juncture): Start here · Configure your agent's settings · MCP tools
Why it exists
Coding agents lose the plot across long projects. They scatter task tracking across ad-hoc files that drift apart and start contradicting each other; they lose intermittent decisions when the context window compacts; they re-read large plan documents every session until context cost erodes accuracy; and they narrate dependency relationships by hand in prose that goes stale the moment something changes. tackit's job is narrowly correctness on the dev path — not knowledge retrieval — so it absorbs that scatter into one queryable, sliceable, single-source-of-truth store:
- One home per fact. Every view (board, status, rendered narrative) is derived, never hand-kept in parallel — so two copies can't come to disagree.
- Small slices. The unit of access is a task plus its direct links, not a whole document, so context cost stays bounded.
- Fail loud. Malformed data and illegal transitions are refused at the boundary, not silently absorbed.
- Traceable change. Editing a task flags everything that depends on it for review, so a change can't silently leave the rest of the plan wrong.
Install
Two parts. A human pulls the package; then the driving agent wires it in — that
second step is what actually registers the MCP server and the skill. pip install
alone does not make tackit usable by your agent.
1. Human — pull the package:
pip install tackit
2. Agent — register it:
tackit setup # prints the post-install steps; does NOT edit any config
tackit setup emits contextualized steps for the agent to carry out: register the
stdio MCP server in the agent's own config, drop the bundled SKILL.md into the
skills path, and run tackit init. The agent does the wiring because it knows where
its own config lives. 🤖 Agents: also do Configure your agent's
settings, and read For agents: start
here while you install.
For humans: the CLI
The CLI is the human door — debugging, scripting, and a fallback for the agent.
tackit --help (and tackit <cmd> --help) is the full, self-documenting surface.
tackit init # create .tackit/ in this project
tackit add "parse FTS5 query" --label search # create a task
tackit add "rank search results" --dep 1 # task 2 depends_on task 1
tackit search "fts" # ranked keyword search
tackit show 2 # slice: task + deps + dependents
tackit edit 1 --desc "tokenized MATCH" # marks task 1's dependents stale
tackit stale # the reconciliation worklist
tackit reconcile 2 # reviewed-OK; clear stale
tackit close 2 # refused while stale (or atop stale deps)
tackit ls --status open # query/board
The store lives at .tackit/tackit.db (binary, gitignored). Its git-canonical form
is a deterministic SQL text dump, .tackit/tackit.sql, re-written on every change and
committed — so diffs and merges are reviewable text, never a binary blob. Sync is
automatic; tackit status / export / import / restore exist only for the
divergence cases auto-sync deliberately refuses to guess at.
For agents: start here
If you are an agent installing or working in a tackit project, read this — install is
the moment to absorb it. But this is orientation, not the operating manual: the
complete, canonical discipline ships as SKILL.md (dropped into your skills path
during install and loaded whenever you work in a tackit project), and the tools state
your specific obligations in their own results. At work time, rely on those — not on
this page.
The model, in one breath. One item type — a task with a status (open/closed)
and a stale bit; one relationship — depends_on, traversed both ways; freeform
labels. Every view (board, status, narrative) is derived from these, never hand-kept
in parallel.
What SKILL.md holds you to (the short version — read it there in full):
- Single source of truth. Everything goes in tackit, via its tools — never ad-hoc markdown or TODO comments. If it isn't in tackit, it isn't tracked. It is not a knowledge base; durable learnings live in your memory.
- Reconcile on change. A change marks the task's dependents stale. tackit
surfaces the outstanding stale set on every call (deterministically — it's code in
the app, not a reminder you can skip). Review each stale task together with its
depends_onneighbors, theneditorreconcileit. Never end a turn while anything is stale — a task left closed atop a changed dependency is wrong and invisible. A stale task (or one that depends on a stale task) can't be closed. - Find, wire, right-size.
searchbefore you create; wire dependencies explicitly (including among tasks you add together); keep tasks describable units of work.
One convention is worth explaining in full right here — it's the one people skip and then regret, and it belongs in your always-on settings, not just in tackit:
Code ↔ task traceability (the opinionated bit)
tackit stores intent — what a task is, and why. Your code is the implementation. Nothing automatically connects the two: tackit can't see your code, and your code doesn't know which task it came from. The instant your context window resets, that connection is gone — unless you built it into how you wrote both. A future you, or another agent, looking at a function with no memory of why it exists, has no path back to the decision that created it.
So make the link yourself, on both sides:
- Name tasks so they're findable. Tasks are located by keyword
search. A task called "fix bug" or "update logic" is effectively invisible — it surfaces for no reasonable search, so its history and dependents become unrecoverable. Use distinctive, specific terms: the component, table, function, or feature ("rotate JWT signing keys on the auth token endpoint"), never vague verbs. - Mirror that vocabulary in the code, and cite the task id. When you implement
task
T42, referenceT42in the code and comments, and echo the task's distinctive words in file and function names. If the task says "token rotation," the code says "token rotation" — not "key cycling." Now asearchfrom either side lands on the other.
It's a small tax at write time that buys back the one thing a context reset destroys: the ability to recover why. Treat a vague task title, or a code↔task vocabulary mismatch, as a defect, not a style nit. Because this holds even when the tackit skill isn't loaded, put it in your agent's always-on settings too:
Configure your agent's settings
Add the tackit discipline to your agent's always-on instructions (CLAUDE.md for
Claude Code; the equivalent for other agents) so it holds even when the skill isn't
loaded — especially the code↔task traceability, which is global by nature. A starting
point:
## tackit
- tackit is this project's single source of truth for tasks + dependencies. If it
isn't in tackit, it isn't tracked. It is not a knowledge base.
- Code ↔ task traceability is MANDATORY. When you implement a tackit task, cite its
id (e.g. `T42`) and reuse the task's distinctive vocabulary in file/function names
and comments, so a future session can grep from code to intent and back. Treat a
vague task title or a code↔task vocabulary mismatch as a defect, not a style nit.
- Search before creating; wire dependencies explicitly (including among tasks added
together); right-size tasks to describable units of work.
- Reconcile on change: a change marks dependents stale. Review each stale task
against its `depends_on` neighbors, then `edit` or `reconcile`. Never end a turn
while anything is stale.
MCP tools
tackit mcp # serve the stdio MCP server (the agent's primary door)
The agent's primary door is the MCP server: the harness pushes typed tool schemas
into the agent's tool zone (no --help round-trip, no shell quoting, can't
hallucinate a flag that doesn't exist). Tool names are the bare verbs — add,
show, search, edit, close, reopen, reconcile, dep_add, dep_rm,
label_add, label_rm, ls, stale, render, history. Input schemas are
generated from the Python type hints, so they can't drift from the real interface.
Every result is wrapped as {stale_alert, result} so the outstanding stale set rides
along on every call; refusals (e.g. closing a stale task) come back as errors that
state the reason.
Testing
98% line coverage, 110 tests: unit, adapter integration (CLI and MCP driven
end-to-end), and property-based (Hypothesis stateful testing). The property tests
fuzz random operation sequences against four invariants — stale ⇒ open,
version-monotonic, an acyclic dependency graph, and tackit.sql round-trip fidelity —
and have already caught a real serialization bug the example tests missed. From a
clone of the repo:
pip install -e '.[test]'
pytest
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tackit-0.2.0.tar.gz.
File metadata
- Download URL: tackit-0.2.0.tar.gz
- Upload date:
- Size: 70.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e8b57f2f7ba780f4223b48522993e2e5c68a37572755e8894bec73a8cd2ac4d
|
|
| MD5 |
678e030eb6b079c0593d0d314effca22
|
|
| BLAKE2b-256 |
36783b9c62e3a65107d36f12253a331749b901af0ccbe165c8126148ec75b9a3
|
File details
Details for the file tackit-0.2.0-py3-none-any.whl.
File metadata
- Download URL: tackit-0.2.0-py3-none-any.whl
- Upload date:
- Size: 38.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38a447a1ae474515a88953f193a849fcb02f1b621abd9aabf59d0de31336adc4
|
|
| MD5 |
414f4e336bd4db76965e9c703f2ff354
|
|
| BLAKE2b-256 |
a9fdff79d1a9ed8b384ba12d6512c758bf8ba459447b653aaae38647c3ed75a7
|