README.md

  1# yatd, _yet another td_
  2
  3There are many tds. This one is mine. It's in Rust, very fast, very
  4small, fairly simple, and includes a skill. I intend it to be the bare
  5minimum for something like a repo-specific issue tracker and possibly
  6complementary to tools like [OpenSpec].
  7
  8[OpenSpec]: https://github.com/Fission-AI/OpenSpec
  9
 10## Installation
 11
 12Pre-built binaries are available at
 13[releases.secluded.site/yatd/latest][bin-latest].
 14
 15[bin-latest]: https://releases.secluded.site/yatd/latest
 16
 17- Using [mise](https://mise.jdx.dev/) (recommended), copy the snippet from the
 18  releases page into your `mise.toml` or global `~/.config/mise/config.toml` to
 19  automate updates.
 20- Without mise, or a similar tool, download the binary for your platform from
 21  the releases page and place it somewhere in your `$PATH`.
 22
 23Tell your agent how/when to use td by first installing the skill with `td
 24skill`, then somehow referring to td when telling the agent to do something
 25involving td. It shouldn't invoke the skill unless you mention td, allowing
 26your agent to use other todo/issue tools in other repos even with this global
 27skill.
 28
 29Run `td project init <name>` to create a new project and link the current
 30directory to it. If using sibling worktrees in a layout similar to the following
 31and you want to share the project's tasks across worktrees, initialise from the
 32project directory and not any of the worktrees. In the example, `project-name`
 33should be the current working directory.
 34
 35```
 36project-name
 37├── main
 38├── feature-a
 39└── user/hotfix/horrible-thing-went-wrong
 40```
 41
 42Inspired by [alosec/td].
 43
 44[alosec/td]: https://github.com/alosec/td/
 45
 46## Usage
 47
 48There are many ways to use something like this and I won't say any one
 49is better than another. However, I tend to use it in a particular way
 50and that may lead its design to faciliate that way particularly well.
 51
 52<details><summary>td on its own (click to expand)</summary>
 53
 54I first think of a feature, then tell the agent about it and ask it to
 55interview me about any gaps. We go back and forth, me nitpicking things
 56about what it said, it nitpicking things about what I said, until it
 57feels right. Then I say something like "let's think about how we can
 58break this up into the smallest units of work and create tasks with
 59appropriate dependency relationships to communicate the order in which
 60we must tackle them." It creates a bunch of tasks, links them, and
 61probably describes what it did. I run td next to see what's bubbled up
 62to the top, read through it, and decide whether it needs more work or is
 63good to go as-is. If it needs more work, I start a new session with
 64"let's think about {id} and plan it out some more, then log those
 65decisions to the task". If it's ready, the new session begins with
 66"let's get started on {id} by having a look around at the relevant code
 67then breaking it down into smaller child tasks". Then depending on the
 68context window and task scale, I either have it get started in this same
 69session or a new one.
 70
 71I said it's complementary to things like OpenSpec at the beginning, but
 72realise my workflow almost entirely obviates OpenSpec 🥴 I do intend to
 73use them together soon and will describe whatever workflow I end up with
 74then.
 75
 76</details>
 77
 78```
 79$ td --help
 80Todo tracker for AI agents
 81
 82Usage: td [OPTIONS] <COMMAND>
 83
 84Commands:
 85  init      Initialize a central project and bind the current directory to it
 86  use       Bind the current directory to an existing project
 87  projects  List all known projects in central storage
 88  create    Create a new task [aliases: add]
 89  list      List tasks [aliases: ls]
 90  show      Show task details
 91  log       Append a work log entry to a task
 92  update    Update a task
 93  done      Mark task(s) as closed [aliases: close]
 94  rm        Delete task(s)
 95  reopen    Reopen task(s)
 96  dep       Manage dependencies / blockers
 97  label     Manage labels
 98  search    Search tasks by title or description
 99  ready     Show tasks with no open blockers
100  next      Recommend next task(s) to work on
101  stats     Show task statistics (always JSON)
102  tidy      Compact accumulated delta files into the base snapshot
103  export    Export tasks to JSONL (one JSON object per line)
104  import    Import tasks from a JSONL file
105  sync      Sync project state with a peer via magic wormhole
106  skill     Install the agent skill file (SKILL.md)
107  help      Print this message or the help of the given subcommand(s)
108
109Options:
110  -j, --json               Output JSON
111      --project <PROJECT>  Select a project explicitly (overrides cwd binding)
112  -h, --help               Print help
113  -V, --version            Print version
114```
115
116## Syncing
117
118Everything is [CRDTs], so syncing is (or at least should™ be) easy! The
119built-in method uses a [Rust port][magic-wormhole.rs] of
120[magic-wormhole].
121
122- Initiate a sync on one device with `td sync`
123  - Outputs a code like `9-lurid-gecko`
124- Accept on another device with `td sync 9-lurid-gecko`
125
126[CRDTs]: https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type
127[magic-wormhole.rs]: https://github.com/magic-wormhole/magic-wormhole.rs
128[magic-wormhole]: https://magic-wormhole.readthedocs.io/en/latest/welcome.html
129
130If you want to use something like Syncthing or Nextcloud or Google Drive
131or whatever, you _should_ just be able to point the sync daemon at
132`$XDG_DATA_HOME/td/projects/`, but I've not tested this.
133
134## Bootstrapping
135
136When syncing a project to another machine, do **not** run `td init` on
137the other machine. Initialize just once on the first machine, then
138bootstrap others with `td sync` ([sync docs](#syncing)). The first
139machine will notice the other has nothing and provide everything.
140
141Running `td init` on both machines generates different `project_id`
142values and prevents sync from merging them.
143
144## Contributions
145
146I'm trying [the Jujutsu VCS] out for this project. I'm enjoying it and
147LLMs seem to do pretty well with it too. The collaboration story is a
148bit less convenient, especially since I'm also trying [pr.pico.sh]. It
149works _very_ well with git projects, but jujutsu is missing some things
150git has which [pr.pico.sh] relies on. When cloning this repo, do so with
151`jj git clone --colocate git@git.secluded.site:yatd.git` and the
152relevant git commands should work fine.
153
154[the Jujutsu VCS]: https://www.jj-vcs.dev/latest/
155
156Patch requests are in [amolith/llm-projects] on [pr.pico.sh]. You don't
157need a new account to contribute, you don't need to fork this repo, you
158don't need to fiddle with `git send-email`, you don't need to faff with
159your email client to get `git request-pull` working...
160
161You just need:
162
163- Git
164- SSH
165- An SSH key
166
167If you're using LLM agents, you might instead want to give them [my pr.pico.sh
168skill].
169
170```sh
171# Clone this repo
172jj git clone --colocate git@git.secluded.site:yatd.git
173
174# Create a new change and describe what it does
175jj new -m "Add fancy new thing" # Imperative, kernel-style commits, not Conventional Commits
176
177# When ready, create a new patch request
178git format-patch origin/main --stdout | ssh pr.pico.sh pr create amolith/llm-projects
179
180# After potential feedback, revise and submit a new patchset
181jj amend
182git format-patch origin/main --stdout | ssh pr.pico.sh pr add {prID}
183
184# List patch requests
185ssh pr.pico.sh pr ls amolith/llm-projects --mine
186```
187
188See "How do Patch Requests work?" on [pr.pico.sh]'s home page for a more
189complete example workflow.
190
191[amolith/llm-projects]: https://pr.pico.sh/r/amolith/llm-projects
192[pr.pico.sh]: https://pr.pico.sh
193[my pr.pico.sh skill]: https://git.secluded.site/agent-skills#:~:text=collaborating%2Dthrough%2Dpr%2Dpico%2Dsh