Hooks in detail
bdrive init runs this for you — that is why setup is one command. This is what
it does, for when you want to run it yourself, review what changed, or debug a
folder that isn’t syncing.
The hooks
Section titled “The hooks”bdrive hooks install # every detected platform, this machinebdrive hooks install --agent claude,codex,gemini,hermesbdrive hooks # status tablebdrive hooks uninstall # remove them againEach platform gets the same three hooks written into its own user-level config, in its own format:
| Platform | Config it writes | Pull / push / read events |
|---|---|---|
| Claude Code | ~/.claude/settings.json |
UserPromptSubmit / PostToolUse (Write|Edit|MultiEdit) / PostToolUse (Read|Grep|Bash) |
| Codex | ~/.codex/hooks.json |
UserPromptSubmit / PostToolUse (apply_patch) / PostToolUse (read_file|shell) |
| Gemini CLI | ~/.gemini/settings.json |
BeforeAgent / AfterTool (write_file|replace|edit) / AfterTool (read tools) |
| Hermes | ~/.hermes/config.yaml |
pre_llm_call / post_tool_call (write_file|patch) / post_tool_call (read_file|grep|bash) |
Three hooks, three jobs:
- Pull, before the agent answers, so it never reads a stale file. This one blocks — it is the only place BearDrive makes you wait, and it is why the whole thing works.
- Push, after an edit, so teammates see the change within seconds even when no daemon is running.
- Read tracking, on the agent’s read-shaped tools, queued locally and sent on the next sync. This is what fills the Dashboard. Listing tools are deliberately excluded: seeing a filename is not reading it.
When the sync daemon is running and up to date with the hub (it has pulled since the last change it was told about, and its connection to the hub is alive), the pull and push hooks leave the syncing to it: they only record the session and report what changed, and return in milliseconds (after waiting for a daemon sync already in progress to finish). Without a daemon, or when the daemon cannot vouch for the folder, they run a full sync themselves.
A session that starts above its synced folders (your home folder, or a repo
root whose wiki/ is the synced folder) never runs that full sync: it records
the session, reports what the daemon has pulled so far, and starts the daemon
if it is not running. Walking every synced folder below your home folder on
each prompt is slower than the hook’s timeout.
Every platform pipes hook JSON with a session id, so one hook command serves all
four, and changes are stamped with <agent> session <id> — visible in
bdrive log and the hub’s history.
Codex hooks are experimental and off by default. Turn them on in
~/.codex/config.toml:
[features]codex_hooks = trueCodex then asks once to trust the hook definition. Answer yes.
Both are safe to re-run
Section titled “Both are safe to re-run”Merging is idempotent and preserves hooks you already have. Each hook carries its own marker, so a config written before a hook existed gains just the missing one, and a registered hook’s matcher is upgraded in place when coverage grows.
Re-run bdrive hooks install after a CLI upgrade, once per machine.
Where they live matters
Section titled “Where they live matters”Hooks are registered once per machine, in each platform’s own user config — never inside a project. Agent platforms read hook config only from the directory a session starts in: never a parent, never a subfolder. A file in the project would fire only for the sessions that happened to start exactly there, and — if the project is synced — would travel to the whole team. A user-level registration covers every session in every folder instead.
So BearDrive writes no agent-config directory into your project, and teammates
don’t inherit your hooks: each device registers its own the first time it runs
bdrive init. Earlier versions did write project-level hooks; installing strips
those out as it goes, so nothing ends up running twice.
The hook opens with a shell guard that makes it a fast no-op in any folder
without a .bdrive/ directory, which is what makes registering it globally safe.
bdrive hooks uninstall takes them back out — it removes only BearDrive’s own
entries and leaves every other hook in those files untouched. Syncing itself is
unaffected; only turn-boundary sync stops.
Surviving a reboot
Section titled “Surviving a reboot”The sync daemon is an ordinary background process, so a restart ends it. bdrive init therefore also registers a login item that runs bdrive resume, which
starts or wakes the global sync supervisor for every project this device syncs and
has not paused:
bdrive autostart # is it registered?bdrive autostart install # register it (init already did)bdrive autostart uninstall # stop starting sync at loginbdrive resume # start or wake the sync daemon right nowOne registration covers every project — add or remove projects freely, nothing
to re-register. Projects paused with bdrive stop stay paused; only bdrive init resumes those.
Where it lives, per platform — user-level either way, no sudo, nothing
machine-wide:
| Platform | What gets written |
|---|---|
| macOS | ~/Library/LaunchAgents/ai.beardrive.daemon.plist (launchd loads it at login) |
| Linux | ~/.config/systemd/user/beardrive.service plus the default.target.wants symlink that enables it (honors XDG_CONFIG_HOME) |
Linux needs systemd as the init system. Without it — Alpine or another
runit/OpenRC distro, WSL1, a slim container — bdrive autostart says so rather
than writing a unit nothing would read.
On macOS, the moment that file is written you get a “Background Items Added”
notification, and bdrive appears in System Settings → General → Login Items.
That notice is macOS reporting the registration above — every way of starting
at login triggers it, including Apple’s own SMAppService and a plain
crontab — so bdrive init asks first on a terminal and says what is about to
happen when it can’t ask. Answer no, or run bdrive autostart uninstall, and
the item goes away; sync then resumes on the next bdrive resume, bdrive init, or agent turn instead of at login.
Either way this is not the only thing that recovers sync: an agent turn in a project syncs it too, so a machine you actually work on catches up on its own.