Add --version and typed delete for all kinds #5

Merged
kglitchy merged 3 commits from version-and-delete into main 2026-10-01 15:20:41 +00:00
Owner

Adds things --version and makes things delete work for projects, headings, areas, and tags.

Based on main after #3 (e27328c). Commits:

  • acf5dec — -V/--version prints things <version> (<short commit>[-dirty]), e.g. things 0.1.0 (c436138), so you can tell which build is installed. The commit comes from a small build.rs; builds outside a git checkout print just the version and don't fail.
  • 8c64bcb — typed delete:
    things delete "<task title or uuid>"          # unchanged
    things delete task    "Buy milk"              # to Trash
    things delete project "Home projects"         # to Trash; its contents go with it
    things delete heading "Next actions"          # to Trash; its to-dos go with it
    things delete area "Old job" --yes [--force]  # permanent
    things delete tag  "Unused tag" --yes         # permanent
    
    A kind name used as a selector is read as the kind: delete a task titled "task" with things delete task task or its UUID. Typed forms only match items of that kind that aren't already in Trash. Shell completion suggests the right kind for each form.
  • c436138 — README, SKILL.md, and the protocol doc ("Trash and deletion").

Wire behavior

Matched to what Things 3 for Mac writes, as observed in a real account's sync history:

  • Trash: trashing a task, project, or heading sets tr: true on that item only. Contents stay tr: false and are hidden by their container. restore sets tr: false on the container.
  • Areas: deleting an area is permanent and happens in one commit. Every item's ar drops the area, and open projects in the area move to Trash. If the area still has open projects or to-dos, the CLI refuses unless --force is given.
  • Tags: deleting a tag is permanent and happens in one commit. Tasks and areas drop it from tg, and child tags move up a level (pn).
  • Purge (changed): purge of a project or heading, and purge trash, now also delete the items inside a trashed project or heading in the same commit, as the app does. Previously they were left orphaned.
  • Cache: areas now record their tags, so the cache format version was bumped again. Expect one full resync on first run.

Inferred, not observed:

  • Headings: a trashed heading never appeared in the history. Headings are handled like projects, per Things' docs.
  • Loose to-dos in a deleted area: none appeared in the history. They're moved to Trash the same way as open projects.

Verification

  • cargo fmt --check, cargo clippy --all-targets -- -D warnings, make test: clean
  • cargo test: 145 passed (up from 136), 1 ignored (live)
  • New tests cover the wire payloads for each kind, plus end-to-end tests against the fake cloud for each typed form, the legacy form, the --yes refusal, the non-empty area refusal, and restoring a trashed project.
  • No writes were made to a real Things account. The live test was not run, so the inferred cases above are unverified against Things Cloud.
Adds `things --version` and makes `things delete` work for projects, headings, areas, and tags. Based on `main` after #3 (`e27328c`). Commits: - `acf5dec` — `-V/--version` prints `things <version> (<short commit>[-dirty])`, e.g. `things 0.1.0 (c436138)`, so you can tell which build is installed. The commit comes from a small `build.rs`; builds outside a git checkout print just the version and don't fail. - `8c64bcb` — typed `delete`: ``` things delete "<task title or uuid>" # unchanged things delete task "Buy milk" # to Trash things delete project "Home projects" # to Trash; its contents go with it things delete heading "Next actions" # to Trash; its to-dos go with it things delete area "Old job" --yes [--force] # permanent things delete tag "Unused tag" --yes # permanent ``` A kind name used as a selector is read as the kind: delete a task titled "task" with `things delete task task` or its UUID. Typed forms only match items of that kind that aren't already in Trash. Shell completion suggests the right kind for each form. - `c436138` — README, SKILL.md, and the protocol doc ("Trash and deletion"). ## Wire behavior Matched to what Things 3 for Mac writes, as observed in a real account's sync history: - **Trash:** trashing a task, project, or heading sets `tr: true` on that item only. Contents stay `tr: false` and are hidden by their container. `restore` sets `tr: false` on the container. - **Areas:** deleting an area is permanent and happens in one commit. Every item's `ar` drops the area, and open projects in the area move to Trash. If the area still has open projects or to-dos, the CLI refuses unless `--force` is given. - **Tags:** deleting a tag is permanent and happens in one commit. Tasks and areas drop it from `tg`, and child tags move up a level (`pn`). - **Purge (changed):** `purge` of a project or heading, and `purge trash`, now also delete the items inside a trashed project or heading in the same commit, as the app does. Previously they were left orphaned. - **Cache:** areas now record their tags, so the cache format version was bumped again. Expect one full resync on first run. Inferred, not observed: - **Headings:** a trashed heading never appeared in the history. Headings are handled like projects, per Things' docs. - **Loose to-dos in a deleted area:** none appeared in the history. They're moved to Trash the same way as open projects. ## Verification - `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, `make test`: clean - `cargo test`: 145 passed (up from 136), 1 ignored (live) - New tests cover the wire payloads for each kind, plus end-to-end tests against the fake cloud for each typed form, the legacy form, the `--yes` refusal, the non-empty area refusal, and restoring a trashed project. - No writes were made to a real Things account. The live test was not run, so the inferred cases above are unverified against Things Cloud.
build.rs stamps 'things <version> (<short commit>[-dirty])' and reruns when
HEAD, its branch ref, packed refs, the index, or the sources change. Builds
outside a git checkout that tracks this crate print just the version.
'things delete task|project|heading <selector>' moves the item to Trash by
setting tr on it alone; its contents stay untrashed and are hidden by their
container, as Things.app writes it. 'things delete area|tag <selector> --yes'
deletes permanently (Things has no Trash for them) and, in the same commit,
writes what the app writes: every task drops the area from ar, open projects
and to-dos in the area move to Trash (refused without --force), and a
deleted tag leaves tasks' and areas' tg and its child tags' pn. The bare
'things delete <task>' form is unchanged.

Purging a project or heading, or emptying Trash, now also deletes the
contained items in one commit, matching the app; areas track their tags,
so the cache format version is bumped.
kglitchy force-pushed version-and-delete from c43613866b to 3f805cba3d 2026-10-01 15:19:44 +00:00 Compare
kglitchy deleted branch version-and-delete 2026-10-01 15:20:41 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kglitchy/things-cli!5
No description provided.