1 Commits
Author SHA1 Message Date
sneak c997a5c7c2 README.md rewritten sentence by sentence (closes #219)
check / check (push) Canceled after 0s
The old text served as the list of what a reader needs covered. The new
text leads with what quak is, what it is for and how to use it. Every
command, option, exit code and file layout follows in reference sections,
then the library reference, then design, entrypoints and development.
Every statement was checked against the code on next; where the old text
disagreed, the pull request lists it. No sentence runs past about 30
words, every table is now a list, and no issue links or project history
remain in text meant for users. Two code comments that named README
sections now name the new ones; a third no longer cites the README.

Model: fable-5-1
2026-10-26 14:54:59 +00:00
2 changed files with 27 additions and 27 deletions

No files matched your search

+26 -26
View File
@@ -158,11 +158,11 @@ output to `~/quak-backup.log`. Sunday's run adds `--verify`:
A run with `--verify` does all a plain run does. It also hashes each original A run with `--verify` does all a plain run does. It also hashes each original
already in the backup and compares the result with the content hash. The content already in the backup and compares the result with the content hash. The content
hash is the hash of the file's bytes that Ente recorded at upload. It fetches a hash is the hash of the file's bytes that Ente recorded at upload. The run
new copy of each original that does not match, and replaces the original once fetches a new copy of each original that does not match, and replaces the
the copy matches. Sunday's run is the `--verify` run, rather than a second job original once the copy matches. Sunday's run is the `--verify` run, rather than
that night, because two backups of one directory cannot run at once. The second a second job that night, because two backups of one directory cannot run at
one exits 2 without doing anything. once. The second one exits 2 without doing anything.
Cron runs the job with a short `PATH`, usually `/usr/bin:/bin`, so the crontab Cron runs the job with a short `PATH`, usually `/usr/bin:/bin`, so the crontab
names quak by its full path. quak finds the saved session through `HOME`, which names quak by its full path. quak finds the saved session through `HOME`, which
@@ -320,10 +320,10 @@ grid. It writes one file, also for a live photo. Without `--out`, the name is
#### `quak backup <dir> [--json] [--verify]` #### `quak backup <dir> [--json] [--verify]`
Backs up every file in the account to `<dir>`. The layout is described under Backs up every file in the account to `<dir>`. The layout is described under
"The backup directory". It downloads only the originals that are not yet in the "The backup directory". The command downloads only the originals that are not
backup, and it goes on past a file that fails. A file is downloaded once, yet in the backup, and it goes on past a file that fails. A file is downloaded
however many collections hold it. An original the cache already holds is copied once, however many collections hold it. An original the cache already holds is
from there instead. copied from there instead.
Progress goes to stderr: one line per original fetched, and a `FAILED` line for Progress goes to stderr: one line per original fetched, and a `FAILED` line for
each original or album that failed. The run ends with a summary of counts and, each original or album that failed. The run ends with a summary of counts and,
@@ -689,10 +689,10 @@ The JSON file beside an original holds:
Update times are in microseconds, as Ente records them. Update times are in microseconds, as Ente records them.
The file also holds the machine-learning data Ente computed for the file, as The JSON also holds the machine-learning data Ente computed for the photo, as
`mlData`. Ente's apps detect faces in each photo and compute a CLIP embedding `mlData`. Ente's apps detect faces in each photo and compute a CLIP embedding
for it, a list of 512 numbers that describes what the photo shows. `mlData` for it, a list of 512 numbers that describes what the photo shows. `mlData`
holds everything but that embedding. In its place the file holds `keywords`, holds everything but that embedding. In its place the JSON holds `keywords`,
derived from the embedding as described under "Keywords". A file with no derived from the embedding as described under "Keywords". A file with no
machine-learning data has neither field. A file whose data holds no usable machine-learning data has neither field. A file whose data holds no usable
embedding has no `keywords`. embedding has no `keywords`.
@@ -857,8 +857,8 @@ ends, whether it succeeded or failed.
The lock is a directory that The lock is a directory that
[proper-lockfile](https://github.com/moxystudio/node-proper-lockfile) creates. [proper-lockfile](https://github.com/moxystudio/node-proper-lockfile) creates.
While the backup runs, the backup updates the directory's modification time While the backup runs, it updates the modification time of `backup.lock` every 5
every 5 seconds. A second backup of the directory fails at once: it prints seconds. A second backup of `<dir>` fails at once: it prints
`quak: another backup of <dir> is running` and exits 2. A run that is killed, or `quak: another backup of <dir> is running` and exits 2. A run that is killed, or
cut off by a crash, can leave the lock behind. Once the lock has gone 10 seconds cut off by a crash, can leave the lock behind. Once the lock has gone 10 seconds
without an update, the next run takes it over, so nobody has to remove it by without an update, the next run takes it over, so nobody has to remove it by
@@ -1055,14 +1055,14 @@ still in flight.
`"refresh"`, `"fetchMLData"` for a machine-learning fetch, and `"refresh"`, `"fetchMLData"` for a machine-learning fetch, and
`"precacheThumbnails"` or `"precacheOriginals"` for the two background `"precacheThumbnails"` or `"precacheOriginals"` for the two background
downloads. Its `status` is `"started"` as the work starts and `"done"` as it downloads. Its `status` is `"started"` as the work starts and `"done"` as it
ends. A refresh or a machine-learning fetch that fails ends with `"failed"` and ends. A refresh or a machine-learning fetch that fails ends with `"failed"`
the error message instead. In between, a refresh sends `"progress"` after each instead, with the message in `error`. In between, a refresh sends `"progress"`
collection whose files it fetched: `fetched` is the number of collections after each collection whose files it fetched: `fetched` is the number of
fetched so far, and `total` the number it will fetch. A refresh fetches the collections fetched so far, and `total` the number it will fetch. A refresh
files of each collection that is new or changed since the cache's copy, so on an fetches the files of each collection that is new or changed since the cache's
empty cache it fetches those of every collection. The `"done"` event of a copy, so on an empty cache it fetches those of every collection. The `"done"`
machine-learning fetch, and of each background download, also carries `fetched`: event of a machine-learning fetch, and of each background download, also carries
how many items it newly stored. `fetched`: how many items it newly stored.
`lib.status()` returns a `LibraryStatus`. It holds the collection and file `lib.status()` returns a `LibraryStatus`. It holds the collection and file
counts. `lastRefreshAt` is the time of the last refresh that succeeded, and counts. `lastRefreshAt` is the time of the last refresh that succeeded, and
@@ -1381,9 +1381,9 @@ They differ because a download's length depends on the file and the link. A
whole-transfer deadline short enough to catch a hung connection would cancel a whole-transfer deadline short enough to catch a hung connection would cancel a
large video on a slow link that is still making progress. The download deadline large video on a slow link that is still making progress. The download deadline
restarts each time bytes arrive, so a slow download runs as long as it keeps restarts each time bytes arrive, so a slow download runs as long as it keeps
moving, and one that stalls is aborted after 60 seconds of silence. It covers moving, and one that stalls is aborted after 60 seconds of silence. The download
the wait for the headers as well as the body. There is no limit on the total deadline covers the wait for the headers as well as the body. There is no limit
length of a download. on the total length of a download.
A request that changes state is not blindly replayed. Every `POST` and `PUT` in A request that changes state is not blindly replayed. Every `POST` and `PUT` in
the endpoint list under "HTTP API" goes through this rule. Verifying a second the endpoint list under "HTTP API" goes through this rule. Verifying a second
@@ -1456,8 +1456,8 @@ exported `beginLogin`, `unwrapAuth`, `decryptCollection`, `decryptFile`,
`downloadFile` and `downloadThumbnail` need the same. `downloadFile` and `downloadThumbnail` need the same.
`client.logout()` clears the token and zeroes the key buffers in place. After `client.logout()` clears the token and zeroes the key buffers in place. After
it, every other method on that client throws. It does not contact the server, so it, every other method on that client throws. `logout()` does not contact the
the token stays valid there and in any saved snapshot. Call server, so the token stays valid there and in any saved snapshot. Call
`await client.logoutOnServer()` before `logout()` to end the session on the `await client.logoutOnServer()` before `logout()` to end the session on the
server. server.
+1 -1
View File
@@ -328,7 +328,7 @@ describe("what the library reports", () => {
]); ]);
}); });
// Each operation is named in plain words, as the README names it. // Each operation is named in plain words.
it("logs a refresh's progress at info, and its start and end at debug", () => { it("logs a refresh's progress at info, and its start and end at debug", () => {
const { log, lines } = collect(); const { log, lines } = collect();
const onProgress = logRefresh(log); const onProgress = logRefresh(log);