things-api 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -9
- package/deputy/AppIcon.icns +0 -0
- package/deputy/VERSION +1 -1
- package/deputy/helpers-Info.plist +4 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/CodeResources +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Info.plist +3 -1
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/MacOS/things-reader +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Resources/AppIcon.icns +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/_CodeSignature/CodeResources +15 -2
- package/deputy/prebuilt/Things API Helper.app/Contents/Info.plist +5 -1
- package/deputy/prebuilt/Things API Helper.app/Contents/MacOS/things-deputy +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Resources/AppIcon.icns +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/_CodeSignature/CodeResources +14 -2
- package/deputy/reader/Info.plist +2 -0
- package/deputy/reader/entitlements.plist +30 -0
- package/deputy/reader/main.swift +129 -40
- package/deputy/src/server.swift +25 -2
- package/deputy/src/tcc.swift +58 -0
- package/dist/audit/schema.d.ts +13 -1
- package/dist/audit/schema.js.map +1 -1
- package/dist/capability.d.ts +160 -0
- package/dist/capability.js +416 -0
- package/dist/capability.js.map +1 -0
- package/dist/cli/commands/doctor.js +127 -1
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/helpers.js +178 -51
- package/dist/cli/commands/helpers.js.map +1 -1
- package/dist/cli/commands/op-result.js +6 -0
- package/dist/cli/commands/op-result.js.map +1 -1
- package/dist/cli/commands/reads.js +47 -1
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/setup.d.ts +9 -0
- package/dist/cli/commands/setup.js +63 -83
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/writes.d.ts +1 -1
- package/dist/cli/commands/writes.js +241 -107
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/dry-run.d.ts +1 -1
- package/dist/cli/dry-run.js +1 -1
- package/dist/cli/glyphs.d.ts +23 -4
- package/dist/cli/glyphs.js +46 -19
- package/dist/cli/glyphs.js.map +1 -1
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.js +49 -27
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/period.d.ts +3 -1
- package/dist/cli/period.js +1 -1
- package/dist/cli/period.js.map +1 -1
- package/dist/cli/read-driver.js +26 -1
- package/dist/cli/read-driver.js.map +1 -1
- package/dist/cli/render.d.ts +31 -4
- package/dist/cli/render.js +127 -15
- package/dist/cli/render.js.map +1 -1
- package/dist/client.d.ts +22 -2
- package/dist/client.js +36 -13
- package/dist/client.js.map +1 -1
- package/dist/contracts.d.ts +6 -2
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/deputy/install.d.ts +219 -5
- package/dist/deputy/install.js +803 -31
- package/dist/deputy/install.js.map +1 -1
- package/dist/deputy/notices.js +2 -2
- package/dist/deputy/notices.js.map +1 -1
- package/dist/deputy/protocol.d.ts +59 -5
- package/dist/deputy/protocol.js +48 -11
- package/dist/deputy/protocol.js.map +1 -1
- package/dist/deputy/routing.d.ts +21 -0
- package/dist/deputy/routing.js +111 -27
- package/dist/deputy/routing.js.map +1 -1
- package/dist/diagnose.d.ts +14 -1
- package/dist/diagnose.js +46 -6
- package/dist/diagnose.js.map +1 -1
- package/dist/direct-setup.d.ts +78 -0
- package/dist/direct-setup.js +484 -0
- package/dist/direct-setup.js.map +1 -0
- package/dist/host-access.d.ts +63 -0
- package/dist/host-access.js +165 -0
- package/dist/host-access.js.map +1 -0
- package/dist/index.d.ts +20 -5
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +27 -1
- package/dist/mcp/server.js +285 -100
- package/dist/mcp/server.js.map +1 -1
- package/dist/op-result.d.ts +9 -0
- package/dist/op-result.js +5 -0
- package/dist/op-result.js.map +1 -1
- package/dist/read/filter-contract.d.ts +1 -1
- package/dist/read/filter-contract.js +4 -0
- package/dist/read/filter-contract.js.map +1 -1
- package/dist/read/shape.js +4 -0
- package/dist/read/shape.js.map +1 -1
- package/dist/read/views.d.ts +29 -0
- package/dist/read/views.js +60 -0
- package/dist/read/views.js.map +1 -1
- package/dist/session-grant.d.ts +48 -0
- package/dist/session-grant.js +170 -0
- package/dist/session-grant.js.map +1 -0
- package/dist/surface-copy.d.ts +8 -0
- package/dist/surface-copy.js +8 -0
- package/dist/surface-copy.js.map +1 -1
- package/dist/wizard.d.ts +58 -0
- package/dist/wizard.js +167 -0
- package/dist/wizard.js.map +1 -0
- package/dist/write/availability.d.ts +1 -1
- package/dist/write/availability.js +3 -3
- package/dist/write/availability.js.map +1 -1
- package/dist/write/batch.d.ts +20 -0
- package/dist/write/batch.js +94 -15
- package/dist/write/batch.js.map +1 -1
- package/dist/write/capabilities.d.ts +9 -0
- package/dist/write/capabilities.js +2 -0
- package/dist/write/capabilities.js.map +1 -1
- package/dist/write/clear-reminder.js +1 -1
- package/dist/write/clear-reminder.js.map +1 -1
- package/dist/write/commands.d.ts +12 -1
- package/dist/write/commands.js +112 -224
- package/dist/write/commands.js.map +1 -1
- package/dist/write/failure-hints.d.ts +3 -1
- package/dist/write/failure-hints.js.map +1 -1
- package/dist/write/guards.js +19 -2
- package/dist/write/guards.js.map +1 -1
- package/dist/write/lock.d.ts +16 -13
- package/dist/write/lock.js +55 -0
- package/dist/write/lock.js.map +1 -1
- package/dist/write/make-repeating-project.js +9 -13
- package/dist/write/make-repeating-project.js.map +1 -1
- package/dist/write/operations.d.ts +36 -21
- package/dist/write/operations.js +7 -0
- package/dist/write/operations.js.map +1 -1
- package/dist/write/opid.d.ts +14 -0
- package/dist/write/opid.js +22 -0
- package/dist/write/opid.js.map +1 -1
- package/dist/write/param-schema.d.ts +124 -0
- package/dist/write/param-schema.js +747 -0
- package/dist/write/param-schema.js.map +1 -0
- package/dist/write/pipeline.d.ts +76 -2
- package/dist/write/pipeline.js +190 -2
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/pre-state.d.ts +8 -0
- package/dist/write/pre-state.js +29 -2
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/promote-clone.js +539 -439
- package/dist/write/promote-clone.js.map +1 -1
- package/dist/write/reorder.js +25 -8
- package/dist/write/reorder.js.map +1 -1
- package/dist/write/repeat-rule.d.ts +28 -1
- package/dist/write/repeat-rule.js +54 -4
- package/dist/write/repeat-rule.js.map +1 -1
- package/dist/write/resolution-timestamps.d.ts +11 -0
- package/dist/write/resolution-timestamps.js +83 -38
- package/dist/write/resolution-timestamps.js.map +1 -1
- package/dist/write/reversibility.js +4 -0
- package/dist/write/reversibility.js.map +1 -1
- package/dist/write/template-mutation.d.ts +137 -0
- package/dist/write/template-mutation.js +451 -0
- package/dist/write/template-mutation.js.map +1 -0
- package/dist/write/undo.js +10 -20
- package/dist/write/undo.js.map +1 -1
- package/dist/write/update-fields.d.ts +151 -0
- package/dist/write/update-fields.js +427 -0
- package/dist/write/update-fields.js.map +1 -0
- package/dist/write/vectors/applescript.js +3 -0
- package/dist/write/vectors/applescript.js.map +1 -1
- package/dist/write/vectors/registry.d.ts +1 -1
- package/dist/write/vectors/registry.js +10 -2
- package/dist/write/vectors/registry.js.map +1 -1
- package/dist/write/vectors/shortcuts.js +2 -2
- package/dist/write/vectors/shortcuts.js.map +1 -1
- package/dist/write/vectors/simulator.js +7 -2
- package/dist/write/vectors/simulator.js.map +1 -1
- package/dist/write/vectors/types.d.ts +57 -0
- package/dist/write/vectors/ui-recipes.d.ts +19 -0
- package/dist/write/vectors/ui-recipes.js +30 -0
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui.d.ts +13 -0
- package/dist/write/vectors/ui.js +62 -13
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/verify/delta.d.ts +21 -0
- package/dist/write/verify/delta.js.map +1 -1
- package/package.json +2 -1
- package/schema/envelope.schema.json +5 -3
- package/scripts/build-helpers.sh +5 -0
- package/skills/things-cli/SKILL.md +5 -3
- package/skills/things-cli/references/contracts.md +1 -0
- package/skills/things-cli/references/data-model.md +3 -0
- package/skills/things-cli/references/errors.md +1 -1
- package/skills/things-cli/references/gui.md +1 -0
- package/skills/things-cli/references/repeating.md +6 -0
- package/skills/things-cli/references/tag-cleanup.md +64 -0
|
@@ -7,5 +7,6 @@ Curated rendering facts — the bench loop may compress or relocate these but mu
|
|
|
7
7
|
- **Sidebar**: top-level views (Inbox, Today, Upcoming, Anytime, Someday, Logbook, Trash), then each **area** with its active **projects** nested beneath it — in the same order this CLI/API reports them. Reordering areas or projects changes what the user sees there.
|
|
8
8
|
- **List rows are compact**: a to-do in any list shows its checkbox/status, title, tags, deadline, and small marker chips — the Today ★, This Evening ⏾, and (in the Today view only) the provisional `•` "new item" pip, plus has-notes / reminder / checklist glyphs (`things legend` names them all). The **notes TEXT and checklist CONTENTS are invisible until the user opens the item**. Put must-see-at-a-glance information in the title; supporting detail belongs in notes. Projects carry the same Today ★ / This Evening ⏾ pips as to-dos. Why some chips vanish once a row's date goes stale — the reminder bell, the This-Evening section, and the provisional pip — is in [banner.md](banner.md).
|
|
9
9
|
- **Project notes** are likewise visible only when the project itself is opened in project view — in lists, a project is just its title (and progress ring).
|
|
10
|
+
- **An open card renders the notes as markdown, with the syntax characters left in place** — headings, bold/italic, code spans, fenced blocks, and `-`/numbered lists take on their formatting while the user still sees the `#`, `**`, backticks, and dashes that produced it. Write notes the user will read as source AND as formatting: no huge heading stacks, and no `[label](url)` (a bare URL links itself; the label form stays literal). See [data-model.md](data-model.md) for the full construct list.
|
|
10
11
|
- **Today** shows the day's scheduled items, with **This Evening** as a separate section beneath. **Upcoming** is a forward-looking date-ordered calendar of scheduled items. **Logbook** is where completed/canceled items go — after completing something for the user, that's where they'll find it.
|
|
11
12
|
- When telling the user where something landed, name the container and view ("in project P under area A"; "it'll show in Today this evening").
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
A repeating item is a **template** plus the **instances** it spawns. The template holds the rule (how often, on what calendar day, with what deadline/reminder/end bound); each occurrence the app materializes is a separate to-do (or project) you complete normally. Completing an instance never touches the template; the template keeps spawning the next occurrence on schedule.
|
|
4
4
|
|
|
5
|
+
**Telling the two halves apart in output.** On a TTY both wear the `↻` glyph, in different slots: a TEMPLATE keeps an ordinary checkbox and carries a **blue `↻` in front of its title** (`[ ] ↻ Water plants ‹Jul 8›`, `( ) ↻ Weekly review`); an INSTANCE is an ordinary checkable row with a **muted `↻` after the title**, in the marker cluster beside `≡`/`◷`/`≔` (`[ ] Water plants ↻ ≡`). In `--json` the same split is presence-keyed: a template carries a `repeating` object, an instance carries a flat `instanceOf: <templateUuid>` (the template's uuid — pass it to the repeat verbs), and a plain row carries neither. `things legend` lists both marks.
|
|
6
|
+
|
|
7
|
+
## Finding a series in the first place
|
|
8
|
+
|
|
9
|
+
`things repeaters` lists every repeating series in the library — to-dos and projects — with its uuid, its next occurrence, its container, and its decoded rule. Reach for it before any repeat write, because a template is invisible to every other read: the list views show the OCCURRENCES a series spawns rather than the series itself, and `search` matches those occurrences but never the template behind them. Paused and ended series are listed too (each row says which), which is usually the fastest answer to "why has this stopped appearing?". `--json` carries the rule structurally under `repeating.rule`; the uuid it gives you is what `reschedule-repeat`, `pause-repeat`, `resume-repeat`, and `show` all take.
|
|
10
|
+
|
|
5
11
|
## The verbs
|
|
6
12
|
|
|
7
13
|
- `things todo make-repeating <ref> --frequency … --interval …` — turn an existing plain to-do into a repeating series. This **REPLACES the item**: the original to-do disappears and a fresh template takes its place, so the uuid you get back is the TEMPLATE's, not the original's. Cannot be undone through the normal path (the original is moved to the Trash; `things undo` removes the new series and restores it).
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Mass tag cleanup — reshaping a tag vocabulary without flooding the timeline
|
|
2
|
+
|
|
3
|
+
A tag cleanup ("we have 40 tags, six of them mean the same thing") touches hundreds of items, and the naive version re-dates every one of them: `things changes --since <moment>` — and any watcher or sync-driven review keyed on the modification date — then reports the whole library as freshly changed, burying whatever really happened that day.
|
|
4
|
+
|
|
5
|
+
It does not have to. **Two of the three moves cost nothing on the timeline, and the third has a flag.** Work in that order.
|
|
6
|
+
|
|
7
|
+
## The three moves, cheapest first
|
|
8
|
+
|
|
9
|
+
| Move | Command | Timeline cost |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| **Rename a tag** (merge a synonym into the survivor's name, fix casing, re-word) | `things tag update <ref> --title "<new>"` | **none** — the assignment stores the tag's identity, not its text, so no member item is touched. Existing assignments follow the rename. |
|
|
12
|
+
| **Delete a tag** (retire it everywhere, including its whole nested subtree) | `things tag delete <ref> --dangerously-permanent [--acknowledge-subtree]` | **none** — the tag is removed from every item without re-dating any of them. Permanent: tags do not go to the Trash. |
|
|
13
|
+
| **Apply or remove a tag on items** (`--set` replaces the tag set, `--add` merges) | `things todo tags <uuid> --add "<tag>"` / `things project tags <ref> --set "<a>,<b>"` | **one re-date per item** — this is the only move that lands on the timeline, and the only one that wants `--preserve-modified`. |
|
|
14
|
+
|
|
15
|
+
So: **reshape the vocabulary first, re-tag items last.** A rename that turns `errands`, `Errand`, and `errand-run` into one surviving tag costs nothing; every item you can leave alone by renaming instead of re-tagging is an item that never reaches the timeline.
|
|
16
|
+
|
|
17
|
+
## The recipe
|
|
18
|
+
|
|
19
|
+
1. **Look before you write.** `things tags` lists the hierarchy; `things anytime --tag <name> --all --json` (or `things search`) enumerates what a tag actually holds. Decide which tag survives.
|
|
20
|
+
2. **Rename the survivor into the name you want** (`tag update`), rather than creating a new tag and re-tagging into it. Free.
|
|
21
|
+
3. **Fold the synonyms.** For each doomed tag, the items that carry it and NOT the survivor need the survivor added — this is the only pass that re-dates anything, so run it with `--preserve-modified`. One item at a time:
|
|
22
|
+
```sh
|
|
23
|
+
things todo tags <uuid> --add "errand" --preserve-modified
|
|
24
|
+
```
|
|
25
|
+
For hundreds of them, `things batch` is the vehicle: it takes `--preserve-modified` at the RUN level, applying it to every line, and the whole submission comes back under one `undoToken`. The batch op is `todo.set-tags`, which REPLACES the tag set (there is no per-line merge — `--add` is CLI sugar over a read), so build each line's full set from the item's current tags:
|
|
26
|
+
```sh
|
|
27
|
+
# anytime is a SECTIONED view (data.sections[].items[]); item tags are
|
|
28
|
+
# {title} objects, and todo.set-tags wants a flat list of titles.
|
|
29
|
+
things anytime --tag "Errand" --all --json \
|
|
30
|
+
| jq -c '.data.sections[].items[]
|
|
31
|
+
| select(.type == "to-do")
|
|
32
|
+
| {op: "todo.set-tags",
|
|
33
|
+
params: {uuid, tags: ([(.tags // [])[].title] - ["errand"] + ["errand"])}}' \
|
|
34
|
+
| things batch --preserve-modified
|
|
35
|
+
```
|
|
36
|
+
(Project rows carry their own tags — filter them out as above and re-tag them with `project.set-tags` in a second pass, or drop the `select` and branch the `op` on `.type`.)
|
|
37
|
+
Each line's result carries `preservedModified` (and `preserveFailures` for any restore that did not land), so you can see the pass stayed silent. A single line can opt back onto the timeline with its own `"options": {"preserveModified": false}` — the per-line value always outranks the run flag. Add an `"opId"` per line if you want a stopped batch to be resubmittable verbatim.
|
|
38
|
+
4. **Delete the doomed tags** (`tag delete … --dangerously-permanent`, plus `--acknowledge-subtree` when the tag has children — deleting a parent deletes its whole subtree). Free, and it also removes the tag from anything you missed in step 3, so a stray assignment does not survive as a ghost.
|
|
39
|
+
5. **Check the timeline you were protecting**: `things changes --since <the moment you started>` should show only what you meant to surface.
|
|
40
|
+
|
|
41
|
+
## `--preserve-modified` in one paragraph
|
|
42
|
+
|
|
43
|
+
It captures each pre-existing edited item's modification date before the write and restores it (to the whole second) afterwards, so the edit does not surface in `changes`. It is universal — every write verb takes it — and a no-op on a pure create. The restore is best-effort: a failure is reported per item and the change itself still stands, so a cleanup never half-applies because a restore missed. It is **safe against a synced library**: the restored date propagates to your other devices and survives the round-trip, so the item stays off the timeline everywhere; the one edge is a genuinely concurrent edit to the same item on another device, which re-dates it through Things Cloud's per-attribute merge — the edit resurfaces rather than being silently hidden (SYNC2B).
|
|
44
|
+
|
|
45
|
+
Full contract: the `--preserve-modified` bullet in [../SKILL.md](../SKILL.md); per-operation detail in `things <verb> --help`.
|
|
46
|
+
|
|
47
|
+
## The adjacent cleanup: retiring an area
|
|
48
|
+
|
|
49
|
+
The same "make the free move first" logic applies to an `(archived)`-style area you want to dissolve. **Deleting an area treats its members by status:**
|
|
50
|
+
|
|
51
|
+
- an **open** direct member (to-do or project) is moved to the **Trash** and re-dated;
|
|
52
|
+
- a **logged** member (completed or canceled) is merely **detached** — its area link is cleared, it stays live in the Logbook, and it is **not** re-dated.
|
|
53
|
+
|
|
54
|
+
So deleting a long-dead area full of finished work is mostly free: the history stays in the Logbook, unlinked, off the timeline. Only the open remnants move, and those are exactly the ones you should look at first. Deleting an area is **permanent** (areas do not go to the Trash) and a non-empty one is refused unless you pass `--allow-non-empty`:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
things area delete "Old Client (archived)" --dangerously-permanent --allow-non-empty --preserve-modified
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Preview it first — `--dry-run` reports the plan — and if you want the open remnants kept, move them out before deleting rather than restoring them from the Trash afterwards.
|
|
61
|
+
|
|
62
|
+
## What this rests on
|
|
63
|
+
|
|
64
|
+
The laws above are measured, not assumed: the rename/delete/apply modification-date footprint (TAGMOD), the area-delete status-dependent trash-vs-detach split (TAGMOD-T4, refining AREADEL), and the sync round-trip that makes the restore safe on a real Things Cloud account (SYNC2B). The evidence lives with the project's lab documentation, indexed by those names.
|