things-api 0.7.0 → 0.8.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.
Files changed (114) hide show
  1. package/README.md +3 -1
  2. package/dist/cli/commands/area.d.ts +14 -0
  3. package/dist/cli/commands/area.js +107 -33
  4. package/dist/cli/commands/area.js.map +1 -1
  5. package/dist/cli/commands/project.d.ts +14 -0
  6. package/dist/cli/commands/project.js +114 -30
  7. package/dist/cli/commands/project.js.map +1 -1
  8. package/dist/cli/commands/reads.d.ts +90 -12
  9. package/dist/cli/commands/reads.js +534 -74
  10. package/dist/cli/commands/reads.js.map +1 -1
  11. package/dist/cli/commands/show.d.ts +9 -0
  12. package/dist/cli/commands/show.js +41 -0
  13. package/dist/cli/commands/show.js.map +1 -0
  14. package/dist/cli/commands/todo.d.ts +9 -0
  15. package/dist/cli/commands/todo.js +89 -15
  16. package/dist/cli/commands/todo.js.map +1 -1
  17. package/dist/cli/commands/writes.js +55 -1
  18. package/dist/cli/commands/writes.js.map +1 -1
  19. package/dist/cli/glyphs.d.ts +72 -0
  20. package/dist/cli/glyphs.js +169 -0
  21. package/dist/cli/glyphs.js.map +1 -0
  22. package/dist/cli/main.js +2 -0
  23. package/dist/cli/main.js.map +1 -1
  24. package/dist/cli/style.d.ts +5 -0
  25. package/dist/cli/style.js +5 -0
  26. package/dist/cli/style.js.map +1 -1
  27. package/dist/client.d.ts +33 -36
  28. package/dist/client.js +9 -73
  29. package/dist/client.js.map +1 -1
  30. package/dist/contracts.d.ts +1 -1
  31. package/dist/contracts.js +1 -1
  32. package/dist/db/baselines/db-v26.js +7 -5
  33. package/dist/db/baselines/db-v26.js.map +1 -1
  34. package/dist/db/schema.d.ts +1 -1
  35. package/dist/db/schema.js +7 -1
  36. package/dist/db/schema.js.map +1 -1
  37. package/dist/mcp/server.js +19 -0
  38. package/dist/mcp/server.js.map +1 -1
  39. package/dist/model/entities.d.ts +12 -0
  40. package/dist/model/entities.js.map +1 -1
  41. package/dist/model/mappers.js +4 -0
  42. package/dist/model/mappers.js.map +1 -1
  43. package/dist/model/occurrences.js +4 -1
  44. package/dist/model/occurrences.js.map +1 -1
  45. package/dist/model/recurrence.d.ts +21 -2
  46. package/dist/model/recurrence.js +20 -0
  47. package/dist/model/recurrence.js.map +1 -1
  48. package/dist/read/area-view.js +21 -5
  49. package/dist/read/area-view.js.map +1 -1
  50. package/dist/read/detail.js +12 -2
  51. package/dist/read/detail.js.map +1 -1
  52. package/dist/read/log-boundary.d.ts +24 -0
  53. package/dist/read/log-boundary.js +38 -0
  54. package/dist/read/log-boundary.js.map +1 -0
  55. package/dist/read/project-view.js +28 -3
  56. package/dist/read/project-view.js.map +1 -1
  57. package/dist/read/queries.d.ts +14 -1
  58. package/dist/read/queries.js +25 -2
  59. package/dist/read/queries.js.map +1 -1
  60. package/dist/read/show-target.d.ts +16 -0
  61. package/dist/read/show-target.js +32 -0
  62. package/dist/read/show-target.js.map +1 -0
  63. package/dist/read/snapshot.js +2 -0
  64. package/dist/read/snapshot.js.map +1 -1
  65. package/dist/read/views.d.ts +25 -3
  66. package/dist/read/views.js +176 -21
  67. package/dist/read/views.js.map +1 -1
  68. package/dist/write/automation-probe.js +14 -6
  69. package/dist/write/automation-probe.js.map +1 -1
  70. package/dist/write/capabilities.d.ts +3 -0
  71. package/dist/write/capabilities.js +2 -0
  72. package/dist/write/capabilities.js.map +1 -1
  73. package/dist/write/checklist.d.ts +50 -0
  74. package/dist/write/checklist.js +61 -0
  75. package/dist/write/checklist.js.map +1 -0
  76. package/dist/write/clear-reminder.d.ts +3 -0
  77. package/dist/write/clear-reminder.js +205 -0
  78. package/dist/write/clear-reminder.js.map +1 -0
  79. package/dist/write/commands.js +122 -8
  80. package/dist/write/commands.js.map +1 -1
  81. package/dist/write/edit-checklist.d.ts +3 -0
  82. package/dist/write/edit-checklist.js +184 -0
  83. package/dist/write/edit-checklist.js.map +1 -0
  84. package/dist/write/failure-hints.d.ts +7 -0
  85. package/dist/write/failure-hints.js +25 -2
  86. package/dist/write/failure-hints.js.map +1 -1
  87. package/dist/write/guards.d.ts +1 -1
  88. package/dist/write/guards.js +16 -0
  89. package/dist/write/guards.js.map +1 -1
  90. package/dist/write/operations.d.ts +32 -1
  91. package/dist/write/operations.js +3 -0
  92. package/dist/write/operations.js.map +1 -1
  93. package/dist/write/pipeline.d.ts +3 -0
  94. package/dist/write/pipeline.js +23 -1
  95. package/dist/write/pipeline.js.map +1 -1
  96. package/dist/write/reversibility.d.ts +46 -0
  97. package/dist/write/reversibility.js +164 -0
  98. package/dist/write/reversibility.js.map +1 -0
  99. package/dist/write/undo.d.ts +29 -2
  100. package/dist/write/undo.js +356 -9
  101. package/dist/write/undo.js.map +1 -1
  102. package/dist/write/vectors/registry.js +2 -1
  103. package/dist/write/vectors/registry.js.map +1 -1
  104. package/dist/write/vectors/shortcuts.d.ts +9 -0
  105. package/dist/write/vectors/shortcuts.js +90 -0
  106. package/dist/write/vectors/shortcuts.js.map +1 -0
  107. package/dist/write/vectors/types.d.ts +11 -3
  108. package/dist/write/vectors/url-scheme.js +16 -0
  109. package/dist/write/vectors/url-scheme.js.map +1 -1
  110. package/dist/write/verify/delta.d.ts +1 -1
  111. package/dist/write/verify/delta.js +1 -1
  112. package/dist/write/verify/delta.js.map +1 -1
  113. package/package.json +1 -1
  114. package/shortcuts/things-proxy-find-items.shortcut +0 -0
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A typed TypeScript library + CLI (`things`) for programmatic interaction with [Things 3](https://culturedcode.com/things/) by Cultured Code.
4
4
 
5
- **Status: read + write + MCP layers live and published to npm (v0.7.0 — see [CHANGELOG.md](CHANGELOG.md)).** Reads go straight to the local SQLite database (UI-exact Today ordering, sidebar-grouped Anytime/Someday with container-status cascade, decoded repeat rules, occurrence projections); writes run a verified pipeline over two lab-validated write vectors (URL scheme + AppleScript) with hazard guards, disruption-tier policy, a JSONL audit trail, batch mode, audit-replay undo (transactional across compound operations), full project lifecycle (complete/cancel/reopen/restore), heading rename/archive/unarchive with children policies, container detach, granular stateful checklists, tag hierarchy management incl. un-nesting, completion/creation backdating, Logbook imports, tiered fuzzy name resolution (uuid prefixes, `things:///show?id=` share links), and ordering across eight scopes (incl. a project's headings and the top-level sidebar projects). A third surface — Apple Shortcuts — is lab-proven for the three capabilities nothing else can do (creating a heading in an existing project, clearing a reminder from a date-scheduled item, single-item permanent delete) and is on the roadmap as a configurable write vector. See [docs/design/](docs/design/) for the architecture and VM-lab design, [docs/lab/](docs/lab/harness.md) for the probe harness and campaign results the write layer is grounded in, and [docs/atlas/](docs/atlas/schema-v26.md) for the database↔UI map.
5
+ **Status: read + write + MCP layers live and published to npm (v0.7.0 — see [CHANGELOG.md](CHANGELOG.md)).** Reads go straight to the local SQLite database (UI-exact Today ordering, sidebar-grouped Anytime/Someday with container-status cascade, decoded repeat rules, occurrence projections); writes run a verified pipeline over two lab-validated write vectors (URL scheme + AppleScript) with hazard guards, disruption-tier policy, a JSONL audit trail, batch mode, audit-replay undo (transactional across compound operations), full project lifecycle (complete/cancel/reopen/restore), heading rename/archive/unarchive with children policies, container detach, granular stateful checklists, tag hierarchy management incl. un-nesting, completion/creation backdating, Logbook imports, tiered fuzzy name resolution (uuid prefixes, `things:///show?id=` share links), and ordering across eight scopes (incl. a project's headings and the top-level sidebar projects). A third surface — Apple Shortcuts — is now wired for the two headless capabilities nothing else can do: creating a heading in an existing project (`things heading add`) and clearing a reminder from a date-scheduled item (`things todo clear-reminder`). Both run through bundled proxy shortcuts (`things setup shortcuts`) and are gated on their presence. Single-item permanent delete stays interactive-only (its macOS consent has no always-allow) and is out of the headless pipeline. See [docs/design/](docs/design/) for the architecture and VM-lab design, [docs/lab/](docs/lab/harness.md) for the probe harness and campaign results the write layer is grounded in, and [docs/atlas/](docs/atlas/schema-v26.md) for the database↔UI map.
6
6
 
7
7
  ```sh
8
8
  things today --json # read: your Today list, Evening split, UI order
@@ -26,6 +26,8 @@ things setup shortcuts # opens an install sheet per missing shortcut — click
26
26
 
27
27
  On each shortcut's first run macOS asks for permission — choose **Always Allow** so later runs are unattended (the two delete shortcuts re-ask on every run by design; Apple offers no always-allow for deletion). `things setup shortcuts --check` and `things doctor` report installation state.
28
28
 
29
+ Once installed, these Shortcuts-only operations become available as ordinary commands: `things heading add <project> <title>` (create a heading in an existing project) and `things todo clear-reminder <uuid>` (clear a date-scheduled to-do's reminder while keeping its date). Both are also exposed over MCP (`create_heading`, `clear_reminder`). If a required shortcut is missing, the command is blocked up front with a pointer back to `things setup shortcuts` — nothing is dispatched.
30
+
29
31
  ### Development install
30
32
 
31
33
  To get a global `things` command that runs the live TypeScript source (no build step — Node ≥ 24 strips types natively):
@@ -3,4 +3,18 @@
3
3
  * under `things area` are registered by writes.ts on the same group).
4
4
  */
5
5
  import type { Command } from "commander";
6
+ import type { AreaView } from "../../read/area-view.ts";
7
+ export interface AreaShowOpts {
8
+ showLater?: boolean;
9
+ /** Commander optional-value flag: true when bare, the raw string when given a count. */
10
+ showLogged?: boolean | string;
11
+ }
12
+ /**
13
+ * GUI layout: active projects first (sidebar order), then the area's direct
14
+ * to-dos. `--show-later` reveals the GUI's toggled sections — Upcoming
15
+ * (future-scheduled projects, to-dos, and repeating templates intermixed in
16
+ * date order) and Someday (someday projects as a leading block, then
17
+ * someday to-dos). `--show-logged` reveals the full logbook.
18
+ */
19
+ export declare function renderAreaView(view: AreaView, opts: AreaShowOpts): string[];
6
20
  export declare function registerAreaCommands(program: Command): void;
@@ -1,41 +1,99 @@
1
- import { bold, dim } from "../style.js";
2
- import { formatItem, uuidDisplayWidth, withClient } from "./reads.js";
3
- function renderAreaView(view) {
4
- const everyItem = [
1
+ import { localToday } from "../../model/dates.js";
2
+ import { bold, dim, green } from "../style.js";
3
+ import { areaMark, thingsLink } from "../glyphs.js";
4
+ import { formatItem, openInThings, uuidDisplayWidth, withClient } from "./reads.js";
5
+ /** Bare `--show-logged` shows this many recent entries (areas accumulate thousands). */
6
+ const RECENT_LOGGED_DEFAULT = 15;
7
+ function loggedCount(showLogged) {
8
+ if (showLogged === undefined)
9
+ return 0;
10
+ if (showLogged === true)
11
+ return RECENT_LOGGED_DEFAULT;
12
+ const n = Number(showLogged);
13
+ return Number.isInteger(n) && n > 0 ? n : RECENT_LOGGED_DEFAULT;
14
+ }
15
+ /**
16
+ * GUI layout: active projects first (sidebar order), then the area's direct
17
+ * to-dos. `--show-later` reveals the GUI's toggled sections — Upcoming
18
+ * (future-scheduled projects, to-dos, and repeating templates intermixed in
19
+ * date order) and Someday (someday projects as a leading block, then
20
+ * someday to-dos). `--show-logged` reveals the full logbook.
21
+ */
22
+ export function renderAreaView(view, opts) {
23
+ const todayIso = localToday();
24
+ // Closed-but-unswept projects always sit in the active block (checked),
25
+ // never in Upcoming/Someday — start/startDate only classify OPEN rows.
26
+ const isSomedayProject = (p) => p.status === "open" && p.start === "someday" && p.startDate === null;
27
+ const isScheduledProject = (p) => p.status === "open" && p.startDate !== null && p.startDate > todayIso;
28
+ const activeProjects = view.projects.filter((p) => !isSomedayProject(p) && !isScheduledProject(p));
29
+ const somedayProjects = view.projects.filter(isSomedayProject);
30
+ // Upcoming intermixes scheduled projects, scheduled to-dos, and repeating
31
+ // templates in date order (templates sort by their next occurrence).
32
+ const upcoming = [
33
+ ...view.projects.filter(isScheduledProject).map((p) => ({ date: p.startDate ?? "", item: p })),
34
+ ...view.later.scheduled.flatMap((d) => d.items.map((t) => ({ date: d.date, item: t }))),
35
+ ...view.later.repeating.map((t) => ({ date: t.repeating.nextOccurrence ?? "9999", item: t })),
36
+ ].sort((a, b) => a.date.localeCompare(b.date));
37
+ const logged = view.logged.slice(0, loggedCount(opts.showLogged));
38
+ const shown = [
39
+ ...activeProjects,
5
40
  ...view.active,
6
- ...view.projects,
7
- ...view.later.scheduled.flatMap((d) => d.items),
8
- ...view.later.repeating,
9
- ...view.later.someday,
10
- ...view.logged.slice(0, 10),
41
+ ...(opts.showLater === true
42
+ ? [...upcoming.map((u) => u.item), ...somedayProjects, ...view.later.someday]
43
+ : []),
44
+ ...logged,
11
45
  ];
12
- const w = uuidDisplayWidth(everyItem);
46
+ const w = uuidDisplayWidth(shown);
13
47
  // Rows inside this view never repeat the area's own name.
14
48
  const fmt = (i) => formatItem(i, w, { suppressArea: view.area.uuid });
15
49
  const fmtProject = (i) => formatItem(i, w, { projectTitle: true, suppressArea: view.area.uuid });
16
- const tags = view.area.tags.length
17
- ? ` ${dim(`#${view.area.tags.map((t) => t.title).join(" #")}`)}`
18
- : "";
19
- const lines = [`${view.area.uuid} ${bold(view.area.title)}${tags}`];
20
- const section = (header, rows) => {
21
- lines.push("", bold(header), ...rows);
50
+ // Card header: glyph + name, the GUI's share link (carries the uuid — it
51
+ // pastes back into any ref argument), then labeled meta lines. The opened
52
+ // resource shows its tags green (GUI: list pills are gray).
53
+ const lines = [
54
+ `${bold("Area:")} ${areaMark()} ${bold(view.area.title)}`,
55
+ ` ${dim("uri:")} ${thingsLink(view.area.uuid)}`,
56
+ ];
57
+ if (view.area.tags.length > 0)
58
+ lines.push(` ${dim("tags:")} ${green(`#${view.area.tags.map((t) => t.title).join(" #")}`)}`);
59
+ const block = (rows) => {
60
+ if (rows.length > 0)
61
+ lines.push("", ...rows);
22
62
  };
23
- section("── Active ──", view.active.length ? view.active.map(fmt) : ["(none)"]);
24
- section("── Projects ──", view.projects.length ? view.projects.map(fmtProject) : ["(none)"]);
25
- if (view.later.scheduled.length || view.later.repeating.length || view.later.someday.length) {
26
- lines.push("", bold("── Later ──"));
27
- for (const day of view.later.scheduled) {
28
- lines.push(` ${day.date}:`, ...day.items.map(fmt));
29
- }
30
- if (view.later.repeating.length) {
31
- lines.push(" repeating templates:", ...view.later.repeating.map(fmt));
63
+ block(activeProjects.map(fmtProject));
64
+ block(view.active.map(fmt));
65
+ if (activeProjects.length === 0 && view.active.length === 0)
66
+ lines.push("", "(no active items)");
67
+ if (opts.showLater === true) {
68
+ if (upcoming.length > 0) {
69
+ lines.push("", bold("── Upcoming ──"), ...upcoming.map((u) => fmt(u.item)));
32
70
  }
33
- if (view.later.someday.length) {
34
- lines.push(" someday:", ...view.later.someday.map(fmt));
71
+ if (somedayProjects.length > 0 || view.later.someday.length > 0) {
72
+ lines.push("", bold("── Someday ──"), ...somedayProjects.map(fmtProject));
73
+ if (view.later.someday.length > 0) {
74
+ if (somedayProjects.length > 0)
75
+ lines.push("");
76
+ lines.push(...view.later.someday.map(fmt));
77
+ }
35
78
  }
36
79
  }
37
- if (view.logged.length)
38
- section(`── Logged (${view.logged.length}) ──`, view.logged.slice(0, 10).map(fmt));
80
+ // Default-hidden rows are never silent — a muted count names the toggle.
81
+ if (opts.showLater !== true) {
82
+ const hiddenLater = upcoming.length + somedayProjects.length + view.later.someday.length;
83
+ if (hiddenLater > 0)
84
+ lines.push("", dim(`…${hiddenLater} later item${hiddenLater === 1 ? "" : "s"} (--show-later)`));
85
+ }
86
+ if (logged.length > 0) {
87
+ // Truncation is loud: areas accumulate years of history — the full
88
+ // archive belongs to `things logbook --area`.
89
+ const header = logged.length < view.logged.length
90
+ ? `── Logged (${logged.length} of ${view.logged.length} — see things logbook --area) ──`
91
+ : `── Logged (${view.logged.length}) ──`;
92
+ lines.push("", bold(header), ...logged.map(fmt));
93
+ }
94
+ else if (view.logged.length > 0) {
95
+ lines.push("", dim(`…${view.logged.length} logged (--show-logged; full history: things logbook --area)`));
96
+ }
39
97
  if (view.trashed.length)
40
98
  lines.push("", bold(`── Trashed (${view.trashed.length}) ──`));
41
99
  return lines;
@@ -44,13 +102,29 @@ export function registerAreaCommands(program) {
44
102
  const area = program.command("area").description("Area-scoped operations");
45
103
  area
46
104
  .command("show <ref>")
47
- .description("Composite area view mirroring the native UI: the area's direct to-dos (active " +
48
- "first), its projects in sidebar order, later (scheduled/repeating/someday), " +
49
- "logged. Target by uuid or unique name.")
105
+ .description("Composite area view mirroring the native UI: active projects first, then the " +
106
+ "area's direct to-dos. --show-later adds the Upcoming (date-ordered) and " +
107
+ "Someday sections; --show-logged adds the full logbook. Target by uuid or " +
108
+ "unique name.")
109
+ .option("--show-later", "include Upcoming and Someday sections")
110
+ .option("--show-logged [n]", "include the n most recently logged items (bare flag = 15; full history via `things logbook --area`)")
111
+ .option("--json", "emit versioned JSON envelope on stdout")
112
+ .option("--db <path>", "explicit database path")
113
+ .action((ref, opts) => {
114
+ withClient(opts, "area-view", (c) => c.read.areaView(ref), ((d) => renderAreaView(d, opts)));
115
+ });
116
+ area
117
+ .command("open <ref>")
118
+ .description("Open the area in the Things app — foregrounds the GUI on this Mac (NOT headless). Errors when the reference is not an area.")
50
119
  .option("--json", "emit versioned JSON envelope on stdout")
51
120
  .option("--db <path>", "explicit database path")
52
121
  .action((ref, opts) => {
53
- withClient(opts, "area-view", (c) => c.read.areaView(ref), renderAreaView);
122
+ withClient(opts, "open", (c) => {
123
+ const t = c.read.showTarget(ref);
124
+ if (t.kind !== "area")
125
+ throw new RangeError(`"${ref}" is a ${t.viaHeading === true ? "heading" : t.kind}, not an area (try \`things open\`)`);
126
+ return { uri: openInThings(t.uuid) };
127
+ }, ((d) => [`opened ${d.uri}`]));
54
128
  });
55
129
  }
56
130
  //# sourceMappingURL=area.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"area.js","sourceRoot":"","sources":["../../../src/cli/commands/area.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"area.js","sourceRoot":"","sources":["../../../src/cli/commands/area.ts"],"names":[],"mappings":"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"}
@@ -2,4 +2,18 @@
2
2
  * `things project show <uuid>` — the composite project view.
3
3
  */
4
4
  import type { Command } from "commander";
5
+ import type { ProjectView } from "../../read/project-view.ts";
6
+ export interface ProjectShowOpts {
7
+ showLater?: boolean;
8
+ /** Optional-value flag: bare = the FULL project logbook (finite lifespans), a count to cap it. */
9
+ showLogged?: boolean | string;
10
+ }
11
+ /**
12
+ * GUI parity: later rows (scheduled / repeating / someday) render INLINE
13
+ * beneath their heading — dimmed boxes and date chips carry the state — not
14
+ * exiled to a separate section that disassociates them from their headings.
15
+ * They are hidden by default like the GUI's toggle; `--show-later` reveals
16
+ * them, `--show-logged` reveals the full logbook.
17
+ */
18
+ export declare function renderProjectView(view: ProjectView, opts: ProjectShowOpts): string[];
5
19
  export declare function registerProjectCommands(program: Command): void;
@@ -1,42 +1,109 @@
1
- import { bold, dim, underline } from "../style.js";
2
- import { formatItem, uuidDisplayWidth, withClient } from "./reads.js";
3
- function renderProjectView(view) {
4
- const everyItem = [
5
- ...view.active,
6
- ...view.headings.flatMap((g) => g.items),
7
- ...view.later.scheduled.flatMap((d) => d.items),
8
- ...view.later.repeating,
9
- ...view.later.someday,
10
- ...view.logged.slice(0, 10),
11
- ];
1
+ import { localToday } from "../../model/dates.js";
2
+ import { bold, dim, green, underline } from "../style.js";
3
+ import { countChip, deadlineDetail, loggedDate, projectCircle, thingsLink, whenValue, } from "../glyphs.js";
4
+ import { formatItem, openInThings, uuidDisplayWidth, withClient } from "./reads.js";
5
+ function loggedSlice(view, showLogged) {
6
+ if (showLogged === undefined)
7
+ return [];
8
+ if (showLogged === true)
9
+ return view.logged;
10
+ const n = Number(showLogged);
11
+ return Number.isInteger(n) && n > 0 ? view.logged.slice(0, n) : view.logged;
12
+ }
13
+ /**
14
+ * GUI parity: later rows (scheduled / repeating / someday) render INLINE
15
+ * beneath their heading — dimmed boxes and date chips carry the state — not
16
+ * exiled to a separate section that disassociates them from their headings.
17
+ * They are hidden by default like the GUI's toggle; `--show-later` reveals
18
+ * them, `--show-logged` reveals the full logbook.
19
+ */
20
+ export function renderProjectView(view, opts) {
21
+ const later = opts.showLater === true
22
+ ? [
23
+ ...view.later.scheduled.flatMap((d) => d.items),
24
+ ...view.later.repeating,
25
+ ...view.later.someday,
26
+ ]
27
+ : [];
28
+ const knownHeadings = new Set(view.headings.map((g) => g.heading.uuid));
29
+ const laterByHeading = new Map();
30
+ const looseLater = [];
31
+ for (const item of later) {
32
+ // A later row whose heading is absent from the view falls back to the
33
+ // loose block rather than vanishing.
34
+ if (item.heading !== null && knownHeadings.has(item.heading.uuid)) {
35
+ const list = laterByHeading.get(item.heading.uuid) ?? [];
36
+ list.push(item);
37
+ laterByHeading.set(item.heading.uuid, list);
38
+ }
39
+ else {
40
+ looseLater.push(item);
41
+ }
42
+ }
43
+ const logged = loggedSlice(view, opts.showLogged);
44
+ const everyItem = [...view.active, ...later, ...view.headings.flatMap((g) => g.items), ...logged];
12
45
  const w = uuidDisplayWidth([...everyItem, ...view.headings.map((g) => g.heading)]);
13
46
  // Rows inside this view never repeat the project's own name.
14
47
  const fmt = (i) => formatItem(i, w, { suppressProject: view.project.uuid });
48
+ // Card header, GUI order: title row (circle, progress chip, area context),
49
+ // share link, then labeled when/deadline/tags lines and the full note.
50
+ // The opened resource shows its tags green (GUI: list pills are gray).
51
+ const p = view.project;
52
+ const todayIso = localToday();
53
+ const areaSuffix = p.area === null ? "" : ` ${dim(`(${p.area.title})`)}`;
54
+ // In the Trash the card says so — the only view where the project's
55
+ // would-be-recovered (untrashed) children remain visible.
56
+ const trashedSuffix = p.trashed ? ` ${dim("(trashed)")}` : "";
15
57
  const lines = [
16
- `${view.project.uuid} ${bold(underline(view.project.title))}`,
17
- ` area: ${view.project.area?.title ?? ""} open: ${view.project.openUntrashedLeafActionsCount}/${view.project.untrashedLeafActionsCount}`,
58
+ `${bold("Project:")} ${projectCircle(p)} ${bold(underline(p.title))} ${countChip(p)}${areaSuffix}${trashedSuffix}`,
59
+ ` ${dim("uri:")} ${thingsLink(p.uuid)}`,
18
60
  ];
19
- lines.push("", bold("── Active ──"), ...(view.active.length ? view.active.map(fmt) : ["(none)"]));
61
+ if (p.status === "open") {
62
+ const when = whenValue(p, todayIso);
63
+ if (when !== null)
64
+ lines.push(` ${dim("when:")} ${when}`);
65
+ }
66
+ if (p.deadline !== null && p.deadline < "4000" && p.status === "open")
67
+ lines.push(` ${dim("deadline:")} ${deadlineDetail(p.deadline, todayIso)}`);
68
+ if (p.status !== "open" && p.stopped !== null)
69
+ lines.push(` ${dim("logged:")} ${loggedDate(p.stopped, todayIso)} ${dim(`(${p.status})`)}`);
70
+ if (p.tags.length > 0)
71
+ lines.push(` ${dim("tags:")} ${green(`#${p.tags.map((t) => t.title).join(" #")}`)}`);
72
+ if (p.inheritedTags !== undefined && p.inheritedTags.length > 0)
73
+ lines.push(` ${dim("inherited:")} ${green(`#${p.inheritedTags.map((t) => t.title).join(" #")}`)}`);
74
+ if (p.repeating.isTemplate)
75
+ lines.push(` ${dim("repeating:")} TEMPLATE (invisible in list views)`);
76
+ if (p.repeating.isInstance)
77
+ lines.push(` ${dim("repeating:")} instance of ${p.repeating.templateUuid}`);
78
+ if (p.notes !== "")
79
+ lines.push("", p.notes);
80
+ const looseRows = [...view.active, ...looseLater];
81
+ if (looseRows.length > 0)
82
+ lines.push("", ...looseRows.map(fmt));
20
83
  for (const group of view.headings) {
21
84
  // Headings are the GUI's dim in-project subheads, not structural
22
85
  // sections — rendered like item rows (their uuid IS addressable:
23
86
  // heading rename/archive), title dim+underlined.
24
- lines.push("", `${dim(group.heading.uuid.slice(0, w))} ${dim(underline(group.heading.title))}`, ...(group.items.length ? group.items.map(fmt) : ["(none)"]));
87
+ const members = [...group.items, ...(laterByHeading.get(group.heading.uuid) ?? [])];
88
+ lines.push("", `${dim(group.heading.uuid.slice(0, w))} ${dim(underline(group.heading.title))}`, ...(members.length > 0 ? members.map(fmt) : ["(none)"]));
25
89
  }
26
- if (view.later.scheduled.length || view.later.repeating.length || view.later.someday.length) {
27
- lines.push("", bold("── Later ──"));
28
- for (const day of view.later.scheduled) {
29
- lines.push(` ${day.date}:`, ...day.items.map(fmt));
30
- }
31
- if (view.later.repeating.length) {
32
- lines.push(" repeating templates:", ...view.later.repeating.map(fmt));
33
- }
34
- if (view.later.someday.length) {
35
- lines.push(" someday:", ...view.later.someday.map(fmt));
36
- }
90
+ // Default-hidden rows are never silent — a muted count names the toggle.
91
+ if (opts.showLater !== true) {
92
+ const hiddenLater = view.later.scheduled.reduce((n, d) => n + d.items.length, 0) +
93
+ view.later.repeating.length +
94
+ view.later.someday.length;
95
+ if (hiddenLater > 0)
96
+ lines.push("", dim(`…${hiddenLater} later item${hiddenLater === 1 ? "" : "s"} (--show-later)`));
97
+ }
98
+ if (logged.length > 0) {
99
+ const header = logged.length < view.logged.length
100
+ ? `── Logged (${logged.length} of ${view.logged.length}) ──`
101
+ : `── Logged (${view.logged.length}) ──`;
102
+ lines.push("", bold(header), ...logged.map(fmt));
103
+ }
104
+ else if (view.logged.length > 0) {
105
+ lines.push("", dim(`…${view.logged.length} logged (--show-logged)`));
37
106
  }
38
- if (view.logged.length)
39
- lines.push("", bold(`── Logged (${view.logged.length}) ──`), ...view.logged.slice(0, 10).map(fmt));
40
107
  if (view.trashed.length)
41
108
  lines.push("", bold(`── Trashed (${view.trashed.length}) ──`));
42
109
  return lines;
@@ -45,11 +112,28 @@ export function registerProjectCommands(program) {
45
112
  const project = program.command("project").description("Project-scoped operations");
46
113
  project
47
114
  .command("show <ref>")
48
- .description("Composite project view mirroring the native UI: active items, headings, later (scheduled/repeating/someday), logged, trashed. Target by uuid or unique name.")
115
+ .description("Composite project view mirroring the native UI: active items and headings. --show-later adds scheduled/repeating/someday rows inline under their headings; --show-logged adds the full logbook. Target by uuid or unique name.")
116
+ .option("--show-later", "include scheduled, repeating, and someday rows")
117
+ .option("--show-logged [n]", "include logged items (bare flag = all; pass a count to cap)")
118
+ .option("--json", "emit versioned JSON envelope on stdout")
119
+ .option("--db <path>", "explicit database path")
120
+ .action((ref, opts) => {
121
+ withClient(opts, "project-view", (c) => c.read.projectView(ref), ((d) => renderProjectView(d, opts)));
122
+ });
123
+ project
124
+ .command("open <ref>")
125
+ .description("Open the project in the Things app — foregrounds the GUI on this Mac (NOT headless). Errors when the reference is not a project.")
49
126
  .option("--json", "emit versioned JSON envelope on stdout")
50
127
  .option("--db <path>", "explicit database path")
51
128
  .action((ref, opts) => {
52
- withClient(opts, "project-view", (c) => c.read.projectView(ref), renderProjectView);
129
+ withClient(opts, "open", (c) => {
130
+ const t = c.read.showTarget(ref);
131
+ if (t.kind !== "project" || t.viaHeading === true) {
132
+ const what = t.viaHeading === true ? "heading" : t.kind;
133
+ throw new RangeError(`"${ref}" is a ${what}, not a project (try \`things open\`)`);
134
+ }
135
+ return { uri: openInThings(t.uuid) };
136
+ }, ((d) => [`opened ${d.uri}`]));
53
137
  });
54
138
  }
55
139
  //# sourceMappingURL=project.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/cli/commands/project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/cli/commands/project.ts"],"names":[],"mappings":"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"}
@@ -12,26 +12,53 @@ interface GlobalReadOpts {
12
12
  export declare function withClient(opts: GlobalReadOpts, kind: string, fn: (client: ThingsClient) => unknown, render: (data: never) => string[]): void;
13
13
  export interface FormatOpts {
14
14
  /**
15
- * Render a grouped project TITLE row: bold+underlined title, no type
16
- * marker — the styling carries the type (the GUI's project-header look).
15
+ * Render a grouped project TITLE row: bold+underlined title (the GUI's
16
+ * project-header look) — the circle glyph and count chip still apply.
17
17
  */
18
18
  projectTitle?: boolean;
19
19
  /** Container uuids already implied by surrounding output — their context suffix is dropped. */
20
20
  suppressProject?: string | null;
21
21
  suppressArea?: string | null;
22
+ /** Reference instant for date-relative tokens (tests pin this; defaults to now). */
23
+ now?: Date;
24
+ /** Pre-styled Today/Evening mark (★/⏾), rendered right after the box — GUI position. */
25
+ mark?: string | null;
26
+ /** Dim status word after the box (the GUI's waiting/paused/ended chips on repeating templates). */
27
+ statusWord?: string;
28
+ /** Suppress the ‹date› chip (rows under a day header already carry the date). */
29
+ hideDateChip?: boolean;
22
30
  }
23
31
  /**
24
- * One item line: `<uuid-prefix> <marker> [meta …] <title> #tags (container)`.
25
- * Human output shows a SHORTENED uuid prefix (every command accepts unique
26
- * prefixes >= 6 chars); `uuidWidth` is the display length from
27
- * uuidDisplayWidth never below 8 so a copied prefix stays unique across
28
- * the whole database, not just the rendered list. Tags follow the title
29
- * (`#`-prefixed, space-separated), mirroring the GUI. Exactly one space
30
- * separates every following token; meta tokens colorize on a TTY only
31
- * (../style.ts) piped output stays plain. `--json` always carries full
32
- * uuids.
32
+ * One item line:
33
+ * `<uuid-prefix> <box> [★|⏾] [logged-date] [‹chip›] <title> [‹n›] [⍾] [≡] [≔] (container) #tags [⚑ deadline]`.
34
+ * Repeating templates seat INSIDE the box (`[↻]`/`(↻)`) rather than as a
35
+ * separate mark; open project rows render their circle and title blue.
36
+ * The box is the glyph-language state carrier (../glyphs.ts): `[ ]`-family
37
+ * for to-dos, `( )`-family for projects state survives with color
38
+ * stripped. Completed titles dim; canceled titles dim+strike (the `[×]`
39
+ * mark keeps the state when strike/ANSI is unavailable). Human output shows
40
+ * a SHORTENED uuid prefix (every command accepts unique prefixes >= 6
41
+ * chars); `uuidWidth` is the display length from uuidDisplayWidth — never
42
+ * below 8 so a copied prefix stays unique across the whole database, not
43
+ * just the rendered list. Tags follow the title (`#`-prefixed, green — GUI
44
+ * color), after the count chip (projects), notes marker, and container.
45
+ * Heading-nested to-dos label their parent PROJECT (via headingProject),
46
+ * never the heading — GUI behavior. Colors engage on a TTY only
47
+ * (../style.ts); `--json` always carries full uuids.
33
48
  */
34
49
  export declare function formatItem(item: ListItem, uuidWidth?: number, opts?: FormatOpts): string;
50
+ /**
51
+ * Row prefix in today-aware views: yellow ★ for Today members, cyan ⏾ for
52
+ * effective This-Evening members (raw evening assignment counts only while
53
+ * startDate is exactly today — the UI's daily expiry), null otherwise.
54
+ */
55
+ export declare function todayMark(item: ListItem, now?: Date): string | null;
56
+ /**
57
+ * Foreground the Things app on a resource via its share URI. A GUI action
58
+ * on this Mac — NOT headless; the shared implementation behind every
59
+ * `open` command. Returns the URI it launched.
60
+ */
61
+ export declare function openInThings(uuid: string): string;
35
62
  /**
36
63
  * Display width for a list's uuid column: the shortest prefix that is
37
64
  * unique WITHIN the list, floored at UUID_DISPLAY_MIN (list-local
@@ -40,6 +67,57 @@ export declare function formatItem(item: ListItem, uuidWidth?: number, opts?: Fo
40
67
  export declare function uuidDisplayWidth(items: Array<{
41
68
  uuid: string;
42
69
  }>): number;
70
+ /** Hidden-later counts per sidebar group (null area = the loose block). */
71
+ export interface LaterHints {
72
+ /** Sidebar-ordered, INCLUDING groups whose every project is later. */
73
+ groups: Array<{
74
+ area: {
75
+ uuid: string;
76
+ title: string;
77
+ } | null;
78
+ hidden: number;
79
+ }>;
80
+ }
81
+ /**
82
+ * The sidebar mirror for `things projects`: loose projects first (the GUI
83
+ * lists them above the areas), then a `── ⬡ Area ──` header per area with
84
+ * its projects beneath (the redundant `(Area)` suffix suppressed). Items
85
+ * arrive from projectsView already in sidebar order — this only inserts the
86
+ * headers. Denser than renderSections on purpose: no title styling and no
87
+ * blank line per project (every row here IS a project). With `hints`,
88
+ * default-hidden later projects are never silent: each group trails a muted
89
+ * `…n later projects` count (a later-only area still gets its header), and
90
+ * the output ends with the flag that reveals them.
91
+ */
92
+ export declare function renderProjectsSidebar(items: ListItem[], hints?: LaterHints): string[];
93
+ /**
94
+ * `--until` accepting whole periods: `2024` means through Dec 31 2024,
95
+ * `2024-03` through Mar 31, `2024-03-05` through end of that day; relative
96
+ * periods (`2w`, `1m`, `1y`) count FORWARD from now through the end of the
97
+ * landing day; anything else parses as an instant.
98
+ */
99
+ export declare function parsePeriodEnd(s: string, now?: Date): Date;
100
+ /**
101
+ * `--since` accepting the same vocabulary at the period's START: `2024` =
102
+ * Jan 1 2024 00:00, `2024-03` = Mar 1, `2024-03-05` = that midnight;
103
+ * relative periods (`2w`, `1m`) count BACKWARD from now to the landing
104
+ * day's midnight; anything else parses as an instant.
105
+ */
106
+ export declare function parsePeriodStart(s: string, now?: Date): Date;
107
+ /**
108
+ * Upcoming rows under GUI-style date headers (empty periods are simply
109
+ * absent), with the trailing Repeating To-Dos section: templates with no
110
+ * set next occurrence, carrying their waiting/paused/ended status word and
111
+ * the bare ⚑ when the rule will assign a deadline per occurrence.
112
+ */
113
+ export declare function renderUpcoming(items: ListItem[], now?: Date): string[];
114
+ /**
115
+ * Logbook rows under GUI-style date headings, month granularity throughout
116
+ * — `── July ──` within the current year, `── March 2025 ──` beyond (finer
117
+ * than the GUI's bare per-year buckets, deliberately). When the row count
118
+ * hits the limit, a trailing note says the range is NOT exhaustive.
119
+ */
120
+ export declare function renderLogbook(items: ListItem[], limit: number, now?: Date): string[];
43
121
  /**
44
122
  * Sidebar-grouped views (anytime/someday), rendered the way the GUI reads:
45
123
  * the area-less block headerless first, then one `── <area> ──` header per
@@ -49,7 +127,7 @@ export declare function uuidDisplayWidth(items: Array<{
49
127
  * (an area header covers its rows; a project title row covers the to-dos
50
128
  * beneath it — a clustered child whose project row is absent, e.g. under a
51
129
  * tag filter, keeps its `(project)` suffix). `star` prefixes each item line
52
- * with the Today-membership star.
130
+ * with the Today-membership mark (★, or ⏾ for This-Evening members).
53
131
  */
54
132
  export declare function renderSections(sections: SidebarSection[], star?: boolean): string[];
55
133
  export declare function registerReadCommands(program: Command): void;