taskify-nostr 0.1.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 +271 -0
- package/dist/aiClient.js +40 -0
- package/dist/completions.js +637 -0
- package/dist/config.js +39 -0
- package/dist/index.js +2074 -0
- package/dist/nostrRuntime.js +888 -0
- package/dist/onboarding.js +93 -0
- package/dist/render.js +207 -0
- package/dist/shared/agentDispatcher.js +595 -0
- package/dist/shared/agentIdempotency.js +50 -0
- package/dist/shared/agentRuntime.js +7 -0
- package/dist/shared/agentSecurity.js +161 -0
- package/dist/shared/boardUtils.js +441 -0
- package/dist/shared/dateUtils.js +123 -0
- package/dist/shared/nostr.js +70 -0
- package/dist/shared/settingsTypes.js +23 -0
- package/dist/shared/taskTypes.js +12 -0
- package/dist/shared/taskUtils.js +261 -0
- package/dist/taskCache.js +59 -0
- package/package.json +44 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
// Shell completion scripts for taskify CLI.
|
|
2
|
+
// Generated programmatically — do NOT use a completion library.
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
function readBoardNames() {
|
|
7
|
+
try {
|
|
8
|
+
const configPath = join(homedir(), ".taskify-cli", "config.json");
|
|
9
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
10
|
+
const cfg = JSON.parse(raw);
|
|
11
|
+
return (cfg.boards ?? []).map((b) => b.name);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function zshCompletion() {
|
|
18
|
+
const boards = readBoardNames();
|
|
19
|
+
const boardList = boards.length > 0
|
|
20
|
+
? boards.map((n) => `'${n.replace(/'/g, "'\\''")}'`).join(" ")
|
|
21
|
+
: "";
|
|
22
|
+
const boardComplete = boardList
|
|
23
|
+
? ` local boards=(${boardList})\n _describe 'board' boards`
|
|
24
|
+
: ` # no boards configured`;
|
|
25
|
+
return `#compdef taskify
|
|
26
|
+
# taskify zsh completion
|
|
27
|
+
# Install: taskify completions --shell zsh > ~/.zsh/completions/_taskify
|
|
28
|
+
|
|
29
|
+
_taskify() {
|
|
30
|
+
local state
|
|
31
|
+
typeset -A opt_args
|
|
32
|
+
|
|
33
|
+
_arguments -C \\
|
|
34
|
+
'(-h --help)'{-h,--help}'[Show help]' \\
|
|
35
|
+
'(-V --version)'{-V,--version}'[Show version]' \\
|
|
36
|
+
'1: :->command' \\
|
|
37
|
+
'*:: :->args'
|
|
38
|
+
|
|
39
|
+
case $state in
|
|
40
|
+
command)
|
|
41
|
+
local commands
|
|
42
|
+
commands=(
|
|
43
|
+
'board:Manage boards'
|
|
44
|
+
'boards:List configured boards'
|
|
45
|
+
'list:List tasks'
|
|
46
|
+
'show:Show full task details'
|
|
47
|
+
'search:Search tasks by title or note'
|
|
48
|
+
'add:Create a new task'
|
|
49
|
+
'done:Mark a task as done'
|
|
50
|
+
'reopen:Reopen a completed task'
|
|
51
|
+
'update:Update task fields'
|
|
52
|
+
'delete:Delete a task'
|
|
53
|
+
'subtask:Toggle a subtask done/incomplete'
|
|
54
|
+
'remind:Set device-local reminders on a task'
|
|
55
|
+
'relay:Manage relay connections'
|
|
56
|
+
'cache:Manage task cache'
|
|
57
|
+
'trust:Manage trusted npubs'
|
|
58
|
+
'config:Manage CLI config'
|
|
59
|
+
'completions:Generate shell completions'
|
|
60
|
+
)
|
|
61
|
+
_describe 'command' commands
|
|
62
|
+
;;
|
|
63
|
+
args)
|
|
64
|
+
case $words[1] in
|
|
65
|
+
board)
|
|
66
|
+
_taskify_board
|
|
67
|
+
;;
|
|
68
|
+
list)
|
|
69
|
+
_arguments \\
|
|
70
|
+
'--board[Filter by board]:board:_taskify_boards' \\
|
|
71
|
+
'--status[Filter status]:status:(open done any)' \\
|
|
72
|
+
'--column[Filter by column]:column:' \\
|
|
73
|
+
'--refresh[Bypass cache and fetch live]' \\
|
|
74
|
+
'--json[Output as JSON]'
|
|
75
|
+
;;
|
|
76
|
+
show)
|
|
77
|
+
_arguments \\
|
|
78
|
+
'1:task id:_taskify_cached_task_ids' \\
|
|
79
|
+
'--board[Board to search in]:board:_taskify_boards' \\
|
|
80
|
+
'--json[Output as JSON]'
|
|
81
|
+
;;
|
|
82
|
+
search)
|
|
83
|
+
_arguments \\
|
|
84
|
+
'1:search query:' \\
|
|
85
|
+
'--board[Limit to board]:board:_taskify_boards' \\
|
|
86
|
+
'--json[Output as JSON]'
|
|
87
|
+
;;
|
|
88
|
+
add)
|
|
89
|
+
_arguments \\
|
|
90
|
+
'1:task title:' \\
|
|
91
|
+
'--board[Board to add to]:board:_taskify_boards' \\
|
|
92
|
+
'--due[Due date (YYYY-MM-DD)]:date:' \\
|
|
93
|
+
'--priority[Priority]:priority:(1 2 3)' \\
|
|
94
|
+
'--note[Note text]:note:' \\
|
|
95
|
+
'--subtask[Add subtask (repeatable)]:subtask:' \\
|
|
96
|
+
'--json[Output as JSON]'
|
|
97
|
+
;;
|
|
98
|
+
done)
|
|
99
|
+
_arguments \\
|
|
100
|
+
'1:task id:_taskify_cached_task_ids' \\
|
|
101
|
+
'--board[Board]:board:_taskify_boards' \\
|
|
102
|
+
'--json[Output as JSON]'
|
|
103
|
+
;;
|
|
104
|
+
reopen)
|
|
105
|
+
_arguments \\
|
|
106
|
+
'1:task id:_taskify_cached_task_ids' \\
|
|
107
|
+
'--board[Board]:board:_taskify_boards' \\
|
|
108
|
+
'--json[Output as JSON]'
|
|
109
|
+
;;
|
|
110
|
+
update)
|
|
111
|
+
_arguments \\
|
|
112
|
+
'1:task id:_taskify_cached_task_ids' \\
|
|
113
|
+
'--board[Board]:board:_taskify_boards' \\
|
|
114
|
+
'--title[New title]:title:' \\
|
|
115
|
+
'--due[New due date]:date:' \\
|
|
116
|
+
'--priority[New priority]:priority:(1 2 3)' \\
|
|
117
|
+
'--note[New note]:note:' \\
|
|
118
|
+
'--json[Output as JSON]'
|
|
119
|
+
;;
|
|
120
|
+
delete)
|
|
121
|
+
_arguments \\
|
|
122
|
+
'1:task id:_taskify_cached_task_ids' \\
|
|
123
|
+
'--board[Board]:board:_taskify_boards' \\
|
|
124
|
+
'--force[Skip confirmation]' \\
|
|
125
|
+
'--json[Output deleted task as JSON]'
|
|
126
|
+
;;
|
|
127
|
+
subtask)
|
|
128
|
+
_arguments \\
|
|
129
|
+
'1:task id:_taskify_cached_task_ids' \\
|
|
130
|
+
'2:subtask ref (index or title):' \\
|
|
131
|
+
'--board[Board]:board:_taskify_boards' \\
|
|
132
|
+
'--done[Mark completed]' \\
|
|
133
|
+
'--reopen[Mark incomplete]' \\
|
|
134
|
+
'--json[Output as JSON]'
|
|
135
|
+
;;
|
|
136
|
+
remind)
|
|
137
|
+
_arguments \\
|
|
138
|
+
'1:task id:_taskify_cached_task_ids' \\
|
|
139
|
+
'*:preset:(0h 5m 15m 30m 1h 1d 1w)' \\
|
|
140
|
+
'--board[Board]:board:_taskify_boards'
|
|
141
|
+
;;
|
|
142
|
+
relay)
|
|
143
|
+
_taskify_relay
|
|
144
|
+
;;
|
|
145
|
+
cache)
|
|
146
|
+
_taskify_cache
|
|
147
|
+
;;
|
|
148
|
+
trust)
|
|
149
|
+
_taskify_trust
|
|
150
|
+
;;
|
|
151
|
+
config)
|
|
152
|
+
_taskify_config
|
|
153
|
+
;;
|
|
154
|
+
completions)
|
|
155
|
+
_arguments \\
|
|
156
|
+
'--shell[Shell type]:shell:(zsh bash fish)'
|
|
157
|
+
;;
|
|
158
|
+
esac
|
|
159
|
+
;;
|
|
160
|
+
esac
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
_taskify_board() {
|
|
164
|
+
local state
|
|
165
|
+
_arguments -C \\
|
|
166
|
+
'1: :->subcommand' \\
|
|
167
|
+
'*:: :->args'
|
|
168
|
+
case $state in
|
|
169
|
+
subcommand)
|
|
170
|
+
local subcommands
|
|
171
|
+
subcommands=(
|
|
172
|
+
'list:List configured boards'
|
|
173
|
+
'join:Join a board by UUID'
|
|
174
|
+
'leave:Remove a board from config'
|
|
175
|
+
'sync:Sync board metadata from Nostr'
|
|
176
|
+
'columns:Show cached columns for all boards'
|
|
177
|
+
)
|
|
178
|
+
_describe 'board subcommand' subcommands
|
|
179
|
+
;;
|
|
180
|
+
args)
|
|
181
|
+
case $words[1] in
|
|
182
|
+
join)
|
|
183
|
+
_arguments \\
|
|
184
|
+
'1:board UUID:' \\
|
|
185
|
+
'--name[Board name]:name:' \\
|
|
186
|
+
'--relay[Relay URL]:url:'
|
|
187
|
+
;;
|
|
188
|
+
leave)
|
|
189
|
+
_arguments '1:board id:_taskify_boards'
|
|
190
|
+
;;
|
|
191
|
+
sync)
|
|
192
|
+
_arguments '1:board id or name:_taskify_boards'
|
|
193
|
+
;;
|
|
194
|
+
esac
|
|
195
|
+
;;
|
|
196
|
+
esac
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
_taskify_relay() {
|
|
200
|
+
local state
|
|
201
|
+
_arguments -C \\
|
|
202
|
+
'1: :->subcommand' \\
|
|
203
|
+
'*:: :->args'
|
|
204
|
+
case $state in
|
|
205
|
+
subcommand)
|
|
206
|
+
local subcommands
|
|
207
|
+
subcommands=(
|
|
208
|
+
'status:Show NDK pool relay connection status'
|
|
209
|
+
'list:Show configured relays with live check'
|
|
210
|
+
'add:Add a relay URL to config'
|
|
211
|
+
'remove:Remove a relay URL from config'
|
|
212
|
+
)
|
|
213
|
+
_describe 'relay subcommand' subcommands
|
|
214
|
+
;;
|
|
215
|
+
args)
|
|
216
|
+
case $words[1] in
|
|
217
|
+
add|remove)
|
|
218
|
+
_arguments '1:relay url:'
|
|
219
|
+
;;
|
|
220
|
+
esac
|
|
221
|
+
;;
|
|
222
|
+
esac
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
_taskify_cache() {
|
|
226
|
+
local state
|
|
227
|
+
_arguments -C \\
|
|
228
|
+
'1: :->subcommand' \\
|
|
229
|
+
'*:: :->args'
|
|
230
|
+
case $state in
|
|
231
|
+
subcommand)
|
|
232
|
+
local subcommands
|
|
233
|
+
subcommands=(
|
|
234
|
+
'clear:Delete the task cache file'
|
|
235
|
+
'status:Show per-board cache age and task count'
|
|
236
|
+
)
|
|
237
|
+
_describe 'cache subcommand' subcommands
|
|
238
|
+
;;
|
|
239
|
+
esac
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
_taskify_trust() {
|
|
243
|
+
local state
|
|
244
|
+
_arguments -C \\
|
|
245
|
+
'1: :->subcommand' \\
|
|
246
|
+
'*:: :->args'
|
|
247
|
+
case $state in
|
|
248
|
+
subcommand)
|
|
249
|
+
local subcommands
|
|
250
|
+
subcommands=('add:Add trusted npub' 'remove:Remove trusted npub' 'list:List trusted npubs')
|
|
251
|
+
_describe 'trust subcommand' subcommands
|
|
252
|
+
;;
|
|
253
|
+
esac
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
_taskify_config() {
|
|
257
|
+
local state
|
|
258
|
+
_arguments -C \\
|
|
259
|
+
'1: :->subcommand' \\
|
|
260
|
+
'*:: :->args'
|
|
261
|
+
case $state in
|
|
262
|
+
subcommand)
|
|
263
|
+
local subcommands
|
|
264
|
+
subcommands=('set:Set config values' 'show:Show current config')
|
|
265
|
+
_describe 'config subcommand' subcommands
|
|
266
|
+
;;
|
|
267
|
+
esac
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
_taskify_boards() {
|
|
271
|
+
${boardComplete}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
# Complete open task IDs from local cache (reads ~/.config/taskify/cache.json at completion time)
|
|
275
|
+
_taskify_cached_task_ids() {
|
|
276
|
+
local cache_file="\${HOME}/.config/taskify/cache.json"
|
|
277
|
+
[[ -f "\${cache_file}" ]] || return
|
|
278
|
+
local -a tasks
|
|
279
|
+
local raw
|
|
280
|
+
raw=\$(node -e "
|
|
281
|
+
try {
|
|
282
|
+
const fs=require('fs');
|
|
283
|
+
const c=JSON.parse(fs.readFileSync(process.env.HOME+'/.config/taskify/cache.json','utf8'));
|
|
284
|
+
const now=Date.now();
|
|
285
|
+
Object.values(c.boards||{}).forEach(b=>{
|
|
286
|
+
if(now-b.fetchedAt<300000){
|
|
287
|
+
(b.tasks||[]).forEach(t=>{
|
|
288
|
+
if(t.status==='open'){
|
|
289
|
+
const title=(t.title||'').replace(/[:\\n]/g,' ').slice(0,60);
|
|
290
|
+
process.stdout.write(t.id.slice(0,8)+':'+title+'\\n');
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}catch(e){}" 2>/dev/null)
|
|
296
|
+
[[ -n "\${raw}" ]] || return
|
|
297
|
+
tasks=(\${(f)raw})
|
|
298
|
+
_describe 'task id' tasks
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
_taskify
|
|
302
|
+
`;
|
|
303
|
+
}
|
|
304
|
+
export function bashCompletion() {
|
|
305
|
+
const boards = readBoardNames();
|
|
306
|
+
const boardList = boards.map((n) => `"${n.replace(/"/g, '\\"')}"`).join(" ");
|
|
307
|
+
return `# taskify bash completion
|
|
308
|
+
# Install: taskify completions --shell bash > ~/.bash_completion.d/taskify
|
|
309
|
+
# source ~/.bash_completion.d/taskify
|
|
310
|
+
|
|
311
|
+
_taskify_boards() {
|
|
312
|
+
local boards=(${boardList})
|
|
313
|
+
COMPREPLY=(\$(compgen -W "\${boards[*]}" -- "\${cur}"))
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
_taskify_cached_task_ids() {
|
|
317
|
+
local cache_file="\${HOME}/.config/taskify/cache.json"
|
|
318
|
+
[[ -f "\${cache_file}" ]] || return
|
|
319
|
+
local raw
|
|
320
|
+
raw=\$(node -e "
|
|
321
|
+
try {
|
|
322
|
+
const fs=require('fs');
|
|
323
|
+
const c=JSON.parse(fs.readFileSync(process.env.HOME+'/.config/taskify/cache.json','utf8'));
|
|
324
|
+
const now=Date.now();
|
|
325
|
+
Object.values(c.boards||{}).forEach(b=>{
|
|
326
|
+
if(now-b.fetchedAt<300000){
|
|
327
|
+
(b.tasks||[]).forEach(t=>{
|
|
328
|
+
if(t.status==='open') process.stdout.write(t.id.slice(0,8)+'\\n');
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}catch(e){}" 2>/dev/null)
|
|
333
|
+
COMPREPLY=(\$(compgen -W "\${raw}" -- "\${cur}"))
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
_taskify() {
|
|
337
|
+
local cur prev words cword
|
|
338
|
+
_init_completion 2>/dev/null || {
|
|
339
|
+
COMPREPLY=()
|
|
340
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
341
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
342
|
+
words=("\${COMP_WORDS[@]}")
|
|
343
|
+
cword=\$COMP_CWORD
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
local commands="board boards list show search add done reopen update delete subtask remind relay cache trust config completions"
|
|
347
|
+
local board_subcmds="list join leave sync columns"
|
|
348
|
+
local relay_subcmds="status list add remove"
|
|
349
|
+
local cache_subcmds="clear status"
|
|
350
|
+
local trust_subcmds="add remove list"
|
|
351
|
+
|
|
352
|
+
# If completing the first argument
|
|
353
|
+
if [[ \$cword -eq 1 ]]; then
|
|
354
|
+
COMPREPLY=(\$(compgen -W "\$commands" -- "\$cur"))
|
|
355
|
+
return
|
|
356
|
+
fi
|
|
357
|
+
|
|
358
|
+
local cmd="\${words[1]}"
|
|
359
|
+
|
|
360
|
+
case "\$cmd" in
|
|
361
|
+
board)
|
|
362
|
+
if [[ \$cword -eq 2 ]]; then
|
|
363
|
+
COMPREPLY=(\$(compgen -W "\$board_subcmds" -- "\$cur"))
|
|
364
|
+
return
|
|
365
|
+
fi
|
|
366
|
+
local subcmd="\${words[2]}"
|
|
367
|
+
case "\$subcmd" in
|
|
368
|
+
join)
|
|
369
|
+
case "\$prev" in
|
|
370
|
+
--name|--relay) return ;;
|
|
371
|
+
esac
|
|
372
|
+
COMPREPLY=(\$(compgen -W "--name --relay" -- "\$cur"))
|
|
373
|
+
;;
|
|
374
|
+
leave|sync)
|
|
375
|
+
_taskify_boards
|
|
376
|
+
;;
|
|
377
|
+
esac
|
|
378
|
+
;;
|
|
379
|
+
list)
|
|
380
|
+
case "\$prev" in
|
|
381
|
+
--board) _taskify_boards ; return ;;
|
|
382
|
+
--status) COMPREPLY=(\$(compgen -W "open done any" -- "\$cur")) ; return ;;
|
|
383
|
+
--column) return ;;
|
|
384
|
+
esac
|
|
385
|
+
COMPREPLY=(\$(compgen -W "--board --status --column --refresh --json" -- "\$cur"))
|
|
386
|
+
;;
|
|
387
|
+
show)
|
|
388
|
+
if [[ \$cword -eq 2 ]]; then _taskify_cached_task_ids ; return ; fi
|
|
389
|
+
case "\$prev" in
|
|
390
|
+
--board) _taskify_boards ; return ;;
|
|
391
|
+
esac
|
|
392
|
+
COMPREPLY=(\$(compgen -W "--board --json" -- "\$cur"))
|
|
393
|
+
;;
|
|
394
|
+
search)
|
|
395
|
+
case "\$prev" in
|
|
396
|
+
--board) _taskify_boards ; return ;;
|
|
397
|
+
esac
|
|
398
|
+
COMPREPLY=(\$(compgen -W "--board --json" -- "\$cur"))
|
|
399
|
+
;;
|
|
400
|
+
add)
|
|
401
|
+
case "\$prev" in
|
|
402
|
+
--board) _taskify_boards ; return ;;
|
|
403
|
+
--priority) COMPREPLY=(\$(compgen -W "1 2 3" -- "\$cur")) ; return ;;
|
|
404
|
+
--due|--note|--subtask) return ;;
|
|
405
|
+
esac
|
|
406
|
+
COMPREPLY=(\$(compgen -W "--board --due --priority --note --subtask --json" -- "\$cur"))
|
|
407
|
+
;;
|
|
408
|
+
done|reopen)
|
|
409
|
+
if [[ \$cword -eq 2 ]]; then _taskify_cached_task_ids ; return ; fi
|
|
410
|
+
case "\$prev" in
|
|
411
|
+
--board) _taskify_boards ; return ;;
|
|
412
|
+
esac
|
|
413
|
+
COMPREPLY=(\$(compgen -W "--board --json" -- "\$cur"))
|
|
414
|
+
;;
|
|
415
|
+
update)
|
|
416
|
+
if [[ \$cword -eq 2 ]]; then _taskify_cached_task_ids ; return ; fi
|
|
417
|
+
case "\$prev" in
|
|
418
|
+
--board) _taskify_boards ; return ;;
|
|
419
|
+
--priority) COMPREPLY=(\$(compgen -W "1 2 3" -- "\$cur")) ; return ;;
|
|
420
|
+
--title|--due|--note) return ;;
|
|
421
|
+
esac
|
|
422
|
+
COMPREPLY=(\$(compgen -W "--board --title --due --priority --note --json" -- "\$cur"))
|
|
423
|
+
;;
|
|
424
|
+
delete)
|
|
425
|
+
if [[ \$cword -eq 2 ]]; then _taskify_cached_task_ids ; return ; fi
|
|
426
|
+
case "\$prev" in
|
|
427
|
+
--board) _taskify_boards ; return ;;
|
|
428
|
+
esac
|
|
429
|
+
COMPREPLY=(\$(compgen -W "--board --force --json" -- "\$cur"))
|
|
430
|
+
;;
|
|
431
|
+
subtask)
|
|
432
|
+
if [[ \$cword -eq 2 ]]; then _taskify_cached_task_ids ; return ; fi
|
|
433
|
+
case "\$prev" in
|
|
434
|
+
--board) _taskify_boards ; return ;;
|
|
435
|
+
esac
|
|
436
|
+
COMPREPLY=(\$(compgen -W "--board --done --reopen --json" -- "\$cur"))
|
|
437
|
+
;;
|
|
438
|
+
remind)
|
|
439
|
+
if [[ \$cword -eq 2 ]]; then _taskify_cached_task_ids ; return ; fi
|
|
440
|
+
case "\$prev" in
|
|
441
|
+
--board) _taskify_boards ; return ;;
|
|
442
|
+
remind) return ;; # task id
|
|
443
|
+
esac
|
|
444
|
+
if [[ \$cword -gt 2 ]]; then
|
|
445
|
+
COMPREPLY=(\$(compgen -W "0h 5m 15m 30m 1h 1d 1w --board" -- "\$cur"))
|
|
446
|
+
fi
|
|
447
|
+
;;
|
|
448
|
+
relay)
|
|
449
|
+
if [[ \$cword -eq 2 ]]; then
|
|
450
|
+
COMPREPLY=(\$(compgen -W "\$relay_subcmds" -- "\$cur"))
|
|
451
|
+
fi
|
|
452
|
+
;;
|
|
453
|
+
cache)
|
|
454
|
+
if [[ \$cword -eq 2 ]]; then
|
|
455
|
+
COMPREPLY=(\$(compgen -W "\$cache_subcmds" -- "\$cur"))
|
|
456
|
+
fi
|
|
457
|
+
;;
|
|
458
|
+
trust)
|
|
459
|
+
if [[ \$cword -eq 2 ]]; then
|
|
460
|
+
COMPREPLY=(\$(compgen -W "\$trust_subcmds" -- "\$cur"))
|
|
461
|
+
fi
|
|
462
|
+
;;
|
|
463
|
+
completions)
|
|
464
|
+
case "\$prev" in
|
|
465
|
+
--shell) COMPREPLY=(\$(compgen -W "zsh bash fish" -- "\$cur")) ; return ;;
|
|
466
|
+
esac
|
|
467
|
+
COMPREPLY=(\$(compgen -W "--shell" -- "\$cur"))
|
|
468
|
+
;;
|
|
469
|
+
esac
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
complete -F _taskify taskify
|
|
473
|
+
`;
|
|
474
|
+
}
|
|
475
|
+
export function fishCompletion() {
|
|
476
|
+
const boards = readBoardNames();
|
|
477
|
+
const boardCompletions = boards
|
|
478
|
+
.map((n) => `complete -c taskify -n '__taskify_using_board_opt' -a '${n.replace(/'/g, "\\'")}' -d 'Board'`)
|
|
479
|
+
.join("\n");
|
|
480
|
+
return `# taskify fish completion
|
|
481
|
+
# Install: taskify completions --shell fish > ~/.config/fish/completions/taskify.fish
|
|
482
|
+
|
|
483
|
+
function __taskify_no_subcommand
|
|
484
|
+
set -l cmd (commandline -poc)
|
|
485
|
+
set -e cmd[1]
|
|
486
|
+
for c in $cmd
|
|
487
|
+
if string match -qr '^[^-]' -- $c
|
|
488
|
+
return 1
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
return 0
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
function __taskify_subcommand_is
|
|
495
|
+
set -l cmd (commandline -poc)
|
|
496
|
+
set -e cmd[1]
|
|
497
|
+
for c in $cmd
|
|
498
|
+
if string match -qr '^[^-]' -- $c
|
|
499
|
+
test "$c" = "$argv[1]"
|
|
500
|
+
return
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
return 1
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
function __taskify_board_subcommand_is
|
|
507
|
+
set -l cmd (commandline -poc)
|
|
508
|
+
set -e cmd[1]
|
|
509
|
+
set -l saw_board 0
|
|
510
|
+
for c in $cmd
|
|
511
|
+
if string match -qr '^[^-]' -- $c
|
|
512
|
+
if test $saw_board -eq 0
|
|
513
|
+
if test "$c" = "board"
|
|
514
|
+
set saw_board 1
|
|
515
|
+
else
|
|
516
|
+
return 1
|
|
517
|
+
end
|
|
518
|
+
else
|
|
519
|
+
test "$c" = "$argv[1]"
|
|
520
|
+
return
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
return 1
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
function __taskify_using_board_opt
|
|
528
|
+
set -l cmd (commandline -poc)
|
|
529
|
+
string match -q -- '--board' $cmd[-1]
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
# Top-level subcommands
|
|
533
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a board -d 'Manage boards'
|
|
534
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a boards -d 'List configured boards'
|
|
535
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a list -d 'List tasks'
|
|
536
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a show -d 'Show full task details'
|
|
537
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a search -d 'Search tasks'
|
|
538
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a add -d 'Create a new task'
|
|
539
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a done -d 'Mark a task as done'
|
|
540
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a reopen -d 'Reopen a completed task'
|
|
541
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a update -d 'Update task fields'
|
|
542
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a delete -d 'Delete a task'
|
|
543
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a subtask -d 'Toggle a subtask'
|
|
544
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a remind -d 'Set reminders on a task'
|
|
545
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a relay -d 'Manage relay connections'
|
|
546
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a cache -d 'Manage task cache'
|
|
547
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a trust -d 'Manage trusted npubs'
|
|
548
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a config -d 'Manage CLI config'
|
|
549
|
+
complete -c taskify -f -n '__taskify_no_subcommand' -a completions -d 'Generate shell completions'
|
|
550
|
+
|
|
551
|
+
# board subcommands
|
|
552
|
+
complete -c taskify -f -n '__taskify_subcommand_is board' -a list -d 'List configured boards'
|
|
553
|
+
complete -c taskify -f -n '__taskify_subcommand_is board' -a join -d 'Join a board by UUID'
|
|
554
|
+
complete -c taskify -f -n '__taskify_subcommand_is board' -a leave -d 'Remove a board from config'
|
|
555
|
+
complete -c taskify -f -n '__taskify_subcommand_is board' -a sync -d 'Sync board metadata from Nostr'
|
|
556
|
+
complete -c taskify -f -n '__taskify_subcommand_is board' -a columns -d 'Show cached columns'
|
|
557
|
+
|
|
558
|
+
# relay subcommands
|
|
559
|
+
complete -c taskify -f -n '__taskify_subcommand_is relay' -a status -d 'Show NDK pool relay status'
|
|
560
|
+
complete -c taskify -f -n '__taskify_subcommand_is relay' -a list -d 'Show configured relays'
|
|
561
|
+
complete -c taskify -f -n '__taskify_subcommand_is relay' -a add -d 'Add a relay URL'
|
|
562
|
+
complete -c taskify -f -n '__taskify_subcommand_is relay' -a remove -d 'Remove a relay URL'
|
|
563
|
+
|
|
564
|
+
# cache subcommands
|
|
565
|
+
complete -c taskify -f -n '__taskify_subcommand_is cache' -a clear -d 'Delete the task cache'
|
|
566
|
+
complete -c taskify -f -n '__taskify_subcommand_is cache' -a status -d 'Show cache status'
|
|
567
|
+
|
|
568
|
+
# board join options
|
|
569
|
+
complete -c taskify -f -n '__taskify_board_subcommand_is join' -l name -d 'Board name'
|
|
570
|
+
complete -c taskify -f -n '__taskify_board_subcommand_is join' -l relay -d 'Relay URL'
|
|
571
|
+
|
|
572
|
+
# board sync / leave — complete board names
|
|
573
|
+
${boardCompletions || "# (no boards configured)"}
|
|
574
|
+
|
|
575
|
+
# list options
|
|
576
|
+
complete -c taskify -n '__taskify_subcommand_is list' -l board -d 'Filter by board'
|
|
577
|
+
complete -c taskify -n '__taskify_subcommand_is list' -l status -d 'Filter status' -a 'open done any'
|
|
578
|
+
complete -c taskify -n '__taskify_subcommand_is list' -l column -d 'Filter by column'
|
|
579
|
+
complete -c taskify -n '__taskify_subcommand_is list' -l refresh -d 'Bypass cache'
|
|
580
|
+
complete -c taskify -n '__taskify_subcommand_is list' -l json -d 'Output as JSON'
|
|
581
|
+
|
|
582
|
+
# show options
|
|
583
|
+
complete -c taskify -n '__taskify_subcommand_is show' -l board -d 'Board to search in'
|
|
584
|
+
complete -c taskify -n '__taskify_subcommand_is show' -l json -d 'Output as JSON'
|
|
585
|
+
|
|
586
|
+
# search options
|
|
587
|
+
complete -c taskify -n '__taskify_subcommand_is search' -l board -d 'Limit to board'
|
|
588
|
+
complete -c taskify -n '__taskify_subcommand_is search' -l json -d 'Output as JSON'
|
|
589
|
+
|
|
590
|
+
# add options
|
|
591
|
+
complete -c taskify -n '__taskify_subcommand_is add' -l board -d 'Board to add to'
|
|
592
|
+
complete -c taskify -n '__taskify_subcommand_is add' -l due -d 'Due date (YYYY-MM-DD)'
|
|
593
|
+
complete -c taskify -n '__taskify_subcommand_is add' -l priority -d 'Priority' -a '1 2 3'
|
|
594
|
+
complete -c taskify -n '__taskify_subcommand_is add' -l note -d 'Note text'
|
|
595
|
+
complete -c taskify -n '__taskify_subcommand_is add' -l subtask -d 'Add subtask (repeatable)'
|
|
596
|
+
complete -c taskify -n '__taskify_subcommand_is add' -l json -d 'Output as JSON'
|
|
597
|
+
|
|
598
|
+
# done options
|
|
599
|
+
complete -c taskify -n '__taskify_subcommand_is done' -l board -d 'Board'
|
|
600
|
+
complete -c taskify -n '__taskify_subcommand_is done' -l json -d 'Output as JSON'
|
|
601
|
+
|
|
602
|
+
# reopen options
|
|
603
|
+
complete -c taskify -n '__taskify_subcommand_is reopen' -l board -d 'Board'
|
|
604
|
+
complete -c taskify -n '__taskify_subcommand_is reopen' -l json -d 'Output as JSON'
|
|
605
|
+
|
|
606
|
+
# update options
|
|
607
|
+
complete -c taskify -n '__taskify_subcommand_is update' -l board -d 'Board'
|
|
608
|
+
complete -c taskify -n '__taskify_subcommand_is update' -l title -d 'New title'
|
|
609
|
+
complete -c taskify -n '__taskify_subcommand_is update' -l due -d 'New due date'
|
|
610
|
+
complete -c taskify -n '__taskify_subcommand_is update' -l priority -d 'New priority' -a '1 2 3'
|
|
611
|
+
complete -c taskify -n '__taskify_subcommand_is update' -l note -d 'New note'
|
|
612
|
+
complete -c taskify -n '__taskify_subcommand_is update' -l json -d 'Output as JSON'
|
|
613
|
+
|
|
614
|
+
# delete options
|
|
615
|
+
complete -c taskify -n '__taskify_subcommand_is delete' -l board -d 'Board'
|
|
616
|
+
complete -c taskify -n '__taskify_subcommand_is delete' -l force -d 'Skip confirmation'
|
|
617
|
+
complete -c taskify -n '__taskify_subcommand_is delete' -l json -d 'Output deleted task as JSON'
|
|
618
|
+
|
|
619
|
+
# subtask options
|
|
620
|
+
complete -c taskify -n '__taskify_subcommand_is subtask' -l board -d 'Board'
|
|
621
|
+
complete -c taskify -n '__taskify_subcommand_is subtask' -l done -d 'Mark completed'
|
|
622
|
+
complete -c taskify -n '__taskify_subcommand_is subtask' -l reopen -d 'Mark incomplete'
|
|
623
|
+
complete -c taskify -n '__taskify_subcommand_is subtask' -l json -d 'Output as JSON'
|
|
624
|
+
|
|
625
|
+
# remind options
|
|
626
|
+
complete -c taskify -n '__taskify_subcommand_is remind' -l board -d 'Board'
|
|
627
|
+
complete -c taskify -f -n '__taskify_subcommand_is remind' -a '0h 5m 15m 30m 1h 1d 1w' -d 'Reminder preset'
|
|
628
|
+
|
|
629
|
+
# trust subcommands
|
|
630
|
+
complete -c taskify -f -n '__taskify_subcommand_is trust' -a add -d 'Add trusted npub'
|
|
631
|
+
complete -c taskify -f -n '__taskify_subcommand_is trust' -a remove -d 'Remove trusted npub'
|
|
632
|
+
complete -c taskify -f -n '__taskify_subcommand_is trust' -a list -d 'List trusted npubs'
|
|
633
|
+
|
|
634
|
+
# completions options
|
|
635
|
+
complete -c taskify -n '__taskify_subcommand_is completions' -l shell -d 'Shell type' -a 'zsh bash fish'
|
|
636
|
+
`;
|
|
637
|
+
}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readFile, writeFile } from "fs/promises";
|
|
2
|
+
import { mkdirSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
export const CONFIG_DIR = join(homedir(), ".taskify-cli");
|
|
6
|
+
export const CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
7
|
+
const DEFAULT_CONFIG = {
|
|
8
|
+
relays: [
|
|
9
|
+
"wss://relay.damus.io",
|
|
10
|
+
"wss://nos.lol",
|
|
11
|
+
"wss://relay.snort.social",
|
|
12
|
+
"wss://relay.primal.net",
|
|
13
|
+
],
|
|
14
|
+
defaultBoard: "Personal",
|
|
15
|
+
trustedNpubs: [],
|
|
16
|
+
securityMode: "moderate",
|
|
17
|
+
securityEnabled: true,
|
|
18
|
+
boards: [],
|
|
19
|
+
taskReminders: {},
|
|
20
|
+
};
|
|
21
|
+
export async function loadConfig() {
|
|
22
|
+
let cfg;
|
|
23
|
+
try {
|
|
24
|
+
const raw = await readFile(CONFIG_PATH, "utf-8");
|
|
25
|
+
cfg = { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
cfg = { ...DEFAULT_CONFIG };
|
|
29
|
+
}
|
|
30
|
+
if (process.env.TASKIFY_NSEC) {
|
|
31
|
+
cfg.nsec = process.env.TASKIFY_NSEC;
|
|
32
|
+
process.stderr.write("\x1b[2m(using TASKIFY_NSEC from env)\x1b[0m\n");
|
|
33
|
+
}
|
|
34
|
+
return cfg;
|
|
35
|
+
}
|
|
36
|
+
export async function saveConfig(cfg) {
|
|
37
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
38
|
+
await writeFile(CONFIG_PATH, JSON.stringify(cfg, null, 2), "utf-8");
|
|
39
|
+
}
|