aboutsummaryrefslogtreecommitdiff
path: root/man/krino.1
blob: e7d93eb89bb4e2811afe1c48aecb9a9c36f9abd4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
.\" SPDX-License-Identifier: GPL-3.0-or-later
.Dd September 14, 2026
.Dt KRINO 1
.Os
.Sh NAME
.Nm krino
.Nd sort files in a directory by rules
.Sh SYNOPSIS
.Nm
.Op Fl y | Fl n
.Op Fl v
.Op Fl -json
.Op Fl c Ar file
.Op Fl P
.Op Fl -no-color
.Op Fl -min-age Ar duration
.Op Ar name ...
.Pp
.Nm
.Cm init
.Pp
.Nm
.Cm new
.Ar name path
.Pp
.Nm
.Cm check
.Op Ar name ...
.Pp
.Nm
.Cm explain
.Ar file
.Pp
.Nm
.Cm log
.Op Fl n Ar count
.Pp
.Nm
.Cm undo
.Op Ar run
.Sh DESCRIPTION
.Nm
sorts the files in one or more configured directories according to rules
kept in
.Xr krino.conf 5 .
For each directory in turn it scans the files, evaluates every rule against
every file, and builds a plan: the chain of actions
.Pq Ic copy , Ic move , Ic rename , Ic delete
that the file's matching rules add up to.
.Pp
Every rule that matches a file adds its actions to that file's chain, in
the order the rules are written;
.Sy (stop)
on a matching rule ends the chain for that file, so a later rule is never
even evaluated against it.
A rule with no actions besides
.Sy (stop)
is an exclusion.
.Pp
Every test sees the file as it was when the directory was scanned: name,
path, size, modification time and content.
Actions already added to a file's chain by an earlier rule never change
what a later rule's tests see, so the whole plan for a directory can be
computed, shown, and approved before anything is touched.
.Pp
With no
.Fl y
or
.Fl n ,
.Nm
prints the plan and asks how to proceed
.Pq Sx REVIEW .
.Fl y
applies the plan without asking;
.Fl n
prints it and changes nothing.
If standard input is not a terminal and neither is given,
.Nm
refuses rather than guess.
.Sh OPTIONS
.Bl -tag -width Ds
.It Fl y
Apply the plan without asking.
Cannot be combined with
.Fl n .
.It Fl n
Dry run: print the plan and exit without changing anything.
.It Fl v
Also list files that were skipped as unmatched, ignored or busy, and show
the full reason a test matched or not.
.It Fl -json
With
.Fl n ,
print the plan as JSON instead of the text blocks.
Refused unless
.Fl n
is also given.
The document's own
.Ic note
field says its shape is unstable before krino 1.0; a script that reads it
should expect it to change before then.
.It Fl c Ar file
Use
.Ar file
in place of
.Pa $XDG_CONFIG_HOME/krino/krino.conf .
.It Fl -no-color
Never colour the output, as when
.Ev NO_COLOR
is set.
Without it,
.Nm
colours its output only when writing to a terminal, using the terminal's
own 16-colour palette: directory headers bold;
.Ic copy ,
.Ic move
and
.Ic rename
green;
.Ic trash
yellow;
.Sy DELETE permanently
and a refused undo step bold red; skipped steps and match reasons faint;
rule names blue; warnings yellow; the applied count green and a failed count
red; prompt keys bold; the choice echoed in review red; and
.Ic krino log Ns 's
.Dq (undone)
faint.
.It Fl P , Fl -no-pager
Print the plan straight out, never through
.Ev PAGER .
Without it, a plan taller than the terminal is shown through the pager.
.It Fl -min-age Ar duration
For this run only, skip files modified less than
.Ar duration
ago in every directory, in place of each directory's
.Ic min-age
.Pq Xr krino.conf 5 .
.Ar duration
is
.Sy 0 ,
or an integer with one of
.Ql s m h d w ;
.Fl -min-age Cm 0
considers even a file written a moment ago.
Also honoured by
.Ic explain .
.It Fl h , Fl -help
Print usage and exit.
.It Fl -version
Print
.Dq krino Ar version
and exit.
.El
.Sh SUBCOMMANDS
.Bl -tag -width Ds
.It Ic init
Create the config directory with a commented
.Pa krino.conf
and
.Pa template.conf .
Refuses if
.Pa krino.conf
already exists, and leaves an existing
.Pa template.conf
alone.
.It Ic new Ar name path
Copy
.Pa template.conf
to
.Pa dirs/ Ns Ar name Ns Pa .conf ,
fill in
.Ar path ,
and append
.Ar name
to
.Ic include
in
.Pa krino.conf ,
keeping its comments.
.It Ic check Op Ar name ...
Validate the configuration, list each included directory's exclusions and rules, and list
which content-extraction tools
.Pq Xr krino.conf 5 , Sx CONTENT EXTRACTION
are available.
With no
.Ar name ,
checks every included directory.
.It Ic explain Ar file
Evaluate every exclusion and rule of
.Ar file Ns 's
directory against it and show each test's result, so a rule that should
match but does not
.Pq or the reverse
can be diagnosed test by test.
See
.Sx KNOWN LIMITATIONS .
.It Ic log Op Fl n Ar count
List the most recent runs, newest first
.Pq Ar count No defaults to 10 :
the run id, its start time, the directories it touched, and what it did.
A run that a later
.Ic undo
has reversed at least one file of is marked
.Pq undone .
.It Ic undo Op Ar run
Reverse
.Ar run .
With no
.Ar run ,
reverse the most recent run; if that run is itself an undo, it is refused.
An older run is undone by naming it.
See
.Sx UNDO .
.El
.Sh REVIEW
With neither
.Fl y
nor
.Fl n ,
after showing one directory's plan
.Nm
asks:
.Bd -literal -offset indent
[a] apply all  [c] choose per file  [s] skip this directory  [q] quit
.Ed
.Pp
.Ic a
applies every step of every chain shown.
.Ic s
applies nothing in this directory and moves on to the next one.
.Ic q
stops
.Nm
entirely; directories already applied earlier in this run stay applied and
can be reversed with
.Ic undo .
.Pp
.Ic c
asks about each file in turn, showing the same block the plan shows for it:
each step, then the rule and the reason it matched:
.Bd -literal -offset indent
[2/41] fv_123.pdf
       copy    \(-> ~/backup/invoices/2026/
       rule    backup
       because content "invoice"
  [y] yes  [n] no  [a] yes to this and all remaining  [t] trash  [d] delete permanently  [w] write, apply chosen so far  [q] quit, apply nothing
.Ed
.Pp
Approval is per file: a file's whole chain runs, or none of it.
.Ic t
and
.Ic d
set aside what the rules planned for the file and approve one step on the
file itself instead: to the Trash, or deleted permanently, logged under the
rule name
.Sy (review) .
.Ic d
first asks
.Dq delete Ar name No permanently? [y/N] ;
any key but
.Ic y
deletes nothing and asks about the file again.
A permanent delete cannot be undone.
Each choice is confirmed on its own line under the file, in red:
.Dq \(-> yes ,
.Dq \(-> no ,
.Dq \(-> trash ,
and so on.
Enter is ignored.
.Pp
.Ic w
applies what was decided so far and stops
.Nm ,
without going on to any later directory, so a long review can be done over
several sessions.
Files answered
.Ic n
are logged as declined; files never reached are not logged, are counted as
.Dq not reviewed ,
and are asked about again next time, as are declined files.
.Ic q
here aborts the review for this directory entirely, discarding even a file
already marked
.Ic yes ,
and folds into the top-level
.Ic q
above.
.Sh UNDO
.Ic krino undo
reverses a run's steps, last step first within each file, after building
and showing a plan of its own
.Pq shown and approved the same way as a sort plan; Fl y No and Fl n No apply .
One undo plan covers every directory the run touched, so its menu has no
per-directory skip;
.Ic s
and
.Ic q
both apply nothing:
.Bd -literal -offset indent
[a] apply all  [c] choose per file  [s] skip  [q] quit
.Ed
.Pp
Its per-file prompt is the one in
.Sx REVIEW
without
.Ic t
and
.Ic d .
.Pp
An undo run cannot itself be undone: naming it to
.Ic undo
is refused.
.Pp
A step's reversal is refused when the world has moved on since the step ran
.Pq its target is gone or has changed, or the original path is occupied again ;
a refused file has nothing of its chain reversed, so no file is left half
undone.
An exception is a created directory found non-empty at its own turn: that
alone does not refuse the rest of the file's reversal, since it means
another file still lives there, not that something unexpected changed
underfoot.
Every created directory still empty once every file in the run has had its
turn is then removed, deepest path first, so an undo does not leave the
empty directories it made behind.
.Pp
A permanent delete,
.Sy (delete permanent) ,
is never undoable; it is shown in the plan with that reason and nothing is
attempted for it.
.Pp
.Ic krino log
marks a run
.Pq undone
once its undo run has reversed at least one file's chain \(em not that
every file in it was restored: a run left partly reversed, because some
files were declined during the undo's own review, is still shown as
.Pq undone
in full.
.Sh ENVIRONMENT
.Bl -tag -width Ds
.It Ev XDG_CONFIG_HOME
Base of the configuration directory
.Pq Pa $XDG_CONFIG_HOME/krino ;
default
.Pa ~/.config .
.It Ev XDG_STATE_HOME
Base of the log and the per-directory lock files
.Pq Pa $XDG_STATE_HOME/krino ;
default
.Pa ~/.local/state .
.It Ev XDG_DATA_HOME
Base of the trash a
.Sy (delete)
step uses
.Pq Pa $XDG_DATA_HOME/Trash ;
default
.Pa ~/.local/share .
.It Ev XDG_CACHE_HOME
Base of the keyword cache
.Pq Pa $XDG_CACHE_HOME/krino ;
default
.Pa ~/.cache .
.It Ev PAGER
Used to show a plan taller than the terminal; default
.Dq less -FRX .
Never used for
.Fl -json
output.
.It Ev NO_COLOR
When set, disables colour, as
.Fl -no-color
does.
.El
.Sh FILES
.Bl -tag -width Ds
.It Pa $XDG_CONFIG_HOME/krino/krino.conf
The main configuration file: which directories run, defaults, the log
path.
.It Pa $XDG_CONFIG_HOME/krino/template.conf
Copied by
.Ic krino new
for each new directory.
.It Pa $XDG_CONFIG_HOME/krino/dirs/ Ns Ar name Ns Pa .conf
One file per configured directory.
.It Pa $XDG_STATE_HOME/krino/krino.log
The append-only log every run writes to.
.It Pa $XDG_STATE_HOME/krino/ Ns Ar name Ns Pa .lock
Held for the duration of a run against directory
.Ar name ,
so a second
.Nm
against the same directory waits, or fails immediately with
.Fl y .
.It Pa $XDG_DATA_HOME/Trash
The freedesktop.org trash a
.Sy (delete)
step moves files into.
.It Pa $XDG_CACHE_HOME/krino/ Ns Ar name Ns Pa .cache
Which content keywords each extracted file of directory
.Ar name
contains, so an unchanged file is not extracted again; see
.Xr krino.conf 5 , Sx CONTENT EXTRACTION .
Safe to delete at any time.
.El
.Sh EXIT STATUS
.Bl -tag -width Ds
.It 0
Success, including a run that found nothing to do, or one whose plan was
entirely declined at review.
.It 1
A step failed, a directory's lock was already held by another
.Nm ,
or a configured directory could not be read.
.It 2
A usage mistake or a configuration error.
Flags must come before any directory name on the command line: a flag
found after a directory name is a usage error rather than a guess.
.It 130
Interrupted
.Pq Ic Ctrl-C
or terminated; the current step, if any, is finished and logged first.
.El
.Sh KNOWN LIMITATIONS
.Ic krino explain
evaluates every test of every rule's condition against the file, without
the cost-ordered short-circuiting a real run uses within an
.Sy and/or .
It can therefore run a content-extraction tool, and report a
.Dq content unreadable
warning, for a test that a real run would never reach because an earlier,
cheaper test in the same condition already decided the rule did not match.
.Ic explain
is a full trace of every test, not a cost-faithful preview of what
.Fl n
would actually spend time on.
.Sh SEE ALSO
.Xr krino.conf 5
.Pp
.Pa docs/sexp-primer.md
in the source repository
.Pq installed at Pa $PREFIX/share/doc/krino/sexp-primer.md
is a short tutorial on the configuration syntax.