Repository navigation
fileregister 1.4.0
Albums are named in the note's frontmatter. An album gives a bundle an order; what it is called is one field. album: Safari, Namibia 2026 in the frontmatter of the binder's note, and every member inherits it, because grubber passes frontmatter down into each block of the file. The heading takes it from the members, and without the field it stays the binder name. register album safari --title "Safari, Namibia 2026" writes the field, editing the note by hand does the same, and grubber extract ~/notes -a -f album~Safari finds every member.
The identity layer is auditable. ~/.local/share/bookmarks.json holds id → bookmark and was the one store nothing could see into: both existing audit directions start from records, so an entry no record claimed was invisible, and the file only grew. register audit gains a third direction, Bookmark → Record, with four verdicts: orphan (resolves, no record claims it), broken (a file still carries the id, so register repair can re-bind it), dead (neither), and malformed (the key was never a minted id). register cleanup gains a matching section offering only the two beyond repair, and --prune drops them without asking.
--prune refuses rather than guess. "Dead" means the blob does not resolve and no file carries the id, which is only true if the question could be asked. An unmounted volume, or a mounted one Spotlight does not index, makes every bookmark on it look dead, so those entries are parked as unreachable and the prune declines, naming the volume. The same holds for the engine: without fileanchor 1.2.0's last_path the guard has nothing to judge, so the dead verdict is withheld entirely. The capability is measured, not read off a version number.
Engine: fileanchor 1.2.0, bundled in the download and required for the audit direction above. Resolving no longer mounts a volume or shows UI. It used to mount detached disk images on its own and could block on an unreachable network share. A failed resolve now names the path recorded in the bookmark, which is what separates a gone file from an absent volume. And the id attribute is stored as a property list: written as a raw string, two ids on one file made Spotlight drop the whole value, so the file could be found by neither.
grubber comes in the download. fileregister without grubber is the index; whenever the Markdown layer comes into play, grubber reads it. register album now does too, instead of parsing notes itself, and the download carries grubber v0.18.0 beside the engine, so there is nothing to install. The core lifecycle commands run without it; for a source build, make grubber fetches it.
repair and refresh exit non-zero while something needs you. Both exited 0 with records left unresolved, broken bookmarks or failed metadata writes, so neither could drive a monitor. repair exits 1 while a record stays unresolved or a repaired file lacks metadata (files on an unmounted volume do not count); refresh exits 1 on failed writes, broken bookmarks or missing files.
★ is not a binder name. With the tags backend a binder is a Finder tag, and ★ is the marker fileregister owns, so removing a binder named ★ stripped the marker from files still in other binders. A new binder by that name is now refused.
Thirty-six correctness fixes, from a pass over every subcommand. The ones worth knowing: a damaged or unreadable bookmarks.json is an error instead of an empty database. Every writer saves the whole map back, so the next add replaced all stored bookmarks with the few it had just made. An index that cannot be read in full stops the run. add and aka hold their locks across the uniqueness check. A rewritten file keeps its extended attributes. A Finder tag you had set before a binder of the same name is never removed. A container from elsewhere is treated as untrusted. repair takes a file only when it is sure, compares names NFC, and says when it could not write metadata. of tells engine failures, copies and same-named files apart. YAML values are quoted whenever they would not read back as themselves, annotate --prose skips every code fence, and CRLF notes read. list --help answers instead of listing; it had accepted the flag and ignored it.
Download (Apple Silicon): fileregister-macos-arm64.tar.gz bundles register with its two helpers in libexec/, the fileanchor engine and grubber, ready to run, plus each component's licence in licenses/ (register and the engine are PolyForm Noncommercial, grubber is MIT). Fetched with curl it runs as-is; after a browser download, clear the quarantine flag once: xattr -dr com.apple.quarantine register libexec. Intel Macs: build from source (go install + make fileanchor + make grubber).
License: PolyForm Noncommercial 1.0.0. (use, change, non-commercial)