From 974d8aba2fbba10c57e318d6651a285ad547ae9d Mon Sep 17 00:00:00 2001 From: Snow Lee Date: Tue, 28 Jul 2026 18:06:05 -0700 Subject: [PATCH] docs: fix stale claims an audit found against the new CLI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An audit of every doc surface against the code turned up claims that the user-scope hook move and the one-command init made false: project-level hooks "riding the repo", the Claude trust prompt, Codex's //hooks project layer, `--no-hooks` skipping the skill (it does not), prune reconciling against a per-device scope (it now refuses on a scoped project), and `--scan-interval`/`--remote-interval` documented as init flags when they only exist on `bdrive daemon run`. Also documents the surface added today — `--server`, `bdrive hooks uninstall`, and the plugin's PreToolUse auto-approval — refreshes the two sample `init` transcripts to the real output, and corrects hook matchers that had drifted from agenthooks.go. `bdrive scope` told users to narrow an existing mount with `bdrive init . --only `, which resume then ignored — a dead end. Init now applies --only on resume, writing the scope block, so the advice works. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_016aYntCWwdUhpzUfEk3ddyJ --- CLAUDE.md | 2 +- INSTALL_FOR_AGENTS.md | 2 +- README.md | 32 ++++++++++++------- cmd/bdrive/init.go | 21 +++++++++++- plugin/commands/init.md | 4 +-- plugin/commands/install.md | 2 +- plugin/skills/beardrive/SKILL.md | 17 +++++----- .../src/content/docs/concepts/how-it-works.md | 3 +- web/docs/src/content/docs/manual/install.md | 2 +- .../src/content/docs/manual/setup-by-hand.md | 6 +++- web/docs/src/content/docs/reference/cli.md | 9 +++--- .../content/docs/reference/project-files.md | 3 +- 12 files changed, 69 insertions(+), 34 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 32d7916..4cae9ac 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -46,7 +46,7 @@ Package roles (`internal/`): - **`config`** — global state under `$BDRIVE_HOME` (default `~/.bdrive`): device identity (`device.json`), settings (`settings.json`: default server + device token + signed-in account), and the mount registry (`mounts.json`, keyed by **stable mount id**, holding only each mount's last-known path). The per-folder `.bdrive/` directory (`project.go`) holds `config.json` with the mount id + volume/remote/include; **nothing is keyed by the folder path**, so renames/moves are free — `ResolveMount` self-heals the registry path, and the volume store lives at `~/.bdrive/volumes//`. `.bdrive/` is never synced and holds no credentials. - **`webapp`** — the `bdrive web` server, in two modes. Single-volume: `Source` is a `DirSource` (plain folder from disk) or `RemoteSource` (folds journals into a file tree with per-file provenance). Hub: `Root` + `Projects` host many projects on one storage root, each under `//` via `remote.Prefixed`; `ProjectDB` (`projects.go`) is a file-backed registry (JSON, loaded at open, rewritten atomically per change) with create-or-join-by-name semantics, name-scoped per organization. Orgs (`orgs.go`, file-backed `orgs.json`) wall projects by membership (email → owner|member): every per-project route — viewer APIs, uploads, history, shares management, the `/store/*` sync proxy — 403s for non-members, `/api/projects` lists only your orgs' projects, owners mint expiring multi-use invite links (`/join/`), and a pre-org hub migrates all projects into a "default" org (all existing accounts join, oldest owns) at startup. `QuotaProvider` (`quota.go`) is the plan-enforcement seam mirroring `AuthProvider` — CheckWrite/RecordUsage on every write path, CheckSeat on invite redemption; OSS ships only `UnlimitedQuota`, managed deployments swap the provider. Renders markdown (goldmark + Obsidian `[[wikilinks]]`). With `--upload` it accepts writes: browser uploads (`upload.go` — direct-to-storage via presigned URLs when the backend implements `remote.PutSigner`, relayed otherwise; ops journaled under the server's own device) and the per-project `/api/p//store/*` proxy (`store.go`) that whole devices sync through — the `https://` remote backend (`remote/http.go`) is its client; journals are never presigned, only immutable blobs. Frontend is a React + TypeScript app (`webapp/frontend/`, Vite + Tailwind v4 + shadcn/ui — Radix-based components copied into `src/components/ui`, themed from the BearDrive tokens in `src/tw.css`; TanStack query/table/virtual, react-hook-form + zod, cmdk, sonner, lucide-react) whose **built output is committed** at `webapp/static/` — the `go:embed static` target — so plain `go build` needs no Node; after any `frontend/src` change run `npm run build` there and commit the new `static/` (`frontend/check-dist.sh` verifies freshness; e2e suite: `npm run e2e` — Playwright against the seeded harness in `e2e_serve_test.go`, port 8993). It learns everything from `/api/config` (+ `/api/projects` in hub mode) and never sees storage info or credentials. It uses native History-API path routing (`//` in hub mode, `/` in volume mode, `/join/` for invites — no `#`, slashes stay literal). **Every user-facing page owns a URL path**: new surfaces are view routes (`//{dashboard|history|install|settings}[/]`, `VIEW_ROUTES` in `router.ts`; renamed segments live in `LEGACY_VIEWS` and are normalized away on arrival) so deep links, reload, and back/forward always work — never URL-less panel state (the org/hub admin panels are the legacy exceptions; don't add more) implemented by the in-repo synchronous router `frontend/src/nav.ts` + `router.ts` (deliberately NOT a router library: react-router v7's startTransition navigation left stale views on screen); `Server.frontend` serves `index.html` as the SPA fallback for any non-asset, non-API/auth/share route so deep links and refreshes resolve (hashed `assets/*` are cached immutable, everything else no-cache), and all client API/asset URLs are root-absolute so a deep path doesn't break relative resolution. Rendered markdown is transformed as a string before mounting and link clicks are delegated on the container — never patch the `dangerouslySetInnerHTML` subtree after commit (React re-applies the markup on unrelated updates and discards DOM patches). **Read heat** (`reads.go`): a `ReadLedger` (hub-only, nil = off, config `reads` block) aggregates read telemetry into daily per-actor buckets, debounced to 10-minute visits, folded into all-time rows past `retention_days` — viewer file/render/download = human (recorded via the project id the `proj()` resolver stashes in the request context), `/s/*` hits = share, device-reported reads (`POST /api/p//reads`) = agent; `/store/*` replication and history `/blob` views are NEVER reads. `GET /api/p//heat?prefix=&days=` returns counts/distinct-readers/last-read only — actor identities (the email/device/token in the buckets) must never appear in an API response. Recording and flushing degrade silently (log once); telemetry must never fail a request or a sync cycle. The frontend shows heat dots on folder listings and a per-project Dashboard quadrant (reads × staleness, route `//dashboard`) — both visible to every project member, since `/heat` is membership-gated and identity-free. **Hub metadata persistence** (accounts, projects, orgs+invites, shares, devices, read buckets — never blobs or journals) sits behind a pluggable `MetaStore` of typed repos (`db.go`): the service structs (`BuiltinAuth`, `OrgDB`, `ProjectDB`, `ShareDB`, `DeviceRegistry`, `ReadLedger`) keep their in-memory maps + logic and persist each change as one record through a repo (the `ReadRepo` alone is batch-oriented — one flush, one write). Two backends — `db_file.go` (the historical JSON files, still the zero-dep default, reached via the `Open*(path)` constructors) and `db_sql.go` (one `database/sql` impl over pure-Go drivers: `modernc.org/sqlite` locally, `jackc/pgx` for Postgres/Supabase, portable schema + idempotent migrations + transactional multi-row writes). `web.go`'s `database` config (`{driver:file|sqlite|postgres, dsn}`) selects it; file is default and untouched. `db_conformance_test.go` runs the same service ops against every backend. -`cmd/bdrive/` is a thin cobra CLI over these packages (`login`, `logout`, `init`, `stop`, `sync`, `status`, `log`, `export`, `import`, `url`, `web`, `whoami`, `daemon`, `version` — `mnt`/`umnt`/`remote` are gone; `init` is the front door and `stop` pauses). `export`/`import` (`migrate.go`) move a whole project between hubs with full fidelity: the archive is the remote store layout (all devices' journals + all blobs) in a tar.gz, streamed through the existing `remote.Backend` — no server-side support needed, so it works against any hub in either direction (the anti-lock-in story for cloud-hesitant users). `bdrive login` signs the device in (bare form uses the remembered server or `config.DefaultServer` = beardrive.ai; loopback-callback browser flow in `login.go`, `--device` for headless) and stores server+token+account in `settings.json`; `bdrive logout` clears the saved token+account (keeps the remembered server unless `--forget`). Switching hubs is `bdrive login ` then re-`init` — `init` is the only thing that writes a folder's remote (always a hub, `server + "/p/" + id`); there is no client command to point a folder at a raw bucket. `bdrive init` is interactive on a TTY (survey menus: create-new vs connect-existing with a project list; whole-folder vs only-some-subfolders) with full flag bypass (`--name/--project/--only/--yes`) and never prompts without a TTY; it runs the login flow first when there is no session, writes `.bdrive/config.json`, seeds `.bdriveignore`, registers agent sync hooks in each platform's USER config (`~/.claude/settings.json` and friends — once per machine, never inside a project: platforms read hook config only from the directory a session starts in, so a per-project file covers only sessions that start there and, living in a mount, would sync to the team; `Install` also migrates away hooks older versions wrote into projects) and installs the beardrive skill, and starts sync via `startSync`; re-running it resumes — including after a folder move. **A mount is always exactly the folder named** — there is no re-rooting flag. Syncing only part of a mount is `--only wiki,docs`, which writes a bdrive-managed block of `.bdriveignore` negation rules (`cmd/bdrive/scopefile.go`; `bdrive scope add/rm` edits the same block) rather than a second scope mechanism: the old `Include` list in `config.json` is legacy — still honored, never written. Because the rules live in the synced `.bdriveignore`, scope is team-wide, which is why `sync --prune` refuses when `!` rules are present (it would strip everything outside the scope from the hub for everyone; `bdrive forget ` is the per-path tool). `init` also refuses a second folder for a project this device already syncs — one device writes one journal per project, so two mounts would overwrite each other's ops. `bdrive web -c config.json` configures the server from a file, explicit flags winning. +`cmd/bdrive/` is a thin cobra CLI over these packages (`login`, `logout`, `init`, `stop`, `sync`, `scope`, `forget`, `status`, `log`, `share`, `export`, `import`, `url`, `hooks`, `skill`, `read-log`, `hook-approve`, `web`, `whoami`, `daemon`, `version` — `mnt`/`umnt`/`remote` are gone; `init` is the front door and `stop` pauses). `export`/`import` (`migrate.go`) move a whole project between hubs with full fidelity: the archive is the remote store layout (all devices' journals + all blobs) in a tar.gz, streamed through the existing `remote.Backend` — no server-side support needed, so it works against any hub in either direction (the anti-lock-in story for cloud-hesitant users). `bdrive login` signs the device in (bare form uses the remembered server or `config.DefaultServer` = beardrive.ai; loopback-callback browser flow in `login.go`, `--device` for headless) and stores server+token+account in `settings.json`; `bdrive logout` clears the saved token+account (keeps the remembered server unless `--forget`). Switching hubs is `bdrive login ` then re-`init` — `init` is the only thing that writes a folder's remote (always a hub, `server + "/p/" + id`); there is no client command to point a folder at a raw bucket. `bdrive init` is interactive on a TTY (survey menus: create-new vs connect-existing with a project list; whole-folder vs only-some-subfolders) with full flag bypass (`--name/--project/--only/--yes`) and never prompts without a TTY; it runs the login flow first when there is no session, writes `.bdrive/config.json`, seeds `.bdriveignore`, registers agent sync hooks in each platform's USER config (`~/.claude/settings.json` and friends — once per machine, never inside a project: platforms read hook config only from the directory a session starts in, so a per-project file covers only sessions that start there and, living in a mount, would sync to the team; `Install` also migrates away hooks older versions wrote into projects) and installs the beardrive skill, and starts sync via `startSync`; re-running it resumes — including after a folder move. **A mount is always exactly the folder named** — there is no re-rooting flag. Syncing only part of a mount is `--only wiki,docs`, which writes a bdrive-managed block of `.bdriveignore` negation rules (`cmd/bdrive/scopefile.go`; `bdrive scope add/rm` edits the same block) rather than a second scope mechanism: the old `Include` list in `config.json` is legacy — still honored, never written. Because the rules live in the synced `.bdriveignore`, scope is team-wide, which is why `sync --prune` refuses when `!` rules are present (it would strip everything outside the scope from the hub for everyone; `bdrive forget ` is the per-path tool). `init` also refuses a second folder for a project this device already syncs — one device writes one journal per project, so two mounts would overwrite each other's ops. `bdrive web -c config.json` configures the server from a file, explicit flags winning. Authentication (`webapp/auth.go`, `authlocal.go`, `mail.go`) is **mandatory in hub mode** — the config's `auth` block tunes `users_db`/`allow_signup`/`allowed_domains`/`require_verification`/`require_approval`/`admins`/`smtp`; the plain-folder viewer stays auth-free — and sits behind the `AuthProvider` interface — the OSS server ships only `BuiltinAuth` (email+password accounts and device tokens in a file-backed `auth.json`; bcrypt for passwords, SHA-256 digests for tokens, plaintext never stored; server-owned `/auth/*` pages; one-time codes for the CLI callback and device flows; SMTP reset mail with a log-link fallback). **Signup is invite-only by default** (`allow_signup` defaults false): a valid org invite bootstraps an account even when self-signup is closed — `BuiltinAuth.InviteValid` (wired to `OrgDB.ValidInvite`) lets `pageSignup`/`pageLogin` offer account creation for a `/join/` target, and `signupInvited` skips the domain/verification/approval gates and activates immediately (the invite is the vetting). `BuiltinAuth.ValidateSignupPolicy` (called at hub startup, `web.go`) refuses an ungated open hub and email-verification-without-SMTP rather than silently leaving the door open. The three postures: invite-only (default), approval-gated (`require_approval`), and domain-restricted+verified (`allowed_domains`+`require_verification`+`smtp`); `allow_signup`/`allowed_domains`/`admins` stay server-config-owned so a browser session can't widen access. A managed deployment can swap in a different provider (e.g. PropelAuth) without touching the CLI or API — keep provider-specific code out of this repo. The sync client picks up its token from `BDRIVE_TOKEN` or `settings.json` and sends `X-Bdrive-Device{,-Name,-Os}` headers (`remote/http.go`); the hub's file-backed device registry (`webapp/devices.go`) records per-device name/OS/account/server-observed IP. Journal ops carry the signed-in account (`Op.User`/`UserName` from `Session.Account`; `Author` remains the git/OS fallback). History (`webapp/history.go`): `GET /api/p//history?path=|prefix=` (newest first, device-registry join) and `GET /api/p//blob?sha=` stream any exact version — blobs are retained forever, so the future revert phase is just re-putting an old blob as a new op. Share links (`webapp/shares.go`, file-backed `shares.json`): any signed-in member mints `/s/` public URLs (`bdrive share`, or the UI's Share button) serving the file's LATEST content until revoked (optional expiry); `/s/*` responses are sandboxed (CSP `sandbox allow-scripts`, no auth cookies) so shared HTML can't attack hub sessions — keep that header on any change; `/s/*` also sits behind a per-IP token bucket (`ratelimit.go`, `share_rpm` config), and markdown share pages get a "Shared with BearDrive" footer (raw HTML is never injected into). diff --git a/INSTALL_FOR_AGENTS.md b/INSTALL_FOR_AGENTS.md index 9809aa1..242abda 100644 --- a/INSTALL_FOR_AGENTS.md +++ b/INSTALL_FOR_AGENTS.md @@ -192,7 +192,7 @@ claude plugin update beardrive@beardrive ``` Tell the user the plugin loads on their next session (current session keeps -working via the hooks from step 5). Other platforms: step 2 already covered +working via the hooks from step 4). Other platforms: init already covered you — skip this. ## 6. Verify, then show the payoff diff --git a/README.md b/README.md index 4cc0e93..c933bb2 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,10 @@ agents actually read (and which hot-but-stale docs nobody maintains). $ bdrive login https://your-hub # once per device — self-host a hub in ~10 min (docs/self-hosting.md) $ 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) ``` @@ -138,7 +141,7 @@ hub's own storage, never something a syncing client points at directly: |---|---| | `bdrive login [server-url]` | Sign this device in (browser flow; `--device` forces the code flow, and shells without a TTY fall back to it automatically; default server beardrive.ai — the managed cloud, free personal workspace on signup; pass your hub URL to self-host). Switch hubs with `bdrive login ` | | `bdrive logout` | Sign this device out — clear the saved token/account (`--forget` also drops the remembered server) | -| `bdrive init [folder]` | Create/connect a project and start syncing — the mount is always exactly the folder named. Interactive on a TTY, flags (`--name/--project/--only/--yes`) for scripts; registers agent sync hooks for detected platforms (`--no-hooks` skips); re-run to resume | +| `bdrive init [folder]` | Create/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; installs the agent skill, registers agent sync hooks in each platform's user config (`--no-hooks` skips the hooks), prints the project link; re-run to resume | | `bdrive stop [folder]` | Stop syncing, including agent sync hooks (files stay; `bdrive init` resumes) | | `bdrive scope [add\|rm ]` | Show or change which subfolders sync — edits the managed block of `.bdriveignore` rules that `init --only` writes, so no one hand-writes negation syntax. The daemon picks changes up in seconds; `rm` deletes nothing, locally or on the hub | | `bdrive forget ...` | Stop syncing a path *and* remove it from the hub — adds the rule to `.bdriveignore` (which syncs) and prunes in one step. Local files are never touched, here or on teammates' devices | @@ -162,7 +165,8 @@ Each mounted folder carries its own settings, so configuration travels with the project: - **`.bdrive/`** — the folder's settings directory: `config.json` holds the - **stable mount id** plus project/remote/include settings. Written by + **stable mount id** plus the project and remote (and, on older mounts, a + legacy `include` list — still honored, never written now). Written by `bdrive init`, safe to hand-edit (a running daemon picks changes up automatically). Never synced, and it holds no credentials (the session token stays in `~/.bdrive`). Because everything is keyed by the mount id, @@ -176,7 +180,7 @@ the project: ```jsonc // .bdrive/config.json { "id": "m-5a10b713", "volume": "notes", - "remote": "https://drive.example.com/p/p-7f3a2c91", "include": ["/shared/"] } + "remote": "https://drive.example.com/p/p-7f3a2c91" } ``` Opting out is non-destructive: when a pattern starts matching an @@ -376,8 +380,8 @@ makes agents fluent in all of this, and **`/beardrive:install`** sets a project up conversationally: installs the CLI, signs in, creates or connects a project (whole folder or a shared subfolder like `wiki/`), offers to document the shared folder in CLAUDE.md so agents proactively -put shareable artifacts there, and registers project-level hooks in -`.claude/settings.json` — a blocking pull when you submit a prompt (Claude +put shareable artifacts there, and registers hooks in your user config +(`~/.claude/settings.json`, once per machine) — a blocking pull when you submit a prompt (Claude reads fresh team files) and an async push after every file edit (artifacts are on the server seconds after Claude writes them), for every teammate whether or not they installed the plugin. The payoff: "write a report and @@ -462,8 +466,8 @@ The plugin sets up everything at once: - **`/beardrive:install`** — the full team setup, conversationally: CLI, sign-in, project init (whole folder or a shared subfolder like `wiki/`), a consent-gated agent orientation — a synced `AGENTS.md` mapping the - shared folder plus a repo-root pointer to it — and project-level sync - hooks registered in your user config. + shared folder plus a repo-root pointer to it — and sync hooks registered in + your user config, once per machine. - **`/beardrive:init [folder] [--name/--project/--only]`** — just start syncing a project; `/beardrive:status` diagnoses problems. - **Turn-boundary sync hooks**, registered automatically in your user config @@ -471,6 +475,10 @@ The plugin sets up everything at once: pull when you send a message (Claude always reads fresh files) and an async push when the turn ends. The hook no-ops instantly outside BearDrive projects, which is what makes a machine-wide registration safe. +- **No permission gauntlet** — the plugin auto-approves beardrive's own setup + commands (`init`, `login`, `hooks`, `status`, `sync`, `url`) through a + `PreToolUse` hook, and only as bare invocations: anything with a shell + operator falls through to the normal prompt. - **The `beardrive` skill** ([plugin/skills/beardrive](plugin/skills/beardrive/SKILL.md)), covering init/stop/sync, sharing by URL, backends and credentials, selective sync, and troubleshooting. Working in a clone of this repo @@ -487,9 +495,9 @@ to set up BearDrive project on . Ask me which folder to sy ``` The agent fetches [INSTALL_FOR_AGENTS.md](INSTALL_FOR_AGENTS.md) and follows -it: install the CLI, `bdrive skill install`, device-code sign-in, and -`bdrive init` — which also registers the sync hooks for every detected -agent platform. The instructions live at that URL rather than +it: install the CLI, then one `bdrive init` — which signs in (device code +when there is no browser), installs the skill, registers the sync hooks and +prints the project link. The instructions live at that URL rather than inside the prompt so they never go stale in someone's copy — and the agent handles every deviation (already installed, no Homebrew, sign-in, wrong folder). The skill step is the durable part: `SKILL.md` is a cross-agent @@ -529,8 +537,8 @@ working folder ←materialize/scan→ local volume store ←push/pull→ obj as a conflict-copy file by the device that detects the overlap. - A per-mount **daemon** scans the folder every few seconds (cheap size+mtime check) and exchanges with the remote every ~10s — or - immediately after local edits. Tune with --scan-interval and - --remote-interval on `bdrive init`. + immediately after local edits. Tunable with --scan-interval and + --remote-interval on the daemon (defaults 3s / 10s). ### What beardrive does not sync diff --git a/cmd/bdrive/init.go b/cmd/bdrive/init.go index 047310b..9deeb0b 100644 --- a/cmd/bdrive/init.go +++ b/cmd/bdrive/init.go @@ -97,8 +97,27 @@ the folder was renamed or moved.`, return err } else if ok && proj.Remote != "" { fmt.Printf("resuming %s (project %s)\n", folder, proj.Volume) + // --only on an existing mount narrows it in place: the scope is + // just .bdriveignore rules, so re-running init is a legitimate + // way to set them (and is what `bdrive scope` points at). if cmd.Flags().Changed("only") { - fmt.Println("note: --only is ignored on resume — change what syncs with `bdrive scope add`/`rm`") + scope, err := cleanScopeDirs(only) + if err != nil { + return err + } + for _, dir := range scope { + if err := os.MkdirAll(filepath.Join(folder, filepath.FromSlash(dir)), 0o755); err != nil { + return err + } + } + if err := writeScopeDirs(folder, scope); err != nil { + return err + } + if len(scope) == 0 { + fmt.Println(" syncing: the whole folder (scope rules removed)") + } else { + fmt.Printf(" syncing: ./%s only (rules written to .bdriveignore)\n", strings.Join(scope, ", ./")) + } } installSkill(folder) if !noHooks { diff --git a/plugin/commands/init.md b/plugin/commands/init.md index 383b639..fe27b7c 100644 --- a/plugin/commands/init.md +++ b/plugin/commands/init.md @@ -88,5 +88,5 @@ Follow these steps: teammates connect (invite link → `bdrive init`; the scope rides `.bdriveignore`, so it matches automatically). -For the full team setup (the AGENTS.md orientation + per-project sync -hooks in `.claude/settings.json`), suggest `/beardrive:install` instead. +For the full team setup (the AGENTS.md orientation + the sync hooks init +registers in `~/.claude/settings.json`), suggest `/beardrive:install` instead. diff --git a/plugin/commands/install.md b/plugin/commands/install.md index 630e832..22b06a0 100644 --- a/plugin/commands/install.md +++ b/plugin/commands/install.md @@ -1,5 +1,5 @@ --- -description: Set up BearDrive for this project — install the CLI, sign in, create/connect a project, optionally document the shared folder in CLAUDE.md, and register project-level sync hooks so every teammate's files stay fresh during Claude sessions +description: Set up BearDrive for this project — install the CLI, sign in, create/connect a project, optionally document the shared folder in CLAUDE.md, and register machine-wide sync hooks in your agent's user config so files stay fresh in every session argument-hint: "[project-name] [--only ]" --- diff --git a/plugin/skills/beardrive/SKILL.md b/plugin/skills/beardrive/SKILL.md index ff8ca0d..18515b5 100644 --- a/plugin/skills/beardrive/SKILL.md +++ b/plugin/skills/beardrive/SKILL.md @@ -13,14 +13,15 @@ Use this skill whenever the user is working with the `bdrive` CLI: initializing | Action | Command | |---|---| -| Start syncing a project (create/connect; the front door) | `bdrive init []` — interactive on a TTY; flags `--name ` / `--project ` / `--only ` (comma-separated) / `--yes` for scripts and agents. **The mount is always exactly the folder named** — `bdrive init wiki` makes ./wiki the project, whose contents are the project's contents (NEVER prompts without a TTY). Re-run to resume, including after the folder was renamed/moved. Runs the login flow first (against your hub URL) if the device has no session, and registers agent sync hooks for detected platforms (`--no-hooks` skips). | +| Start syncing a project (create/connect; the front door) | `bdrive init []` — interactive on a TTY; flags `--name ` / `--project ` / `--server ` (sign in there if this device has no session) / `--only ` (comma-separated) / `--yes` for scripts and agents. **The mount is always exactly the folder named** — `bdrive init wiki` makes ./wiki the project, whose contents are the project's contents (NEVER prompts without a TTY). Re-run to resume, including after the folder was renamed/moved. Runs the login flow first if the device has no session, installs the beardrive skill, registers agent sync hooks in each platform's USER config (`--no-hooks` skips the hooks only), and prints the project's hub link — one command, so setup costs one permission prompt. | | Run the daemon in the foreground | `bdrive init -f` | | Stop syncing | `bdrive stop []` — pauses daemon *and* agent hooks; `bdrive init` resumes (`--forget` also unregisters) | | Show/change which subfolders sync | `bdrive scope` / `bdrive scope add ` / `bdrive scope rm ` — edits the managed block of `.bdriveignore` rules that `init --only` writes (run from the mount root; never hand-write the negation syntax). The daemon applies it within seconds. `rm` stops syncing a folder but deletes nothing, locally or on the hub; removing the last entry is refused (that would flip to whole-folder sync — use `bdrive stop` instead) | -| One sync cycle now | `bdrive sync []` — `--note ` stamps session context; `--prune` also removes from the hub whatever `.bdriveignore` now excludes (see below); `--hook