ente-cli 0.4.68 → 0.4.69
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/dist/SKILL.md +2 -2
- package/dist/cli.mjs +106 -92
- package/dist/cli.mjs.map +4 -4
- package/package.json +1 -1
package/dist/SKILL.md
CHANGED
|
@@ -133,7 +133,7 @@ ente activity create --type meeting --title "Call with Jane" --entity "Jane Doe"
|
|
|
133
133
|
ente activity search "quarterly review" [--entity "Acme"] [--type meeting] [--limit 10] [--json]
|
|
134
134
|
ente activity get <activityId> [--json] # complete detail: body, full nested agenda, messages/replies, entities, attachments
|
|
135
135
|
ente activity transcript <activityId> [--grep "Preis"] [--context 2] [--recording <id>] [--json] # transcript of the recording behind it
|
|
136
|
-
ente activity update <activityId> [--title "…"] [--content "…"] [--entity-add "Bob"] [--entity-remove "Carol"] [--agent-assignee <agentId> ... | --clear-agent-assignees] [--json]
|
|
136
|
+
ente activity update <activityId> [--title "…"] [--content "…"] [--deadline "2026-05-26" | --clear-deadline] [--entity-add "Bob"] [--entity-remove "Carol"] [--agent-assignee <agentId> ... | --clear-agent-assignees] [--json]
|
|
137
137
|
ente activity content read <activityId> [--cursor <cursor> --expected-version <version>] [--max-blocks 20] [--max-characters 12000] [--json]
|
|
138
138
|
ente activity content edit <activityId> --expected-version <version> --operations-file ./operations.json [--json]
|
|
139
139
|
ente activity message add <activityId> (--content "…" | --content-file ./update.md) [--json]
|
|
@@ -162,7 +162,7 @@ ente tasks [--json] # open tasks by deadline
|
|
|
162
162
|
ente task list [--due today|overdue|all] [--entity "Jane"] [--json]
|
|
163
163
|
ente task get 5 [--space "Work"] [--json]
|
|
164
164
|
ente task create "Reply to Jane" --entity "Jane Doe" --space "Personal" [--deadline "2026-05-23 14:00"] [--content "…"] [--assignee <userId-or-email>] [--json]
|
|
165
|
-
ente task update 5 [--title "…"] [--content "…"] [--deadline "2026-05-26"] [--attr k=v] [--json]
|
|
165
|
+
ente task update 5 [--title "…"] [--content "…"] [--deadline "2026-05-26" | --clear-deadline] [--attr k=v] [--json] # 5 = #N or activity ID
|
|
166
166
|
ente task done 5 [--json]
|
|
167
167
|
ente space members --space "Work" [--json]
|
|
168
168
|
ente task assign 5 <userId-or-email> [--json]
|
package/dist/cli.mjs
CHANGED
|
@@ -3711,7 +3711,7 @@ function warn(opts, latest) {
|
|
|
3711
3711
|
}
|
|
3712
3712
|
|
|
3713
3713
|
// ente/version.ts
|
|
3714
|
-
var VERSION = "0.4.
|
|
3714
|
+
var VERSION = "0.4.69";
|
|
3715
3715
|
|
|
3716
3716
|
// ente/branding.ts
|
|
3717
3717
|
var NPM_REGISTRY = "https://registry.npmjs.org";
|
|
@@ -12247,6 +12247,96 @@ function readContentOption(content, contentFile) {
|
|
|
12247
12247
|
return void 0;
|
|
12248
12248
|
}
|
|
12249
12249
|
|
|
12250
|
+
// ente/deadline.ts
|
|
12251
|
+
var DEFAULT_HOUR = 22;
|
|
12252
|
+
var DEFAULT_MINUTE = 0;
|
|
12253
|
+
function addDaysToBerlinToday(days) {
|
|
12254
|
+
const t = berlinToday();
|
|
12255
|
+
const dt = new Date(Date.UTC(t.year, t.month - 1, t.day) + days * 864e5);
|
|
12256
|
+
return { year: dt.getUTCFullYear(), month: dt.getUTCMonth() + 1, day: dt.getUTCDate() };
|
|
12257
|
+
}
|
|
12258
|
+
function parseTimeOrDefault(s) {
|
|
12259
|
+
if (!s) return [DEFAULT_HOUR, DEFAULT_MINUTE];
|
|
12260
|
+
const m = /^(\d{1,2}):(\d{2})$/.exec(s);
|
|
12261
|
+
if (!m) throw new Error(`Invalid time format: '${s}'. Use HH:MM (e.g. 14:00).`);
|
|
12262
|
+
const hour = Number(m[1]);
|
|
12263
|
+
const minute = Number(m[2]);
|
|
12264
|
+
if (hour > 23 || minute > 59) throw new Error(`Invalid time format: '${s}'.`);
|
|
12265
|
+
return [hour, minute];
|
|
12266
|
+
}
|
|
12267
|
+
function validateDate(year, month, day, original) {
|
|
12268
|
+
if (month < 1 || month > 12 || day < 1 || day > 31) {
|
|
12269
|
+
throw new Error(`Invalid date: '${original}'.`);
|
|
12270
|
+
}
|
|
12271
|
+
const d = new Date(Date.UTC(year, month - 1, day));
|
|
12272
|
+
if (d.getUTCFullYear() !== year || d.getUTCMonth() + 1 !== month || d.getUTCDate() !== day) {
|
|
12273
|
+
throw new Error(`Invalid date: '${original}' \u2014 day ${day} does not exist in month ${month}.`);
|
|
12274
|
+
}
|
|
12275
|
+
}
|
|
12276
|
+
function parseDeadline(input) {
|
|
12277
|
+
const trimmed = input.trim().toLowerCase();
|
|
12278
|
+
if (trimmed.startsWith("tomorrow")) {
|
|
12279
|
+
const [hour, minute] = parseTimeOrDefault(trimmed.slice("tomorrow".length).trim());
|
|
12280
|
+
const t = addDaysToBerlinToday(1);
|
|
12281
|
+
return berlinToEpochMs(t.year, t.month, t.day, hour, minute);
|
|
12282
|
+
}
|
|
12283
|
+
if (trimmed.startsWith("today")) {
|
|
12284
|
+
const [hour, minute] = parseTimeOrDefault(trimmed.slice("today".length).trim());
|
|
12285
|
+
const t = addDaysToBerlinToday(0);
|
|
12286
|
+
return berlinToEpochMs(t.year, t.month, t.day, hour, minute);
|
|
12287
|
+
}
|
|
12288
|
+
const rel = /^\+(\d+)\s*(days?|weeks?)$/.exec(trimmed);
|
|
12289
|
+
if (rel) {
|
|
12290
|
+
const n = Number(rel[1]);
|
|
12291
|
+
const days = rel[2].startsWith("week") ? n * 7 : n;
|
|
12292
|
+
const t = addDaysToBerlinToday(days);
|
|
12293
|
+
return berlinToEpochMs(t.year, t.month, t.day, DEFAULT_HOUR, DEFAULT_MINUTE);
|
|
12294
|
+
}
|
|
12295
|
+
const iso = /^(\d{4})-(\d{2})-(\d{2})t(\d{2}):(\d{2})(?::(\d{2}))?(?:z|([+-])(\d{2}):(\d{2}))$/.exec(
|
|
12296
|
+
trimmed
|
|
12297
|
+
);
|
|
12298
|
+
if (iso) {
|
|
12299
|
+
const year = Number(iso[1]);
|
|
12300
|
+
const month = Number(iso[2]);
|
|
12301
|
+
const day = Number(iso[3]);
|
|
12302
|
+
const hour = Number(iso[4]);
|
|
12303
|
+
const minute = Number(iso[5]);
|
|
12304
|
+
const second = iso[6] ? Number(iso[6]) : 0;
|
|
12305
|
+
validateDate(year, month, day, input);
|
|
12306
|
+
if (hour > 23 || minute > 59 || second > 59) throw new Error(`Invalid time in deadline: '${input}'.`);
|
|
12307
|
+
let offsetMs = 0;
|
|
12308
|
+
if (iso[7]) {
|
|
12309
|
+
const sign = iso[7] === "-" ? -1 : 1;
|
|
12310
|
+
offsetMs = sign * (Number(iso[8]) * 60 + Number(iso[9])) * 6e4;
|
|
12311
|
+
}
|
|
12312
|
+
return Date.UTC(year, month - 1, day, hour, minute, second) - offsetMs;
|
|
12313
|
+
}
|
|
12314
|
+
const date = /^(\d{4})-(\d{2})-(\d{2})(?:\s+(\d{1,2}):(\d{2}))?$/.exec(trimmed);
|
|
12315
|
+
if (date) {
|
|
12316
|
+
const year = Number(date[1]);
|
|
12317
|
+
const month = Number(date[2]);
|
|
12318
|
+
const day = Number(date[3]);
|
|
12319
|
+
validateDate(year, month, day, input);
|
|
12320
|
+
const hour = date[4] ? Number(date[4]) : DEFAULT_HOUR;
|
|
12321
|
+
const minute = date[5] ? Number(date[5]) : DEFAULT_MINUTE;
|
|
12322
|
+
if (hour > 23 || minute > 59) throw new Error(`Invalid time in deadline: '${input}'.`);
|
|
12323
|
+
return berlinToEpochMs(year, month, day, hour, minute);
|
|
12324
|
+
}
|
|
12325
|
+
throw new Error(
|
|
12326
|
+
`Cannot parse deadline '${input}'. Accepted: "tomorrow", "today", "+3 days", "+1 week", "2026-03-15", "2026-03-15 14:00", "2026-03-15T14:00:00+01:00"`
|
|
12327
|
+
);
|
|
12328
|
+
}
|
|
12329
|
+
function defaultDeadline() {
|
|
12330
|
+
const t = addDaysToBerlinToday(1);
|
|
12331
|
+
return berlinToEpochMs(t.year, t.month, t.day, DEFAULT_HOUR, DEFAULT_MINUTE);
|
|
12332
|
+
}
|
|
12333
|
+
function deadlineChange(deadline, clear) {
|
|
12334
|
+
if (clear && deadline !== void 0) throw new Error("Use either --deadline or --clear-deadline, not both.");
|
|
12335
|
+
if (clear) return { deadline: void 0 };
|
|
12336
|
+
if (deadline !== void 0) return { deadline: parseDeadline(deadline) };
|
|
12337
|
+
return null;
|
|
12338
|
+
}
|
|
12339
|
+
|
|
12250
12340
|
// ente/fileAttachments.ts
|
|
12251
12341
|
import { readFileSync as readFileSync8 } from "node:fs";
|
|
12252
12342
|
import { basename, extname } from "node:path";
|
|
@@ -12413,6 +12503,7 @@ var activitiesCreate = makeFunctionReference("activities:create");
|
|
|
12413
12503
|
var activitiesGetCompleteByIdRich = makeFunctionReference("activities:getCompleteByIdRich");
|
|
12414
12504
|
var activitiesGetByIdRich = makeFunctionReference("activities:getByIdRich");
|
|
12415
12505
|
var activitiesSearchRich = makeFunctionReference("activities:searchRich");
|
|
12506
|
+
var activitiesUpdateDeadline = makeFunctionReference("activities:updateDeadline");
|
|
12416
12507
|
var activitiesUpdateTitle = makeFunctionReference("activities:updateTitle");
|
|
12417
12508
|
var activitiesSetContentFromMarkdown = makeFunctionReference("activities:setContentFromMarkdown");
|
|
12418
12509
|
var activitiesReadContent = makeFunctionReference("activities:readContentDurable");
|
|
@@ -12676,13 +12767,16 @@ var ActivityUpdate = class extends ProfileCommand {
|
|
|
12676
12767
|
content = options_exports.String("--content", { description: "Update content" });
|
|
12677
12768
|
contentFile = options_exports.String("--content-file", { description: "Read updated content from a markdown/text file" });
|
|
12678
12769
|
title = options_exports.String("--title", { description: "Update title" });
|
|
12770
|
+
deadline = options_exports.String("--deadline", { description: "Update deadline (human-friendly)" });
|
|
12771
|
+
clearDeadline = options_exports.Boolean("--clear-deadline", false, { description: "Remove the deadline" });
|
|
12679
12772
|
entityAdd = options_exports.Array("--entity-add", { description: "Link additional entities" });
|
|
12680
12773
|
entityRemove = options_exports.Array("--entity-remove", { description: "Unlink entities" });
|
|
12681
12774
|
async run() {
|
|
12682
12775
|
const content = readContentOption(this.content, this.contentFile);
|
|
12776
|
+
const deadline = deadlineChange(this.deadline, this.clearDeadline);
|
|
12683
12777
|
const hasEntityChange = !!(this.entityAdd && this.entityAdd.length || this.entityRemove && this.entityRemove.length);
|
|
12684
|
-
if (this.content === void 0 && this.contentFile === void 0 && this.title === void 0 && !hasEntityChange && !this.agentAssignee?.length && !this.clearAgentAssignees) {
|
|
12685
|
-
this.err("Nothing to update. Specify content, title, entity links or agent assignees.");
|
|
12778
|
+
if (this.content === void 0 && this.contentFile === void 0 && this.title === void 0 && deadline === null && !hasEntityChange && !this.agentAssignee?.length && !this.clearAgentAssignees) {
|
|
12779
|
+
this.err("Nothing to update. Specify content, title, deadline, entity links or agent assignees.");
|
|
12686
12780
|
return 1;
|
|
12687
12781
|
}
|
|
12688
12782
|
if (this.clearAgentAssignees && this.agentAssignee?.length) throw new Error("Choose --agent-assignee or --clear-agent-assignees");
|
|
@@ -12692,6 +12786,7 @@ var ActivityUpdate = class extends ProfileCommand {
|
|
|
12692
12786
|
{ activityId: this.id, agentAssigneeIds: this.agentAssignee ?? [] }
|
|
12693
12787
|
);
|
|
12694
12788
|
if (this.title !== void 0) await caller.mutation(activitiesUpdateTitle, { activityId: this.id, title: this.title });
|
|
12789
|
+
if (deadline) await caller.mutation(activitiesUpdateDeadline, { activityId: this.id, ...deadline });
|
|
12695
12790
|
if (content !== void 0) await caller.mutation(activitiesSetContentFromMarkdown, { activityId: this.id, markdown: content });
|
|
12696
12791
|
if (hasEntityChange) {
|
|
12697
12792
|
const rich = await caller.query(activitiesGetByIdRich, { activityId: this.id });
|
|
@@ -13174,90 +13269,6 @@ var ActivityTranscript = class extends ProfileCommand {
|
|
|
13174
13269
|
};
|
|
13175
13270
|
var ACTIVITY_TRANSCRIPT_COMMANDS = [ActivityTranscript];
|
|
13176
13271
|
|
|
13177
|
-
// ente/deadline.ts
|
|
13178
|
-
var DEFAULT_HOUR = 22;
|
|
13179
|
-
var DEFAULT_MINUTE = 0;
|
|
13180
|
-
function addDaysToBerlinToday(days) {
|
|
13181
|
-
const t = berlinToday();
|
|
13182
|
-
const dt = new Date(Date.UTC(t.year, t.month - 1, t.day) + days * 864e5);
|
|
13183
|
-
return { year: dt.getUTCFullYear(), month: dt.getUTCMonth() + 1, day: dt.getUTCDate() };
|
|
13184
|
-
}
|
|
13185
|
-
function parseTimeOrDefault(s) {
|
|
13186
|
-
if (!s) return [DEFAULT_HOUR, DEFAULT_MINUTE];
|
|
13187
|
-
const m = /^(\d{1,2}):(\d{2})$/.exec(s);
|
|
13188
|
-
if (!m) throw new Error(`Invalid time format: '${s}'. Use HH:MM (e.g. 14:00).`);
|
|
13189
|
-
const hour = Number(m[1]);
|
|
13190
|
-
const minute = Number(m[2]);
|
|
13191
|
-
if (hour > 23 || minute > 59) throw new Error(`Invalid time format: '${s}'.`);
|
|
13192
|
-
return [hour, minute];
|
|
13193
|
-
}
|
|
13194
|
-
function validateDate(year, month, day, original) {
|
|
13195
|
-
if (month < 1 || month > 12 || day < 1 || day > 31) {
|
|
13196
|
-
throw new Error(`Invalid date: '${original}'.`);
|
|
13197
|
-
}
|
|
13198
|
-
const d = new Date(Date.UTC(year, month - 1, day));
|
|
13199
|
-
if (d.getUTCFullYear() !== year || d.getUTCMonth() + 1 !== month || d.getUTCDate() !== day) {
|
|
13200
|
-
throw new Error(`Invalid date: '${original}' \u2014 day ${day} does not exist in month ${month}.`);
|
|
13201
|
-
}
|
|
13202
|
-
}
|
|
13203
|
-
function parseDeadline(input) {
|
|
13204
|
-
const trimmed = input.trim().toLowerCase();
|
|
13205
|
-
if (trimmed.startsWith("tomorrow")) {
|
|
13206
|
-
const [hour, minute] = parseTimeOrDefault(trimmed.slice("tomorrow".length).trim());
|
|
13207
|
-
const t = addDaysToBerlinToday(1);
|
|
13208
|
-
return berlinToEpochMs(t.year, t.month, t.day, hour, minute);
|
|
13209
|
-
}
|
|
13210
|
-
if (trimmed.startsWith("today")) {
|
|
13211
|
-
const [hour, minute] = parseTimeOrDefault(trimmed.slice("today".length).trim());
|
|
13212
|
-
const t = addDaysToBerlinToday(0);
|
|
13213
|
-
return berlinToEpochMs(t.year, t.month, t.day, hour, minute);
|
|
13214
|
-
}
|
|
13215
|
-
const rel = /^\+(\d+)\s*(days?|weeks?)$/.exec(trimmed);
|
|
13216
|
-
if (rel) {
|
|
13217
|
-
const n = Number(rel[1]);
|
|
13218
|
-
const days = rel[2].startsWith("week") ? n * 7 : n;
|
|
13219
|
-
const t = addDaysToBerlinToday(days);
|
|
13220
|
-
return berlinToEpochMs(t.year, t.month, t.day, DEFAULT_HOUR, DEFAULT_MINUTE);
|
|
13221
|
-
}
|
|
13222
|
-
const iso = /^(\d{4})-(\d{2})-(\d{2})t(\d{2}):(\d{2})(?::(\d{2}))?(?:z|([+-])(\d{2}):(\d{2}))$/.exec(
|
|
13223
|
-
trimmed
|
|
13224
|
-
);
|
|
13225
|
-
if (iso) {
|
|
13226
|
-
const year = Number(iso[1]);
|
|
13227
|
-
const month = Number(iso[2]);
|
|
13228
|
-
const day = Number(iso[3]);
|
|
13229
|
-
const hour = Number(iso[4]);
|
|
13230
|
-
const minute = Number(iso[5]);
|
|
13231
|
-
const second = iso[6] ? Number(iso[6]) : 0;
|
|
13232
|
-
validateDate(year, month, day, input);
|
|
13233
|
-
if (hour > 23 || minute > 59 || second > 59) throw new Error(`Invalid time in deadline: '${input}'.`);
|
|
13234
|
-
let offsetMs = 0;
|
|
13235
|
-
if (iso[7]) {
|
|
13236
|
-
const sign = iso[7] === "-" ? -1 : 1;
|
|
13237
|
-
offsetMs = sign * (Number(iso[8]) * 60 + Number(iso[9])) * 6e4;
|
|
13238
|
-
}
|
|
13239
|
-
return Date.UTC(year, month - 1, day, hour, minute, second) - offsetMs;
|
|
13240
|
-
}
|
|
13241
|
-
const date = /^(\d{4})-(\d{2})-(\d{2})(?:\s+(\d{1,2}):(\d{2}))?$/.exec(trimmed);
|
|
13242
|
-
if (date) {
|
|
13243
|
-
const year = Number(date[1]);
|
|
13244
|
-
const month = Number(date[2]);
|
|
13245
|
-
const day = Number(date[3]);
|
|
13246
|
-
validateDate(year, month, day, input);
|
|
13247
|
-
const hour = date[4] ? Number(date[4]) : DEFAULT_HOUR;
|
|
13248
|
-
const minute = date[5] ? Number(date[5]) : DEFAULT_MINUTE;
|
|
13249
|
-
if (hour > 23 || minute > 59) throw new Error(`Invalid time in deadline: '${input}'.`);
|
|
13250
|
-
return berlinToEpochMs(year, month, day, hour, minute);
|
|
13251
|
-
}
|
|
13252
|
-
throw new Error(
|
|
13253
|
-
`Cannot parse deadline '${input}'. Accepted: "tomorrow", "today", "+3 days", "+1 week", "2026-03-15", "2026-03-15 14:00", "2026-03-15T14:00:00+01:00"`
|
|
13254
|
-
);
|
|
13255
|
-
}
|
|
13256
|
-
function defaultDeadline() {
|
|
13257
|
-
const t = addDaysToBerlinToday(1);
|
|
13258
|
-
return berlinToEpochMs(t.year, t.month, t.day, DEFAULT_HOUR, DEFAULT_MINUTE);
|
|
13259
|
-
}
|
|
13260
|
-
|
|
13261
13272
|
// ente/commands/task.ts
|
|
13262
13273
|
function toTaskItem(rich) {
|
|
13263
13274
|
return {
|
|
@@ -13296,7 +13307,7 @@ var activitiesSetAttribute = makeFunctionReference("activities:setAttribute");
|
|
|
13296
13307
|
var activitiesUpdateCreatedAt2 = makeFunctionReference("activities:updateCreatedAt");
|
|
13297
13308
|
var activitiesUpdateTitle2 = makeFunctionReference("activities:updateTitle");
|
|
13298
13309
|
var activitiesSetContentFromMarkdown2 = makeFunctionReference("activities:setContentFromMarkdown");
|
|
13299
|
-
var
|
|
13310
|
+
var activitiesUpdateDeadline2 = makeFunctionReference("activities:updateDeadline");
|
|
13300
13311
|
var activitiesSetCompleted = makeFunctionReference("activities:setCompleted");
|
|
13301
13312
|
var activitiesUpdateAssignees = makeFunctionReference("activities:updateAssignees");
|
|
13302
13313
|
function parseShortId(idStr) {
|
|
@@ -13462,17 +13473,19 @@ var TaskUpdate = class extends ProfileCommand {
|
|
|
13462
13473
|
content = options_exports.String("--content", { description: "Update content" });
|
|
13463
13474
|
attr = options_exports.Array("--attr", { description: "Set attributes as key=value pairs" });
|
|
13464
13475
|
deadline = options_exports.String("--deadline", { description: "Update deadline (human-friendly)" });
|
|
13476
|
+
clearDeadline = options_exports.Boolean("--clear-deadline", false, { description: "Remove the deadline" });
|
|
13465
13477
|
async run() {
|
|
13466
13478
|
const attributes = parseAttrs(this.attr);
|
|
13467
|
-
|
|
13468
|
-
|
|
13479
|
+
const deadline = deadlineChange(this.deadline, this.clearDeadline);
|
|
13480
|
+
if (this.title === void 0 && this.content === void 0 && deadline === null && Object.keys(attributes).length === 0) {
|
|
13481
|
+
this.err("Nothing to update. Specify --title, --content, --attr, --deadline, or --clear-deadline.");
|
|
13469
13482
|
return 1;
|
|
13470
13483
|
}
|
|
13471
13484
|
const caller = await resolveCaller();
|
|
13472
13485
|
const activityId = await resolveTaskIdC(caller, this.id);
|
|
13473
13486
|
if (this.title !== void 0) await caller.mutation(activitiesUpdateTitle2, { activityId, title: this.title });
|
|
13474
13487
|
if (this.content !== void 0) await caller.mutation(activitiesSetContentFromMarkdown2, { activityId, markdown: this.content });
|
|
13475
|
-
if (
|
|
13488
|
+
if (deadline) await caller.mutation(activitiesUpdateDeadline2, { activityId, ...deadline });
|
|
13476
13489
|
for (const [key, value] of Object.entries(attributes)) {
|
|
13477
13490
|
await caller.mutation(activitiesSetAttribute, { activityId, key, value });
|
|
13478
13491
|
}
|
|
@@ -15986,7 +15999,8 @@ Creating tasks:
|
|
|
15986
15999
|
ente task create "Reply to Ashley" --entity "Ashley" --space "Personal" --deadline "tomorrow" --assignee ashley@example.com
|
|
15987
16000
|
ente task create "Fix bug" --entity "TiVA" --space "TiVA" --deadline "+3 days" --attr github-issue=https://...
|
|
15988
16001
|
|
|
15989
|
-
|
|
16002
|
+
Without --deadline a task is due tomorrow 22:00 Berlin; --no-deadline creates it without one.
|
|
16003
|
+
Remove a deadline later with: ente task update 5 --clear-deadline
|
|
15990
16004
|
|
|
15991
16005
|
Deadlines (human-friendly):
|
|
15992
16006
|
"tomorrow" \u2192 tomorrow 22:00 Berlin
|