chore: drop the Claude plugin and the bundled skill — hooks are the integration (#85)

Two front doors for the same setup, and one of them was a second copy of
everything. The plugin shipped the skill the CLI already installs (to four
platforms, not one), hooks that ran the identical commands `bdrive hooks
install` writes machine-level, and an install flow duplicating
INSTALL_FOR_AGENTS.md. Nothing deduped, so a machine with both pulled twice
per turn — two blocking syncs — and showed two identical `beardrive` skills
in the picker.

What remains is `internal/agenthooks` plus the runbook: init registers a
blocking pull (which also injects the gated-link convention as
additionalContext), an async push on Write/Edit, and read-log for the
heatmap, in each platform's user config, once per machine. That is the whole
integration, and it is the part that was never optional.

Removed: plugin/, .claude-plugin/marketplace.json, internal/agentskills,
`bdrive skill`, `bdrive hook-approve` (its PreToolUse auto-approve only ever
helped when a plugin pre-installed it; the substitute is a `Bash(bdrive:*)`
permission entry, which is user-owned config and needs no code).

The e2e now asserts the absence: no SKILL.md in any platform's skills dir
after init, and no `skill` subcommand. login_test keeps the "no revoke
surface" wording check on logoutNote alone.


Claude-Session: https://claude.ai/code/session_016aYntCWwdUhpzUfEk3ddyJ

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Snow W. Lee (Sungwon)
2026-07-30 12:40:47 +09:00
committed by GitHub
co-authored by Claude Opus 5
parent dfb9da3260
commit 31f705e287
41 changed files with 144 additions and 1773 deletions
@@ -1,36 +1,11 @@
---
title: Skills and hooks in detail
description: What bdrive skill install and bdrive hooks install actually write — the user-level config paths, hook events, idempotency, and when to re-run them.
title: Hooks in detail
description: What bdrive hooks install actually writes — the user-level config paths, hook events, idempotency, and when to re-run it.
---
`bdrive init` runs both of these for you — that is why setup is one command. This
is what they do, for when you want to run them yourself, review what changed, or
debug a folder that isn't syncing.
## The skill
```sh
bdrive skill install # every detected platform
bdrive skill install --agent codex,hermes
bdrive skill # status table
```
It writes one `SKILL.md` — the cross-agent format — into each platform's
user-level skills directory:
| Platform | Path |
|---|---|
| Claude Code | `~/.claude/skills/beardrive/SKILL.md` |
| Codex | `~/.codex/skills/beardrive/SKILL.md` |
| Gemini CLI | `~/.gemini/skills/beardrive/SKILL.md` |
| Hermes | `~/.hermes/skills/beardrive/SKILL.md` |
Installs are user-level on purpose: the skill is about the CLI, not about one
folder, and a synced project folder should never carry it. The file is the
binary's own copy, so re-running after a CLI upgrade refreshes a stale one.
The Claude Code plugin ships the same skill, so `/plugin install
beardrive@beardrive` covers Claude without this command.
`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
@@ -82,8 +57,7 @@ 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 after a CLI upgrade: `bdrive hooks install` and `bdrive skill install`,
once per machine each.
Re-run `bdrive hooks install` after a CLI upgrade, once per machine.
## Where they live matters
+2 -3
View File
@@ -50,9 +50,8 @@ Clients and hub are the same binary — keep them roughly in step. The sync
protocol is append-only journals plus blobs, which old clients read forward.
After upgrading a client, re-run `bdrive hooks install` to pick up hook
improvements and `bdrive skill install` to refresh the agent skill — both once
per machine, since both write to your user config. (Re-running `bdrive init` in a
synced folder refreshes both.)
improvements — once per machine, since it writes to your user config.
(Re-running `bdrive init` in a synced folder does it too.)
## Next
@@ -8,7 +8,7 @@ Useful on a machine with no agent, when scripting a fleet, or when you simply
want to see the moving parts.
Three steps: sign the device in, start syncing a folder, work normally. `init`
installs the agent skill and [registers the hooks](/manual/skills-and-hooks/)
[registers the hooks](/manual/hooks/)
along the way — that is what keeps an agent's files fresh, and it used to be the
step hand-setups forgot.
@@ -44,7 +44,6 @@ $ cd ~/workspace && bdrive init
initialized /Users/snow/workspace
server: https://your-hub
project: workspace (p-7f3a2c91)
skill: installed for claude, codex
claude hooks registered → /Users/snow/.claude/settings.json
daemon: running (pid 55434, scan 3s, remote sync 10s)
```
@@ -59,10 +58,9 @@ folder and syncs everything.
Init writes `.bdrive/config.json`, seeds a starter `.bdriveignore`
(node_modules, build dirs, caches, `.env*`), starts the daemon, and prints the
project's hub link. It also installs the `beardrive` skill and registers the sync
project's hub link. It also registers the sync
hooks for any agent platform it detects — in that platform's **user** config, once
per machine, so nothing lands inside the project. `--no-hooks` skips the hooks
(the skill is installed either way). Not
per machine, so nothing lands inside the project. `--no-hooks` skips them. Not
signed in yet? It runs the login flow first.
:::tip[Working inside a repository]
@@ -106,7 +104,7 @@ changes.
## Next
- [Skills and hooks in detail](/manual/skills-and-hooks/) — what `init` wrote to
- [Hooks in detail](/manual/hooks/) — what `init` wrote to
make an agent read fresh files every turn, and how to inspect or remove it.
- [Shared agent memory](/guides/shared-agent-memory/) — orient agents in the
folder so they know where to read and write.
+5 -7
View File
@@ -11,7 +11,7 @@ One binary, `bdrive` — the CLI, the sync daemon, and the web server.
|---|---|
| `bdrive login [server-url]` | Sign this device in. Browser flow; `--device` forces the approval-link flow, and shells without a TTY (agents, CI, SSH) fall back to it automatically. Default server is beardrive.ai — the managed cloud, free personal workspace on signup; pass your hub URL to self-host. Switch hubs with `bdrive login <new-url>`. `--status` shows the current server and account |
| `bdrive logout` | Sign this device out — clear the saved token and account. `--forget` also drops the remembered server |
| `bdrive init [folder]` | Create or connect a project and start syncing — the mount is always exactly the folder named. Interactive on a TTY; flags (`--name`, `--project`, `--server`, `--only`, `--yes`) for scripts. Also installs the agent skill, registers agent sync hooks for detected platforms (`--no-hooks` skips the hooks only), and prints the project's hub link. Re-run to resume |
| `bdrive init [folder]` | Create or connect a project and start syncing — the mount is always exactly the folder named. Interactive on a TTY; flags (`--name`, `--project`, `--server`, `--only`, `--yes`) for scripts. Also registers agent sync hooks for detected platforms (`--no-hooks` skips them), and prints the project's hub link. Re-run to resume |
| `bdrive stop [folder]` | Stop syncing — daemon and agent sync hooks both pause. Files stay on disk; `bdrive init` resumes |
| `bdrive scope [add\|rm <dirs...>]` | Show or change which subfolders sync — edits the managed block of `.bdriveignore` rules that `init --only` writes. Run from the mount root; the daemon picks changes up in seconds. `rm` stops syncing a folder but deletes nothing, locally or on the hub |
| `bdrive scope --explain` | List every path in the folder, split into what syncs and what does not, with counts — the verifiable answer to "what leaves this machine". Pure read: no daemon, no lock, no network |
@@ -20,8 +20,6 @@ One binary, `bdrive` — the CLI, the sync daemon, and the web server.
| `bdrive share <file>` | Public URL for a synced file. `--list`, `--revoke`, `--expires` (the hub's Share dialog can also set an expiry on an existing link) |
| `bdrive sync [folder]` | Run one sync cycle now. Refuses folders this device never `init`ed and folders paused by `bdrive stop`. `--note <text>` stamps session context onto changes; `--note-ttl` (default 30m) bounds it. `--prune` also removes from the hub what `.bdriveignore` now excludes (files stay on disk everywhere). `--hook <label>` is agent-hook plumbing |
| `bdrive hooks [install\|uninstall]` | Register turn-boundary sync hooks in each detected agent platform's user config — once per machine, covering every folder. Run automatically by `bdrive init`; idempotent; `--agent` overrides detection. `uninstall` removes only BearDrive's own hook entries |
| `bdrive skill [install]` | Install the `beardrive` skill into detected agent platforms so the agent can do setup itself. Run automatically by `bdrive init`; idempotent; `--agent` overrides detection |
| `bdrive hook-approve` | Hook plumbing: answers the beardrive plugin's `PreToolUse` hook, auto-approving bare `bdrive init\|login\|hooks\|status\|sync\|url` so setup costs no permission prompts. Anything with a shell operator is left to the normal prompt |
| `bdrive read-log [folder]` | Hook plumbing: queue agent file reads for the hub's read heatmap. Registered by `bdrive hooks install` |
| `bdrive status [folder]` | Projects, daemon state, pending changes |
| `bdrive log [folder] [-p path] [-n N]` | Change history: account, device, time, file |
@@ -49,9 +47,9 @@ setting. Full flag bypass with `--name`, `--project`, `--only`, `--yes`, and
it never prompts without a TTY.
It runs the login flow first when there is no session, writes
`.bdrive/config.json`, seeds `.bdriveignore`, installs the `beardrive` skill and
registers agent sync hooks for every detected platform (Claude Code, Codex,
Gemini CLI, Hermes — `--no-hooks` skips the hooks; the skill is installed either way), starts sync, and prints the
`.bdrive/config.json`, seeds `.bdriveignore`, registers agent sync hooks for
every detected platform (Claude Code, Codex, Gemini CLI, Hermes — `--no-hooks`
skips them), starts sync, and prints the
project's hub link. That is deliberate: one command means one permission prompt
for an agent, instead of four. Re-running it resumes — including after a folder
move.
@@ -59,7 +57,7 @@ move.
The hooks land in each platform's **user** config (`~/.claude/settings.json` and
friends), once per machine, so they cover every session in every folder; nothing
is written inside the project. See
[Skills and hooks in detail](/manual/skills-and-hooks/).
[Hooks in detail](/manual/hooks/).
The daemon scans every 3s and talks to the hub every 10s; those intervals are
tunable on `bdrive daemon run`, not on init.
@@ -43,7 +43,7 @@ Those two are all BearDrive puts in a project: `.bdrive/config.json`,
here — the sync hooks live in each platform's user config
(`~/.claude/settings.json`, `~/.codex/hooks.json`, `~/.gemini/settings.json`,
`~/.hermes/config.yaml`), written once per machine. See
[Skills and hooks in detail](/manual/skills-and-hooks/).
[Hooks in detail](/manual/hooks/).
## Global state
+18 -53
View File
@@ -1,6 +1,6 @@
---
title: Set up with your agent
description: You don't install BearDrive — you ask your agent to. One command in Claude Code, or one paste in Codex, Gemini CLI, or Hermes, and the folder syncs from then on.
description: You don't install BearDrive — you ask your agent to. One paste in Claude Code, Cowork, Codex, Gemini CLI, or Hermes, and the folder syncs from then on.
---
You don't set BearDrive up. Your agent does.
@@ -9,44 +9,10 @@ Give it one instruction and it installs the CLI, signs this machine in, connects
the folder to a project, and registers the hooks that keep everything in sync —
then tells you what it did. You never open a config file.
## Claude Code and Cowork
## Any agent: one paste
Install the plugin once, in any session:
```
/plugin marketplace add runbear-io/beardrive
/plugin install beardrive@beardrive
```
Then, in the folder you want synced:
```
/beardrive:install
```
It walks you through it: creates or connects a project, asks whether to sync the
whole folder or a subfolder like `wiki/`, offers to write the
[agent orientation files](/guides/shared-agent-memory/), and registers the sync
hooks. It asks before anything it changes.
Cowork shares Claude Code's plugins, so installing it once covers both.
Two more commands come with the plugin: **`/beardrive:init`** to start syncing
without the full setup conversation, and **`/beardrive:status`** to diagnose a
sync problem.
:::tip[Hooks are registered once per machine]
`/beardrive:install` writes hooks into your user config (`~/.claude/settings.json`
and friends), so **every session in every folder is covered** — not just the ones
started where you ran setup. Nothing is written into the project, and each
teammate registers their own the first time they set up.
:::
## Codex, Gemini CLI, and Hermes
These agents ship no BearDrive knowledge yet, so the prompt points them at the
canonical instructions instead. Start the agent in the folder you want synced
and paste:
Start the agent — Claude Code, Cowork, Codex, Gemini CLI, Hermes — in the folder
you want synced, and paste:
```
Follow https://raw.githubusercontent.com/runbear-io/beardrive/main/INSTALL_FOR_AGENTS.md
@@ -60,9 +26,8 @@ thing; the agent handles every deviation — already installed, no Homebrew,
browser sign-in, wrong folder. On BearDrive Cloud, drop `on <hub-url>`
sign-in defaults to beardrive.ai.
The skill step in those instructions is the durable part. Once the skill is
installed the agent knows the CLI from then on, so "share this file" or "what
changed?" work without you explaining anything again.
The hooks step is the durable part: once they are registered, every later
session in every folder syncs automatically, with nothing to remember.
:::tip[Don't retype this for teammates]
A project's home page in the hub shows this same paste with your hub URL and
@@ -71,19 +36,20 @@ project id already filled in. Send people there.
## What your agent just set up
Two things, worth knowing by name:
The sync hooks, and nothing else you have to think about:
- **The skill** — a `SKILL.md` in the agent's own skills directory, teaching it
the `bdrive` CLI. It is a cross-agent format, so one file works in Claude Code,
Codex, Gemini CLI, and Hermes.
- **The hooks** — a blocking pull when you send a message, so the agent always
reads the team's current files, and an async push when the turn ends, so what
it writes reaches everyone else within seconds. They go in the agent's user
config, once per machine, and are a no-op outside BearDrive folders.
- a **blocking pull** when you send a message, so the agent always reads the
team's current files — it also tells the agent your project's link
convention, so it can hand you a hub link for any file it mentions;
- an **async push** after every file edit, so what it writes reaches everyone
else within seconds;
- **read tracking**, so the hub's Dashboard can show what your agents actually
read.
The hooks are what make syncing automatic. `bdrive init` registers them for you,
so there is nothing extra to run — [skills and hooks in
detail](/manual/skills-and-hooks/) covers what gets written where.
They go in the agent's user config, once per machine, and are a no-op outside
BearDrive folders. `bdrive init` registers them for you, so there is nothing
extra to run — [hooks in detail](/manual/hooks/) covers what gets written
where.
## Check it worked
@@ -91,7 +57,6 @@ Ask the agent — "is BearDrive set up in this folder?" — or look yourself:
```sh
bdrive status # projects, daemon state, pending changes
bdrive skill # which agents know the CLI on this machine
bdrive hooks # which agents on this machine sync automatically
```
@@ -26,17 +26,14 @@ The folder does not have to match across machines. State is keyed by a stable
project id, never a path, so `~/work` on one and `~/Documents/work` on another
are the same project. Moving or renaming a folder later is free.
The skill and the hooks are installed **once per machine**`bdrive init` does
both on each new device — and from then on they cover every folder that machine
syncs. That is what makes each agent pull before it answers. See
[skills and hooks in detail](/manual/skills-and-hooks/).
The hooks are registered **once per machine**`bdrive init` does it on each
new device — and from then on they cover every folder that machine syncs. That is what makes each agent pull before it answers. See
[hooks in detail](/manual/hooks/).
## More than one agent per machine
The skill is a cross-agent format and the hooks are written into each platform's
own user config, so
Claude Code, Codex, Gemini CLI, and Hermes can all be wired into the same folder
at once. They read the same files and their writes are stamped with which agent
The hooks are written into each platform's own user config, so Claude Code,
Codex, Gemini CLI, and Hermes can all be wired into the same folder at once. They read the same files and their writes are stamped with which agent
session made them, so `bdrive log` and the hub's history stay legible even when
four agents share a project.
@@ -53,7 +50,7 @@ mechanism, just with a longer window.
## What matters for this case
- **[Skills and hooks in detail](/manual/skills-and-hooks/)** — what each new
- **[Hooks in detail](/manual/hooks/)** — what each new
machine registers, and why the pull hook is the one that matters.
- **[How sync works](/concepts/how-it-works/)** — journals, blobs, and
deterministic replay, if you want to know why this converges rather than
@@ -18,14 +18,13 @@ person's agent re-does work that already exists.
## Set it up
Install the plugin once — Cowork and Claude Code share plugins, so this covers
both — then run `/beardrive:install` in the folder you want shared.
[Set up with your agent](/start/setup/) has the two commands.
Start your agent in the folder you want shared and give it the one paste from
[Set up with your agent](/start/setup/).
Nobody on the team needs to open a terminal: the agent installs what it needs
and reports back. Invite teammates from the hub's sidebar (**Manage → New
invite**); the link creates their account and adds them in one step, and they
run the same `/beardrive:install` on their own machine.
give their own agent the same paste.
If the shared work should live in one subfolder rather than everything on your
disk, say so — "sync only `client-work/`" — and the agent scopes it.