Repository navigation
Glossary
This page defines every term a newcomer will meet in the README, SETUP.md, RESEARCH.md, the code, and this wiki, in alphabetical order, one or two sentences each.
Where a term has a page of its own, the link follows the definition. All ids, keys and folder names shown here are placeholders of the right shape; yours are generated per install and will differ.
Additive-only. The property that neither applier ever moves, renames or removes a bookmark; each only creates what is missing. Deletion propagation is off by default and is not on the roadmap in any form that runs without confirmation. See Safety and Ownership Model.
allowed_origins. The field in the native-messaging host manifest that lists which extension origins may launch the host, written as chrome-extension://<your id>/ with the trailing slash. Every copy of the manifest must be updated whenever the extension id changes.
applied.json. A record the fallback file writer rewrites after every successful write, holding the GUIDs it placed and a timestamp. Nothing in the repo reads it back; it is evidence for you, not state the system depends on.
Applier. Either of the two Phase B components that turn desired.json into bookmarks: the unpacked extension (into the running browser) or the fallback file writer (into the Bookmarks file). Both are additive and both skip anything already present by URL, so they are safe to run together.
Atomic write. Writing to a temporary file on the same volume, fsyncing, then renaming over the target with os.replace, so the file is never torn and one version wins whole. Chromium's own ImportantFileWriter does the same, which is why a concurrent write cannot corrupt the file.
Backups (backups/). Timestamped copies of both Bookmarks and Bookmarks.bak that the file writer takes before every write, re-opens to prove they parse, and prunes to the last ten. They exist because Chromium's own .bak is not a safety net.
Bookmarks file. Chromium's JSON store for the bookmark tree, under the Brave profile directory, read exactly once at startup and thereafter overwritten from memory. Its top-level checksum is an MD5 over a pre-order walk of the tree, with titles hashed as UTF-16LE and everything else as UTF-8.
Bookmarks.bak. A copy Chromium takes of whatever was on disk at the first save of each browser session, never inspected and never read back. One session after a bad write, it holds the bad file.
Brave Sync. Brave's cross-device sync chain. If bookmark sync is on, the file carries top-level sync_metadata, injected nodes trip a corruption path and upload to every device, and the file writer hard-aborts rather than proceed.
Canary. The classified_count logged by every Phase A run. On a steady-state run it should be a handful; dozens or hundreds means something is re-selecting the library, and it is the single tell for every delta-detection failure mode.
Checksum. See Bookmarks file. Recomputed on read as a tripwire: a mismatch means something else is editing the file, and the writer refuses. Brave 152 does not read it, but it is written correctly anyway.
classified_count. The number of items Phase A classified in one run. See Canary.
Classified hash. The content_hash value recorded in the ledger once an item's classification has been committed to desired.json. It is written only after the commit, so a crash between the two costs one redundant reclassification rather than a silent skip.
Client. The browser a service worker reports itself as (brave, chrome, edge, and so on), used to key the extension's applied-set per browser. Brave is detected with "brave" in navigator because its user agent deliberately claims to be Chrome; a worker that sends nothing is stored under the sentinel unknown.
Collection. Raindrop's folder. Phase A files every bookmark into exactly one collection from the pinned taxonomy, creating a new collection when nothing fits, and never a catch-all.
collection-map.json. The map from taxonomy path (for example Woodworking / Hand Tools) to Raindrop collection id. Ids are per account and generated when the collection is created.
Content hash. sha256(raw_link|raw_title|||), computed over the verbatim Raindrop values with three always-empty slots for excerpt, note and type. It drives delta detection and must never be recomputed from curated display values. See Ledger and File Formats.
CRX. Chromium's packed extension format. Installing a locally signed CRX permanently marks its id DISABLE_NOT_VERIFIED, and the mark follows the id even when the same folder is later loaded unpacked; never pack one for this project.
Curated folder. A folder on the bookmarks bar that a person built by hand. The tool may add marked nodes into it, but only after a reject-by-default review, and it never touches the nodes already there. Contrast Managed folder.
Curated values. The cleaned title and link stored in the ledger's title and link columns for display: emoji stripped, entities decoded, tracking parameters removed. They intentionally disagree with the raw values the hash was computed from.
Delta. The set of items Phase A classifies in a run: those absent from the ledger (NEW), those whose content hash changed (EDITED), and everything if taxonomy_version moved. Computed from the content hash, never from a timestamp.
desired.json. The only handoff from Phase A to Phase B: a flat list of staged promotions, each {raindrop_id, name, url, folder_path} with folder_path relative to the bookmarks bar. Written by the skill, read by both appliers, never by the browser directly.
DISABLE_NOT_VERIFIED. Chromium's disable reason 256, recorded in Preferences when the install verifier rejects an id that is not on its signed allowlist. It cannot be cleared by any UI or profile edit; the only escape is a new id.
Extension id. Thirty-two lowercase letters a to p, shaped like abcdefghijklmnopabcdefghijklmnop, derived from the SHA-256 of the extension's public key. Pinning the key in manifest.json makes the id a function of key.pem rather than of the install path.
extension_applied. The state.db table where the native host records what the extension applied, keyed (client, raindrop_id) with a status of created, already_present or error. It is the extension's ownership record, because the extension cannot write the file marker.
Fallback writer (file writer). apply_brave.py, run by launchd every 15 minutes. It rewrites Brave's Bookmarks file with backup, atomic replace and re-read verification, and its changes appear at the next Brave start.
folder_path. The /-separated path under the bookmarks bar where a promotion belongs, for example Raindrop/Recipes. A leading Bookmarks Bar component is tolerated and stripped.
GUID. The durable identity of a bookmark node in the file format, which survives Chromium's recovery renumbering where the numeric id does not. The file writer generates them deterministically with uuid5 from the Raindrop id, so re-runs are byte-identical.
Host manifest. The JSON file, named com.raindrop_sync.host.json, that tells the browser where native_host.py lives and which extension may launch it. On macOS Brave reads it from Chrome's NativeMessagingHosts directory, not its own, so it is installed in both.
key.pem. The RSA private key whose public half is pinned in manifest.json and from which the extension id is derived. Losing it means a new id and a manual update of every host manifest; publishing it lets someone else mint your id. Mode 0600, never committed.
launchd agent. The macOS per-user job, label com.raindrop-sync.apply, that runs the fallback writer every 900 seconds and once at load. Its plist must use absolute paths, because launchd does not expand ~.
Ledger. The SQLite database state.db: one row per bookmark with its content hash, the per-browser extension_applied table, taxonomy metadata and run history. It is the memory that makes incremental classification possible. See Ledger and File Formats.
Managed folder. A folder this tool created and owns end to end, such as the top-level mirror folder holding one sub-folder per category. Only a managed folder may be named in reset_folders.json, because a reset removes everything inside it. Contrast Curated folder.
Marker. meta_info: {"raindrop_sync": "v1"} on every node the file writer creates. The writer may only add or remove marked nodes, so unmarked nodes are untouchable by construction; survival of the marker through Brave's own round-trip is verified on Brave 152. See Safety and Ownership Model.
Mirror folder. The managed folder on the bar that mirrors the Raindrop library, one sub-folder per top-level collection, kept flat because hover menus make every extra level a tax on the reader. See Managed folder.
Native messaging host. native_host.py, a stdlib Python process the browser spawns per tick and talks to over stdin and stdout using 4-byte length-prefixed JSON frames. It answers ping, pending and applied, writes only protocol frames to stdout, and logs everything else to native_host.log.
Phase A. Classification: network and LLM work that reads Raindrop, diffs the ledger, classifies the delta into the pinned taxonomy, writes collections and tags back, and stages promotions. It runs on demand as a Claude Code skill and never touches a browser file. See Architecture.
Phase B. Application: the two appliers that read desired.json and put bookmarks into Brave. It touches the browser and never the network, and runs unattended.
Pinned taxonomy. The folder tree and tag vocabulary in taxonomy.json, derived from your own library on the first run and then held fixed; routine runs classify into it and may extend it with a new collection but never restructure it. Re-derivation is a separate, explicit operation. See Taxonomy and Classification.
Postflight. The file writer's verification after a write: re-read from disk, confirm parse, checksum, id uniqueness and GUID uniqueness, and restore the backup on any failure. It is the only error surface a malformed bookmarks file has.
Preflight. The file writer's refusals before a write: the file missing, an unexpected version, a missing root, a checksum mismatch, sync_metadata present, or account or encrypted storage files present. Each is an abort with exit code 2, never a repair.
Promotion. A classified bookmark that has been judged worthy of the browser bar and staged in desired.json. Much narrower than "everything classified"; a run that classifies many and promotes none is normal.
Promotion gate. The reject-by-default review between classification and staging. It rejects deep links that will rot, commentary rather than primary sources, one-off product pages, job postings, news articles, and any proposed new folder with fewer than three qualifying items.
Provenance tag. A tag such as paid-ad or short-link that records how a bookmark arrived. Kept as a fact, never allowed to drive placement.
Raw values. The verbatim link and title as Raindrop returns them, before any cleaning. The content hash is computed over these and only these.
Reconcile / reset. Reconcile is the convergence loop: each tick compares desired.json against what is actually present (by marker, GUID or URL) and adds only the difference, never removing anything to make them agree; in Phase A it also names a full-library read that confirms the ledger matches Raindrop. Reset is the extension-only rebuild of a managed folder requested through reset_folders.json: tear the folder down, then re-create its pending items. See Operations.
reset_folders.json. A JSON array of top-level managed folder titles, for example ["Raindrop"], that asks the extension to remove and rebuild those folders on its next tick with pending items. The fallback writer ignores it.
Serialize (the promise chain). The lock in sw.js that funnels every sync entry point (worker load, onInstalled, onStartup, the alarm) through one promise chain so concurrent callers queue instead of racing. Removing it reintroduces duplicate bookmarks.
Service worker. The MV3 extension's background script, sw.js, which Chromium starts on demand and kills when idle. Its entry points are not ordered relative to each other, and an unpacked worker does not hot-reload.
Source-derived. One of the three status labels in RESEARCH.md: a claim read from Chromium source and adopted as a design constraint rather than reproduced by experiment (findings 5 and 6, for example). See Research Status.
state.db. See Ledger.
Taxonomy (taxonomy.json). See Pinned taxonomy. It is per install and never shipped; the examples in this wiki (Recipes, Woodworking, Research Papers, Travel) are invented.
taxonomy_version. A counter in the ledger's metadata that is bumped only by an explicit re-derivation of the taxonomy or by any other change that invalidates every stored hash, such as widening the hash input. A bump reclassifies the entire library, which is why it is never done silently.
TCC. macOS's per-application privacy consent. Under launchd a denial surfaces as a bare Operation not permitted with no dialog, which is why the runtime tree lives at ~/.raindrop-sync rather than under ~/Documents or ~/Downloads.
Test token. The Raindrop API token created under Settings, Integrations, for an app you create yourself. It authenticates as you with no expiry and no scoping, so it is stored in the login keychain (optionally .env), consumed only through a pipe, and rotated the moment it has been printed anywhere.
Throwaway profile. A copy of the Brave profile directory launched with --user-data-dir=<copy>, used for every experiment so the real profile is never at risk. The method is in RESEARCH.md section 12.
Tick. One run of an applier: an extension alarm firing (every 60 seconds while Brave is open) or a launchd interval elapsing (every 900 seconds). Each tick either finds nothing to do or applies what is missing and re-verifies on the next one.
Unpacked extension. An extension loaded from a folder through Developer mode and Load unpacked, exempt from the install verifier. It is the only supported install route for this project; --load-extension applies only to a browser you launch yourself.
Untested. The RESEARCH.md status label for a claim that has been neither reproduced nor derived from source, such as whether a tag-only edit advances Raindrop's changedBookmarksDate. Phase A does a full read every run until that one is confirmed. See Research Status.
Verified. The RESEARCH.md status label for a claim established by experiment on a real machine, ideally in both directions, such as the checksum encoding and marker survival. See Research Status.
Watermark. The rejected design of selecting changed items by lastUpdate timestamp. Raindrop bumps that field on every write, including this tool's own write-back, so a watermark re-selects the whole library forever.
WebKit timestamp. The date format in the Bookmarks file: microseconds since 1601-01-01, stored as a decimal string. Computed as int(time.time() * 1e6) + 11644473600000000.
Write-back. Phase A's writes to Raindrop: creating collections and applying tags, with Raindrop as the source of truth. Tag writes are read-modify-write because Raindrop's tag field appends rather than replaces.
MIT licence | raindrop-brave-sync on GitHub | Roadmap board
raindrop-brave-sync
Start here
How it works
Running it
Research
Community