go install github.com/runbear-io/beardrive/cmd/bdrive@latest skips the
release ldflags, so every module-built binary claimed to be 0.1.0-dev —
useless in beta bug reports. Fall back to the module version Go stamps
into the binary (debug.ReadBuildInfo) when ldflags didn't set one.
Found during the BEA-33 fresh-machine quickstart check.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(cli): agent hooks never sync folders this device didn't opt into
The turn hooks decided "this folder is managed" from the mere presence of
.bdrive/config.json — a file designed to travel with the folder. Two holes:
- A config.json arriving via git clone / copied dir made one hook firing
silently mint a device identity, register the mount, create a volume
store, journal the whole folder, and inject the hub-link formula — on a
device that never ran init or login.
- `bdrive stop` only killed the daemon: the next agent turn's
`bdrive sync --hook` resumed a full sync cycle and kept injecting links,
and `stop --forget` was undone within one turn by registry self-heal.
Fix: one gate (`syncBlocked`) in the paths all hooks route through —
sync/sync --hook/read-log now require the mount to already be enrolled in
this device's mounts.json (read without ResolveMount's enrolling
self-heal) and not paused. Hook mode exits silently; plain `bdrive sync`
errors with a `bdrive init` pointer. New per-device paused marker in the
volume dir: set by `bdrive stop`, cleared by `bdrive init` (startSync).
Only init enrolls or resumes; folder moves still self-heal since
enrollment is keyed by mount id, not path.
Docs updated (README, SKILL.md, docs cli reference, CHANGELOG). Tests:
hook/read-log no-op + no-enrollment on unenrolled and paused mounts,
plain-sync refusals, stop→pause→forget regression, paused marker contract.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: architecture-diagram PRs must show before/after excerpts of changed classes
The "Architecture changes" PR section now names exactly what changed and
shows Before and After mermaid excerpts scoped to the affected classes and
their immediate relationships — never the full diagram (Before = merge
base). Convention updated in CLAUDE.md, architecture/README.md, and the
pre-PR hook's reminder text.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: add cli-sync architecture diagram; widen diagram convention to the CLI
architecture/cli-sync.md draws the CLI and sync engine (cmd/bdrive +
internal/{syncer,store,journal,config,daemon,agenthooks}): the Session
cycle over Store/journal/remote, and the command layer with the new
syncBlocked opt-in gate, paused marker, and enrollment ownership. The
pre-PR hook and CLAUDE.md now watch these packages too, so CLI-side
structural changes trigger the before/after-excerpt convention the same
way server changes do.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: full-coverage architecture diagrams — overview, frontend, agentskills
Every application package is now drawn somewhere: overview.md (system
diagram — package map, device↔hub↔storage flow, agent surfaces, and the
private cloud/ repo as an external seam consumer), webapp-frontend.md (the
hub SPA's modules: App/HubApp/VolumeApp/Browser, the in-repo nav/router,
api layer, hooks, components), and agentskills added to cli-sync.md. The
pre-PR hook now watches all of cmd/, internal Go code, and frontend/src
(generated static/ excluded); CLAUDE.md and architecture/README.md state
the coverage rule: every code change lands in exactly one detail diagram's
scope, web/docs and cloud/ deliberately excluded.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: PR bodies start with a TL;DR — max 5 informal one-liners
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The anti-lock-in story for cloud-hesitant users: export a project's
complete store (every device's journal + every blob, i.e. full history
and authorship) into a portable tar.gz, and import it as a fresh project
on any other hub — cloud → self-hosted or back.
The archive is simply the remote store layout plus a manifest, streamed
through the existing remote.Backend, so no server-side support is needed
and it works against every existing hub. Import verifies each blob's
content hash, rejects foreign tar entries, requires an empty target
project, and refuses journal-less archives. Reconnecting devices resume
exactly where they were, because their journals are byte-identical.
Docs: README + SKILL.md command tables, docs-site CLI reference section,
and a new step-by-step reference page (Migrate between hubs).
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* tooling: pre-PR hook keeps architecture/ diagrams honest
PreToolUse(Bash) hook blocks gh pr create when internal/webapp or
internal/remote changed but architecture/ didn't; CLAUDE.md documents the
rule and the '# skip-diagram-check' escape hatch for non-structural changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: bump beardrive-cloud's OSS pin on every merge to main
Each OSS main push commits the new sha to OSS_COMMIT in
runbear-io/beardrive-cloud (CLOUD_BUMP_TOKEN: fine-grained PAT, that repo
only, contents r/w — already set). The bump push runs cloud CI against the
new pin and, only if green, the prod deploy — closing the OSS half of the
CI/CD loop. Rebase-retry loop absorbs racing merges.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
- init -f no longer prints 'daemon now keeps this folder in sync' after
the foreground daemon has exited
- one stdinIsTTY() helper (TTY or Cygwin pty) shared by init's prompt
gate and login's headless fallback — the two sites disagreed on Cygwin
- the daemon drops its remote backend when the device token changes, so
an account switch mid-run reconnects with the new credential instead
of pushing with the old one (httpBackend captures the token at open)
- whoami reports a settings read error instead of claiming 'not signed in'
- self-hosting/authentication and manual/setup-by-hand now describe the
automatic device-code fallback instead of presenting --device as required
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
architecture/ holds mermaid class diagrams of the bdrive web server: the
Server core with its seams (Source, AuthProvider, Directory, QuotaProvider,
remote.Backend) and the MetaStore persistence layer.
Convention (CLAUDE.md): a PR that changes the drawn structure updates the
affected diagram in the same branch and embeds only the changed diagrams'
mermaid blocks in the PR description. A PreToolUse hook on gh pr create
(.claude/hooks/check-arch-diagrams.sh) blocks PR creation when
internal/webapp or internal/remote changed but architecture/ didn't;
override with '# skip-diagram-check' when nothing structural changed.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
BEA-7 launch-critical set from the onboarding audit:
- login: shells without a TTY auto-fall back to the device-code flow
(agents/CI/SSH no longer hang on the browser callback); a failed
browser open also falls back, and the waiting state hints --device
- bdrive --version now works (cobra root Version), same output as
bdrive version
- init prints a next-steps block: daemon auto-sync note, the
'bdrive init --project p-xxx' connect command for teammates,
bdrive log / bdrive share
- authorship: the daemon re-reads settings.json every tick so a
login/logout/account switch is reflected in op authorship instead
of stamping a stale identity forever; whoami now shows the
signed-in account and labels the git/OS author as the signed-out
fallback
Docs updated in README, plugin SKILL.md, and web/docs reference/cli.md.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Root --help still described the retired direct-to-bucket model (S3/GCS as
the sync transport); clients sync only through a hub now. And with
database: sqlite/postgres the hub startup line printed a projects.json
path that is never read — misleading for self-hosters checking where
their metadata lives.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
.dockerignore excluded plugin/, which is now a compiled package
(plugin/embed.go embeds SKILL.md). Add .gcloudignore so source uploads
skip node_modules; anchor /bdrive so cmd/bdrive isn't excluded.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UdqEkKvj4Dc2d718mcV6EY
A fresh hub following docs/self-hosting.md was a locked room: invite-only
(the default) showed "Sign up disabled" with nobody to mint an invite, and
the approval-gated posture stranded the first admin as pending forever.
Emails on the config's admin list are operator-vetted, so they now
activate immediately on signup (any posture), and while the hub has zero
accounts they may sign up even on an invite-only hub. Strangers still
can't take the bootstrap slot, and the door closes after the first
account. Validated end to end from scratch: hub boot → admin signup →
device-code login × 2 devices → init → bidirectional sync → hooks install.
Also adds the missing GitHub Actions CI workflow (build/vet/test on
ubuntu + macos) — the repo previously had no CI at all.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add a job-shaped use-case page for engineering teams whose customer
context lives where coding agents can't see it: sync a context/ folder
into the repo via --shared, gitignore it (one-writer invariant), point
AGENTS.md at it, and run the in→used→back loop. Register it in the
sidebar between team-wiki and company-brain.
Also sharpen team-artifacts' "send a person a link" story — markdown/HTML
render as pages at a URL, member-only vs public links.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sSVdMviADW8pu6sAJ4SfX
The hub already abstracted authentication — AuthProvider, with BuiltinAuth
as the built-in implementation — and then reached around that seam three
times: Accounts() was declared on neither interface, admin.go type-asserted
*BuiltinAuth (five handlers silently degraded to 404/empty under any other
provider), and organizations were not on the seam at all.
That last gap had teeth. A deployment whose identities come from elsewhere
had no way to own its orgs, so the code that did own them wrote into the
hub's OrgDB from the side — and nothing stopped the hub from inventing an
org that the identity system had never heard of. One did: a hub-created org
held every project while the mirrored one sat empty, and no sync path could
see the difference.
Directory (directory.go) is where organizations live now. LocalDirectory
wraps today's OrgDB unchanged — same last-owner protection, same normEmail,
same "o-"+randHex(4) ids, same file/SQL persistence — so a self-hosted hub
behaves exactly as before. A deployment whose orgs are owned elsewhere
implements the same interface, returns ErrManagedElsewhere from the write
half, and the handlers answer 409 with ManageURL. The hub never learns why
a write was refused, only where to send the user.
Two rules shape the interface. Reads are on the request path: Role runs on
every project request, including the /store/* endpoints a device hits every
few seconds with a token that carries no identity claims, so an
implementation backed by a remote system answers from its own cache — and
that cache is its business, not the hub's. Writes are optional, because
"this hub owns its orgs" is a deployment fact, not a code path.
- Server.Orgs *OrgDB becomes Server.Dir Directory: 28 call sites, 8
nil-checks, one writeDirErr helper for the 409 translation.
- /api/orgs gains manage_url per org — the destination of the account
menu's Settings entry. The client follows a link and never branches on
which kind of hub it is talking to.
- Org administration becomes a real route, /orgs/<id>, retiring one of the
two URL-less panels CLAUDE.md grandfathers. When a directory's ManageURL
is not hub-local, the SPA fallback redirects there instead — so a hub that
cannot administer its orgs cannot paint a console whose every control 409s.
- Accounts() moves onto AuthProvider. admin.go's type assertion becomes an
optional AccountApprover, and a provider without one now answers 503
rather than an empty approval queue: "no queue here" and "queue is empty"
are different answers and only one of them was true.
Two reviews drove the rest. The architecture review caught a browser page
load that could delete org members (a display read ran the full membership
reconcile, and a 200 with an empty user list evicted everyone), one write
site that escaped the 409 translation, and a webhook that could wedge an
event stream behind an unappliable event. The design review, over eight
rounds, caught the org page rendering live controls on a hub that cannot
use them, a share link made unrevokable by a long filename, nine keyboard
tab stops parked off-screen behind a closed drawer, and — five separate
times — a fix of mine that looked right in the source and did nothing in
the browser.
Conformance tests run both a writable and a read-only implementation against
one contract; the seat, prune, and out-of-order regressions each have a test
written to fail against the old code.
Sidebar order is now Start here -> Working with agents -> Manual setup
(optional) -> Use cases -> Self-hosting -> Reference -> Concepts.
README and CLAUDE.md carry the group order and the rule for what belongs
in each, so both move with it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
"Is this for me?" was answerable only by reading the guides and doing the
translation yourself. These five pages answer it directly, sit between
Start here and Working with agents, and route out rather than re-teaching
features:
- Share work across your team's agents — a team that doesn't live in a
terminal: Cowork and Claude Code share plugins, so the agent does the
setup and nobody opens a shell.
- Keep a wiki your agents maintain — knowledge written as a side effect
of work; Insights' hot-and-stale quadrant is the maintenance queue.
- Turn a personal brain into a company brain — OKF bundles, gbrain repos,
Obsidian vaults. They are already markdown directories, so there is
nothing to convert.
- Run a personal wiki, publish part of it — history as the point, plus
per-file public links.
- Carry one context across agents and devices — one project, many mounts,
and what actually happens when two machines edit one file.
Titles are job-shaped; the persona is named in the first line and in the
description, which is also the search snippet and the llms.txt line.
The company-brain page is the long one (790 words vs ~400) because it
carries two frictions worth being honest about. gbrain's own team setup
shares a brain through a remote Postgres, an HTTP MCP server, and
per-teammate OAuth with isolation enforced in SQL; file sync plus each
person's local brain skips all of that at small scale, and the page says
what the server still buys you rather than dunking. And privacy does not
map cleanly: gbrain scopes per person, BearDrive's unit of membership is
the project, so a walled boundary is a separate project — stated plainly,
with a table.
Unverified: whether "let one machine run consolidation" matches how
gbrain teams actually work. Written from the docs, not from practice.
Verified: 23 pages build, zero broken internal links, both external
references (Google Cloud's OKF announcement, the gbrain repo) resolve 200.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The sidebar and the homepage disagreed. index.md's "Where to start"
already led with connecting an agent, but the left rail read Install
(brew) -> Quickstart (bdrive login, bdrive init) -> ... -> Connect an
agent, three groups down. Anyone following the rail met the CLI first and
the skill last — the opposite of how the product is meant to be adopted.
The agent page was also filed under guides/, which this repo defines as
agent-workflow docs rather than setup.
Sidebar order is now the recommended path, and that path is agent-first:
Start here what it is -> set up with your agent -> your first hour
Working with agents shared memory, artifacts, read heat, scoping
Manual setup (opt) install the CLI, set up by hand, skills and hooks
Self-hosting / Reference / Concepts unchanged
- start/setup (was guides/connect-an-agent): rewritten as the front door.
Claude Code's plugin, then the one-paste for Codex/Gemini/Hermes, then
what the agent just installed and how to check it.
- start/first-hour (new): the page that was missing — ask for a doc, get
a link back, share it, a teammate's agent picks it up. What success
looks like without a command you have to type.
- manual/skills-and-hooks (new): the mechanics lifted out of the old
onboarding page — per-platform paths, hook events, idempotency,
project-level vs per-user — so the Start page can stay conversational.
- manual/install and manual/setup-by-hand (were start/*): both now open
by saying you probably don't need them, and link back to the agent path.
- index.md leads with "You don't install it — you ask your agent to";
the CLI and hub sentence moves below it.
No `brew install` appears anywhere in Start here. Reference -> CLI stays
exactly where it was: the people most likely to self-host are CLI-first,
and burying it would read as condescending.
Three public URLs moved, so astro.config.mjs declares redirects. Static
builds emit meta-refresh only, so README carries copy-paste 301 rules for
the host — Firebase Hosting and a Cloud Storage + load balancer URL map.
Verified: 18 pages build, zero broken internal links across the built
output, all three redirects resolve. CLAUDE.md and the docs README record
the rule so this doesn't quietly revert.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces the 🐻 emoji standing in for a logo everywhere. The mark is the
letter B built from three rectangles — a rail and two blocks, the same
shape as the product (a spine with volumes hanging off it). One fill, so
`currentColor` themes it in the sidebar, the favicon, and flat ink.
- Web app: <Mark> in shell.tsx replaces the emoji-in-a-gradient-tile
badge; the mark takes the honey and the wordmark takes text colour, so
the accent lands once. #vault-name sets in Jersey 10 at 18px — the face
is condensed, so that measures like 13px of the UI face.
- Auth pages (authlocal.go): server-rendered, so they had their own emoji
logo. Same mark, inline.
- Docs: bear.svg becomes the mark (fixed honey fill — Starlight renders
the logo as <img>, which can't inherit currentColor), and .site-title
sets in Jersey 10. Starlight tints that title with the accent by
default, which put honey on white in light mode and failed contrast;
it now takes --sl-color-white, matching the app.
- Favicon: the mark, as a data URI.
Jersey 10 is SIL OFL and self-hosted in both trees — Vite fingerprints
the app's copy into static/assets/, the docs serve theirs from public/ —
so no surface makes a third-party font request. Licence ships beside each
file. It is deliberately not a design token: tw.css's @theme block is
mirrored by the cloud landing's tokens.css and a drift check fails the
build if they diverge, so the logo face lives in plain CSS.
The cloud landing page carries the same mark and face (separate repo).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds web/docs — the public product documentation, built with Astro +
Starlight and deployed on its own rather than embedded in the binary.
Why a standalone site in the OSS repo, rather than a section of the cloud
landing page:
- Docs change far more often than the binary does. Embedding them would
mean a Go rebuild and redeploy to fix a typo, and would ship a Pagefind
search index inside every self-hoster's install.
- Self-hosting instructions and the CLI reference document the OSS
project, so "edit this page" should resolve to something an outside
contributor can open a PR against.
- Design tokens get easier, not harder: scripts/tokens.mjs generates
src/styles/tokens.gen.css from the @theme block in the hub frontend's
tw.css, so there is one source of truth and nothing to police. (The
cloud landing sits across a module edge and has to keep a *copy*,
guarded by its own check-tokens.mjs.) custom.css maps Starlight's
--sl-color-* onto those tokens and invents no colors of its own.
Content is seeded from README.md, docs/self-hosting.md, and the plugin
skill. Guides deliberately cover agent workflows — connecting an agent,
the two-file AGENTS.md orientation pattern, artifacts and links, read
heat, scoping the folder — rather than re-teaching the CLI, which lives
in Reference.
starlight-llms-txt emits /llms.txt at build. Convention wants that at the
root domain, so beardrive.ai/llms.txt should point here; that redirect
belongs to the cloud landing and is the one cross-repo coordination point
this split introduces.
Claude-Session: https://claude.ai/code/session_018GcqsM6prjdv9rUrhVVEiC
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The landing page sells BearDrive Cloud, so it now lives in the private
cloud module (web/landing, served by the hub at / for signed-out visitors)
instead of this repo. A self-hosted hub should never serve "Start free"
CTAs pointing at our managed service, and marketing for the paid product
doesn't belong in the AGPL tree.
Rebuilt there as an Astro site on the webapp's own design tokens, so the
landing and the app stop drifting apart visually.
Doc pointers updated to the new location.
Claude-Session: https://claude.ai/code/session_01RA5pQH92cxk5SfiYJeTUjK
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Existing tracked docs (self-hosting, assets) stay tracked — README and
the website link them; the ignore only keeps new files local.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- --page-read and --page-app both resolve to 768px (Tailwind md)
- History, folder listings, and the onboarding empty state move to the
default app column; Insights already sat there. Only rendered markdown
keeps read (HTML files keep their wide frame).
- layout.spec.ts repinned first (test-first); 59/59 e2e green
- shell.tsx docstring and stale style.css width comments updated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two changes to the demo data, both driven by how the screenshots read.
Warning triangles were on roughly half the files, which stops meaning
"look here" and starts meaning nothing. Staleness is now ~15% overall, and
correlated with reads rather than uniform: a heavily-read file is far
likelier to be stale, because it's the one everybody trusts and nobody
owns. That puts the red on big cells in the treemap and in the top-right
of the scatter — where the story is — instead of scattering it across a
hundred files nobody opens. Fewer warnings, and the ones left are the ones
worth reading.
The agent fleet goes from four to eight: one per teammate plus shared CI,
which is what a team's coverage matrix actually looks like once everyone
runs their own. Each has a bias (agentBias) toward particular areas, so
the matrix shows agents specialising instead of eight identical rows.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RA5pQH92cxk5SfiYJeTUjK
The demo harness generated files named run-015.md, des-031.md and so on,
with one-line bodies. Screenshots taken from it end up on the website, and
"des-031.md" in a treemap tells a visitor nothing about what BearDrive is
for.
Replaced the generator with a wiki a company would actually have: runbooks,
ADRs with real slugs, dated meeting notes, product and research docs, and
three hand-written documents (q3-findings, incident-response, first-week)
whose markdown renders with headings, tables, code and lists so the file
view is worth screenshotting. Read-heat shaping is unchanged — runbooks are
what the on-call agents live in, research notes are written for humans and
barely read by anything — so the insights views still light up.
Project renamed proj -> acme-wiki to match.
Also dropped the "must never be committed" note: the file has been in the
tree for a while and is genuinely useful for exploring the UI and taking
product screenshots. It still only runs under BDRIVE_MANUAL_SERVE=1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RA5pQH92cxk5SfiYJeTUjK
A design pass over the new tiers found four problems, two of them
introduced by the refactor itself:
- Insights was assigned `wide`, but its charts are viewBox="0 0 720 …"
SVGs at width:100% — a wider column didn't show more, it magnified:
measured 1.67x at 1600px, painting a 10.5px treemap label at 21px,
larger than the page h1. Insights moves back to `app` and .in-chart
caps at its 760px design width. Widening a column must never mean
scaling content up; that line is now written into shell.tsx.
- /install rendered the same ConnectGuide as the project home, but
wrapped in the .onboard card: x=652 w=560 top=186 against home's
x=492 w=880 top=96 — two sidebar items apart, same component, three
different numbers. It renders directly now. .onboard stays what it
is, the empty-state hero card.
- History was `app`, so `.htime { margin-left: auto }` stranded each
timestamp ~600px from its path. It's a listing — same rows as the
folder view — so it belongs in `read` alongside it.
- --hero-top: 10vh is viewport-relative in the wrong direction: 84px on
a 390x844 phone against 80px on a 1280x800 desktop, i.e. the smallest
screen paid the most. Now clamp(32px, 8vh, 88px).
Also fixes the Copy button in the guide's code blocks: it was absolutely
positioned over a scrolling box, so its 72px of reserved padding
scrolled away with the content and the button landed on top of the
command (visible mid-token at 560px and on mobile). The block is a grid
now — code scrolls in its own track, the button can't overlap it.
layout.spec.ts gains three assertions: /install and home render the
guide identically, no chart scales past ~1.0x at 1600, and the tier map
matches the new assignments.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Every route invented its own content column: widths ran 560px to
unbounded (704 / 760 / 860 / 936 / 560), half of them uncentered because
they set max-width with no auto margins, and markdown pages carried the
constraint on #content itself so the 40px gutter came out of the reading
measure — .md text ran 624px against the folder listing's 704px directly
beside it in the tree.
Now there is exactly one primitive:
- #content owns scrolling and the page gutter, never a width.
- <Page width="read|app|wide"> (shell.tsx) owns width and centering, one
per view, driven by CSS tokens --page-read/-app/-wide (704/880/1200).
read = prose + listings, app = structured views, wide = data-dense.
- .markdown goes back to being typography only; the column around it is
.page.read, which also retires the #content.markdown min-width hack.
- Views declare no layout: .guide/.insights/.history/.admin/.dirlist/
.markdown lost their max-widths, Browser picks the width per route.
- Short centered states (empty, loading, not-found, no-preview, onboard)
shared one --hero-top instead of 8/12/15/22vh apiece.
Insights moves to wide — its treemap and coverage matrix were cramped at
760. Everything else lines up: app pages at 880, read pages at 704, same
edges on every route.
e2e/layout.spec.ts locks it in: one .page per route, widths resolve to
the tokens, same-width routes share edges, #content never constrains
width, and no view re-declares a column inside .page.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The hub's install guide told Codex and Hermes users to run four CLI
commands by hand, and the one people skipped — `bdrive hooks install` —
is exactly the one that makes files sync at turn boundaries. Hand the
setup to the agent instead, the way the Claude tab hands it to the
plugin.
- `bdrive skill install` (internal/agentskills, plugin/embed.go): the
binary now carries the beardrive skill and writes it to any agent that
reads SKILL.md — ~/.{claude,codex,gemini,hermes}/skills/beardrive/.
User-level on purpose: the skill is about the CLI, not one folder, and
a synced project folder should never carry it. Idempotent; refreshes a
stale copy after a CLI upgrade. Bare `bdrive skill` prints the table,
mirroring `bdrive hooks`.
- Guide's Codex/Hermes tabs are now a single paste, no terminal: the
prompt has the agent install the CLI, keep the skill, sign in, init,
and register hooks. The commands ride inside the prompt because these
agents ship no BearDrive knowledge (Claude's tab is terse only because
the plugin carries it). `login --device` there — a browser-callback
sign-in is invisible to an agent mid-turn, while the device flow gives
it a code and URL to relay. Plain commands live on in an "or run it
yourself" fallback.
- Docs realigned: README, SKILL.md, /beardrive:install, self-hosting.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Members and shares-audit render through @tanstack/react-table (sortable,
spec-first); org rename, hub signup policy, and onboarding create/join are
react-hook-form + zod with inline errors replacing toast-on-typo. 55/55.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
Only the visible window renders (collapsed subtrees not at all — the ~5k-file
DOM cliff from the CTO review is gone). Flat rows keep data-path/.active
contract, nesting guide lines, mobile 44px rows; scroll-into-view moves into
FileTree via scrollToIndex. Fold behavior pinned by spec first. 54/54.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
On /insights/<path> and /history/<path> the tree highlights (and unfolds to)
the target; Dashboard/History menu items light up only for their root,
project-wide views. 50/50 e2e.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
Icon-only trigger in the vault header (Linear-style); a tiny search.ts
emitter asks Browser's palette to open — no plumbing through the shell.
Custom tooltip card (label + kbd chip, arrow) on hover/focus. Topbar search
and its centered styles removed. 47/47 e2e incl. header-trigger spec.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
- search control sits centered in the topbar at ~2x width, kbd right-aligned
(static again on mobile)
- Share is icon-only
- History button shows only on the project home: gone from dashboard/history
(and other view routes) and whenever a file/folder is selected — the ⋯
menu and sidebar carry it
- Download is ⋯-menu-only; a hidden anchor keeps the browser download flow
46/46 e2e.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
/<pid>/install and /<pid>/settings join /insights and /history as view
routes — deep links, reload, and back/forward work; the sidebar menu
navigates instead of toggling panel state. Rule recorded in CLAUDE.md:
new surfaces are view routes, never URL-less panels (org/hub admin panels
are the legacy exceptions). 46/46 e2e incl. deep-link spec.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
Panels are not routes: navigating to the already-current /insights URL never
changes pathname, so the route-change effect couldn't close the open panel.
Menu Dashboard (and the ⋯ Insights entry) now close the panel explicitly.
Regression spec added; 46/46.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
Under the project dropdown: Dashboard (project insights), Installation
(connect guide, moved out of Settings), Settings (project facts). Active
states follow the open view/panel; the inline gear next to the dropdown is
gone. 46/46 e2e.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
The ⋯ menu's Insights opens /insights/<current path>: a folder scopes the
treemap/scatter/hot-path/agent-coverage to its subtree, a file to itself;
crumb and title show the scope. urlForView now carries targets for insights
like it did for history. 45/45 e2e.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
Topbar button, ⋯ menu entry, palette action, hidden file input, and the
upload plumbing (upload.ts) are gone; the server upload API stays (devices
and the store proxy depend on it). Spec reworked to seed via API and assert
the affordance is absent. 44/44 green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
- header is the brand only (BearDrive), linking home
- Projects section is a dropdown (native select, styled) with the project
mark, plus the project-settings gear beside it and + to create
- sidebar footer is the account row (avatar, name, email) opening a popover:
Organization → <org> Settings, Hub → Signup & access (admins), Account →
Log out (danger red)
- volume mode unchanged (sign-out stays in its header)
- Playwright suite reworked for the new layout — 44/44 green; static rebuilt
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
Design feedback applied:
- icons are lucide-react (lucide.dev) behind the existing <Icon name> API;
the inline SVG sprite is gone
- org bar (sidebar footer): the Manage text button is a gear icon opening
the org admin panel; sign-out moved here, after the gear
- header: the org-manage (people) button is removed; the header gear now
opens a new per-PROJECT settings panel (identity facts + connect guide);
sign-out stays in the header only when no project/org bar is present
(volume mode, loading, empty state)
Playwright suite updated and green (44/44); static/ rebuilt.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
From the first agent-conversation e2e against a live hub:
- install.md: git handoff for tracked knowledge folders (one transport per
folder), .bdrive//.bdriveignore git guidance, Hermes per-user hook warning,
drop stale share--list aside
- SKILL.md: .bdriveignore is local-only on --shared mounts (root file sits
outside the include list) — doc now matches behavior
- new project skill .claude/skills/onboarding-e2e: reusable procedure to
re-run the conversation-level e2e (staging, instruction materialization,
agent prompt contract, verification, pass bar)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
bdrive log preferred Op.Author (git/OS identity) even when the op carried the
hub account (Op.User/UserName), so team history showed local git emails.
Found by the agent-onboarding live e2e: device signed in as e2e-bot showed
snow@runbear.io in log. Now: UserName → User → Author. bdrive status likewise
shows 'signed in as Name <email>' when a session exists.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
- login copy across README/skill/commands: bare `bdrive login` (BearDrive
Cloud) is the default; signup auto-creates a free personal workspace,
pending invites route into the team; self-hosted hubs pass a URL
- init flows propose a detected knowledge folder (wiki/docs/notes/handbook/
vault) as --shared instead of asking open-endedly; repo-root rule restated
- install always ends by handing the user a `bdrive url` link to a
representative page — the activation moment
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
Two viewer features plus the security fix the second one surfaced:
- Missing file/folder paths now get a not-found view: the path, and the
hint that a just-created file may still be uploading or syncing from a
teammate's device — the tree polls every few seconds so it appears on
its own, plus a Check again button that refetches immediately. The
topbar's share/download actions no longer show for nonexistent files.
- Opening an .html file renders it as a page (sandboxed iframe,
allow-scripts only) instead of showing source text.
- SECURITY: /api/file was already serving synced HTML inline as
text/html on the hub origin with session cookies — a stored-XSS
surface reachable by direct navigation, previously masked only by the
viewer showing HTML as text. Inline HTML and SVG responses now carry
'Content-Security-Policy: sandbox allow-scripts' (the same wall as
/s/* share pages); downloads are exempt (attachments never execute in
the hub origin).
Tests: Go CSP-header matrix (html/svg sandboxed, md clean, download
exempt); e2e: sandboxed-iframe rendering incl. in-frame content + CSP
assertion, and the not-found → late-upload → Check again flow. 44 specs
green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Field report follow-up: an agent with a stale skill copy couldn't find
the gated URL after creating a file. Instructions rot; hook output is
computed fresh from the binary every turn. Claude Code's turn-start
pull hook now runs 'bdrive sync --hook claude-code', which:
- pulls as before, and stamps the session note from the event JSON
(replacing the sh/sed pipeline for the pull leg)
- emits the project's gated-link formula as UserPromptSubmit
additionalContext: whenever the agent mentions a synced file path in
prose, it appends the hub link on an emoji — `<path>` [🔗](<url>) —
path plain (it's the local path), hyperlink on the emoji only; code
blocks stay plain; bdrive share stays explicit-opt-in-public
Blind-tested: an agent given only the injected context decorated every
path mention correctly, kept the code-block command plain, and checked
files were synced before linking.
- hooks install now CONVERGES marker-identified groups to the current
shape (command/matcher/flags), so improvements reach existing
projects on reinstall instead of being frozen by the idempotency
marker; hermes same
- plugin: UserPromptSubmit → beardrive-pull.sh (stdout passes through);
version 0.3.0
- SKILL 'Share what you make' generalized to 'Link what you mention'
(URL formula documented for non-Claude platforms); install.md pointer
template updated
Never fails the turn: every error path in --hook mode is a silent
successful exit; offline still emits (links serve online teammates).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
A leading YAML frontmatter block used to render as goldmark's
thematic-break soup (hr + stray text). It now renders as a compact
table: keys in the author's order (yaml.Node, not a map), flat lists
comma-joined, nested values as compact YAML in <code>, everything
HTML-escaped. Anything that isn't a well-formed YAML mapping — mid-doc
fences, unclosed fences, list-shaped or invalid YAML — falls through
and renders exactly as before; empty frontmatter is simply hidden.
Applies everywhere the server renders markdown: the hub viewer and
public share pages, each with theme-matched styling. Matters most for
OKF/gbrain-style frontmattered knowledge bases.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
'Share with the team' must show the product's actual default: the
permission-walled bdrive url viewer link (sign-in + membership), with
the public /s/ link as an explicit opt-in — matching the skill's
'Share what you make' rule shipped in v0.7.0. The old mockup had Claude
minting a public link unasked, contradicting the shipped behavior.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
From the reviewer's focused 'good enough to grow?' pass:
- og:image now points at raw.githubusercontent (resolves today;
beardrive.ai doesn't yet) with width/height so link-preview cards —
the top of a reshare-driven funnel — actually render
- the two real, previously-unused screenshots are embedded: browse.png
(read heat + change feed) under the how-it-works architecture card,
share.png inside the Share-by-URL step — real proof next to the
stylized mockups
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Rounds 5 and 6 both scored 9/8/9/9/8/9 with zero repo-fixable
blocker/major findings — the exit bar (two consecutive passes) is met.
Round 6 truth-verified the loop's copy against the code (commands,
Insights sections, hook platforms, url format — all accurate; zero
fabricated proof). Post-exit optional minors applied: og:image +
twitter card meta on the site, SKILL login-cell waitlist parity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Zero repo-fixable blockers/majors; all four round-4 surfaces verified
fixed. The two optional minors applied: the README command-table login
cell and SKILL's init cell now carry the waitlist-only caveat inline.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Reviewer round 4 (9/6/9/9/7/9) caught that round 3 only fixed the
Quick start: the bare-login default survived in the four highest-
traffic surfaces. All inverted to self-host-first:
- README HERO code block (+ the other-machine one-liner and the
every-other-device shorthand): bdrive login https://your-hub, with
Cloud as a clearly-labeled waitlist callout
- plugin/commands/install.md + init.md step 2: ask for the team's hub
URL; bare 'bdrive login' explicitly flagged as targeting the
not-yet-open Cloud
- SKILL.md walkthrough step 1 + the hub-example comment
- website hero terminal animation: 'syncing → your team's hub', share
URL on a neutral acme-hub.example host (og:url and the coming-soon
card untouched — those are honest)
- README's login reference sentence now says the beardrive.ai default
is waitlist-only
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Reviewer round 3 (9/7/9/8/7/9) caught the sharpest truth bug yet: the
README quickstart's bare 'bdrive login' defaults to beardrive.ai, which
is waitlist-only and not accepting logins — a launch-day visitor's
first command would fail silently. Fixes:
- quickstart step 1 now routes to self-hosting ('bdrive login
https://your-hub', ~10-minute guide linked) with Cloud honestly
framed as waitlist; website closer promises 'Self-host in one
binary' instead of 'under a minute, done'
- handoff gains a P0 gate: verify the FULL first run (login → init →
edit → log) against a working hub before any launch; bare 'bdrive
login' must not be advertised until Cloud accepts logins
- handoff: seed 3-5 good-first-issues (CONTRIBUTING promises them);
replace the mailto waitlist with a real form before Product Hunt
- README trimmed 583→524 lines: the Authentication and Choosing-a-
database operator reference moved verbatim into docs/self-hosting.md
with a compact pointer left behind
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Reviewer round 2 scored 8/7/9/8/8/8 with one repo-fixable major left:
three deeper website spots (storage strip, architecture card, bring-
your-own-storage card) still implied a hub-less direct-to-bucket mode
that v0.3.0 removed — all rewritten to the hub-on-your-storage reality;
themes-preview.html's five retracted 'no server required' strings fixed.
Also: install-path verification added to the handoff P0 and the launch
prep checklist (a 404 brew tap on launch day is fatal); README
credentials table now says the s3/gs/file rows are hub-operator storage,
never client remotes; the agent promise now leads on both README and
website (people-sharing supports it); share.png re-captured against a
real rendered runbook (headings/table/code) instead of a one-line stub.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
GTM reviewer round 1 (baseline: positioning 6, funnel 4, open-paid 8,
community 3, launch 3, metrics 2; 3 blockers + 3 majors, all repo-fixable):
- TRUTH: removed the false 'no server required' claim (x3 on the
website) and stale 'S3/GCS directly' sync claims in both plugin
manifests — hub-only since v0.3.0
- POSITIONING: one line everywhere ('the open-source Google Drive for
AI agents' + the attribution/read-analytics wedge) across README,
website, marketplace.json, plugin.json, SKILL.md; third 'Why' card
and AGPL-why rationale; nav CTA → Star on GitHub
- COMMUNITY: CONTRIBUTING.md, issue forms + PR template, public dated
ROADMAP.md, CHANGELOG.md seeded from all 8 releases
- DEMO ASSETS: real product screenshots captured from the seeded demo
hub (Insights treemap, browse-with-heat, public share page) embedded
in README + website — no fabricated content anywhere
- DOCS: self-hosting quickstart, metrics plan (north star: active
shared brains), launch-plan drafts (Show HN/PH/launch week), and
docs/gtm-handoff.md — the prioritized external-action checklist
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Web-researched persona: a maintainer-turned-managed-cloud-GM grounded in
the a16z three-fits framework (project-community -> product-market ->
value-market), the Supabase/PostHog-era playbooks (positioning-as-
unlock, launch weeks, generous-free-tier PLG, docs-as-marketing), and
COSS failure modes (rug-pull relicensing, resented open-core lines).
Reviews README/website/plugin/docs as funnel surfaces plus the AGPL +
managed-service line, scores six dimensions with evidence, and returns
a stage verdict, replacement copy, and a 30/60/90 plan.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
New command printing a file's hub viewer URL: sign-in + project-org
membership required to open (the internal counterpart to bdrive share's
public links). Computed locally from the mount config — hub origin +
project id from the remote, path segments percent-encoded with literal
slashes; unsynced paths (ignored, or outside a --shared scope) are
refused so nobody gets handed a 404. --sync pushes first so a
just-created file's link resolves immediately; no arg = project home.
The plugin docs now instruct agents to include this link in their reply
whenever they create a shareable artifact (.md/.html/.csv/...) in the
shared folder, reserving bdrive share for people outside the hub:
SKILL.md command map + 'Share what you make' guidance, install.md root
pointer template + payoff step, README, CLAUDE.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Desktop right-aligns Search/Share/⋯ via #meta's flex:1 spacer, but the
mobile styles hide #meta — nothing absorbed the middle space, so the
buttons sat next to the breadcrumb mid-bar (user-reported). On <=900px
the crumb is now the spacer. Verified at 390px: ⋯ right edge at 382/390.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Rounds 4 and 5 both scored every category >=8 with zero high-severity
findings — the exit bar (two consecutive passing designer rounds) is
met. Post-exit cleanup: restore id=search-btn dropped in the React port
so the existing mobile rule hiding the ⌘K badge matches again. Two
remaining observations recorded as won't-fix in the spec with reasons.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Designer round 4: all categories >=8, zero high or medium findings, all
seven round-3 fixes confirmed with measurements. Residual lows fixed for
the confirmation round: insights lens chips, guide tabs, and modal text
inputs to 44px on mobile; at <=430px the share dialog's destructive
Revoke takes its own row instead of sitting 9px from Done.
All responsive CSS on the same URLs — no mobile-specific routes.
42 e2e specs green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Designer round 3 FAILED the bar (6/6/7/9/6, one high) — it caught a
regression my round-2 fix introduced: .ai-main { overflow-wrap:anywhere }
let flex min-content collapse invite/share URL rows to one character per
line at 360/390 (496px-tall rows). Streak reset. Fixes:
- H1: on mobile the admin row's name/URL takes the full row
(flex-basis 100%; controls drop below) and break-word replaces
anywhere, so URLs wrap readably at natural break points
- M1: onboarding inputs collapsed to 18px (.ob-row goes column on
mobile, so flex:1 became flex-basis:0) — now flex:none, 44px
- L1: overflow-menu items 44px; L2: server auth pages get 44px
inputs/buttons at <=900px; L4: .markdown gets width:100% so short
docs stop shrink-to-content floating; L5: .hmeta centers so the
size stays attached when the author line wraps
go build/vet/test green; 42 e2e specs green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Designer round 2: layout 9 / readability 8 / tap-targets 8 /
navigation 9 / polish 8, zero high or medium findings; every round-1
fix confirmed with measurements (no page-level horizontal scroll on any
of the 24 surface x viewport combinations; desktop 1360 unaffected by
the 900px breakpoint).
Remaining low cosmetics fixed for the confirmation round:
- .hsize never wraps ('67 B' split across lines at 360)
- guide Copy button is a real 44px touch target (code blocks get the
height to hold it), admin selects/buttons 40 -> 44px
- truncated emails/URLs wrap on touch instead of dead-end ellipsis
- history timestamps 12px (11px was borderline on small phones)
42 e2e specs green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Designer round 1 scored layout 5 / readability 7 / tap-targets 6 /
navigation 8 / polish 7, one high finding:
- HIGH: tablet 768 and phone-landscape 844 fell between breakpoints —
full desktop topbar + fixed 264px sidebar overflowed the page
(scrollWidth 849 vs 768). The mobile media query now covers
max-width 900px, giving those widths the off-canvas sidebar and
collapsed topbar.
- MED: admin-row selects (28px) and .ai-btn/.ai-del (27px) bumped to
40px targets on mobile, rows wrap; modal buttons to 44px; share
dialog's destructive Revoke pushed away from Done; Escape now
dismisses the share dialog.
- MED: <=430px drops the verbose .dl-meta so filenames stop truncating.
- LOW: gd-copy gets an opaque backing over scrolling code; compact
nowrap history timestamps; invite/pbtn/palette rows to 44px.
42 e2e specs green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Field report: an agent session read a dozen-plus files via Bash
(grep/cat/tail/find) and Grep, but read heat showed almost nothing —
the read-log hook only matched the native Read tool.
- matchers broadened per platform: claude Read|Grep|Bash, codex
read_file|shell, gemini +search_file_content|run_shell_command,
hermes read_file|grep|bash; plugin hooks.json matches Read|Grep|Bash
- read-log is now tool-aware: shell events mine the command line for
existing files it names (redirect targets and flags excluded), grep
events mine the response for the files the matches came from
(content lines and filename lists), and listing tools (Glob, ls) are
deliberately ignored — seeing a file's name is not reading it
- hooks install upgrades a registered hook's stale matcher in place, so
re-running it after a binary upgrade rolls coverage out to existing
projects instead of being skipped by the idempotency marker
- docs: SKILL.md platform table + read-heat wording, install/init
commands, README command table
Note from the same report, verified not a bug: read-log resolves the
mount via the folder's own .bdrive/config.json (config.ResolveMount),
so a stale duplicate registry entry cannot swallow reads.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
- #root { display: contents } so body's flex layout sees through the
React mount point (main pane was stuck at content width)
- README: Web frontend development section; CLAUDE.md: commands +
webapp description rewritten for the React/Vite reality (committed
dist, check-dist pre-release step, the no-router-library and
no-post-commit-DOM-patching lessons)
- verified: clean git-archive checkout builds with no Node and serves
the React app; visual parity pass across desktop + mobile surfaces;
42 e2e specs green; plugin docs untouched (no frontend internals)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
- org admin: rename, member roles/removal (self marked), project
rename/delete, invite links (create/copy/revoke, uses + expiry),
org-wide public-share audit with revoke; members get a read-only view
- hub settings: verification/approval policy toggles (verification
disabled without SMTP), read-only domains/self-signup/admins, pending
signup queue with approve/deny (count feeds the admin bar)
- panels replace the content pane without becoming routes (classic-app
parity): Browser takes a panel prop, HubApp owns the state and any
navigation closes it
- e2e: 8 admin specs, all mutations self-reverting (42 total green)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
- project home at /<pid>: connect-an-agent guide (Claude plugin flow,
Hermes/Codex CLI tabs, persisted choice, copy buttons, real hub origin
+ project id), with Insights embedded below for admins/org-owners
- Insights: squarified treemap, reads×freshness scatter with danger
quadrant, hot-path list, agent coverage matrix — classic math ported
verbatim into JSX SVG; dedicated /insights route
- history views: whole-project / subtree / per-file feeds with kind tags,
device attribution, expandable linkified session notes
- REPLACED react-router-dom with src/nav.ts (~40-line synchronous history
router): v7 wraps navigation in startTransition, which left the old
view on screen for seconds after the URL changed (flaky navigations,
35KB heavier bundle). Routing semantics are unchanged.
- e2e: 12 new specs porting the original 17 parity checks (34 total,
~13s, stable across repeated runs)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
- FileTree with fold state, lone-root auto-open, reveal-on-deep-link;
folder listings with heat dots and the journals-backed change feed
- FileView: markdown (HTML transformed BEFORE render, link clicks
delegated — React re-applies dangerouslySetInnerHTML markup on
unrelated updates, so post-commit DOM patching loses handlers),
images, text, download card
- breadcrumbs, per-route scroll restoration (location.key memo)
- topbar actions: share dialog (mint/copy/open/revoke), history/upload/
download buttons, ⋯ overflow menu; upload via upload/init direct or
relay path, then tree refresh + open
- ⌘K command palette: fuzzy files/projects/actions with stemming
- e2e: 11 new browse specs (22 total green in ~12s); helpers cache one
session cookie per identity to stay under the 10/min auth rate limit
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
- URL as source of truth: parseRoute/urlForPath/urlForView ported verbatim
(src/router.ts), single catch-all route so encoded slashes survive
- hub shell: project nav with color chips, org bar, admin bar with pending
count, sign-out per session flags; volume shell renders too
- empty-state onboarding (invite paste + create project), /join/<token>
invite accept that survives the login redirect
- toast + modal prompt/confirm primitives (imperative promise API over a
React host, matching the classic behavior)
- e2e: 7 new hub specs (11 total green); harness gains a no-org 'solo'
account to reach the empty state
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
- Vite+React+TypeScript workspace at internal/webapp/frontend; vite build
emits committed assets into internal/webapp/static (the go:embed target),
so plain 'go build' still needs no Node
- style.css and the SVG sprite ported verbatim; boot layer (api/config,
401->login redirect) ported so the auth flow works end to end
- frontend(): content-hashed assets/* now served immutable; index.html
stays no-cache (TestFrontendSPAFallback covers both)
- committed e2e harness (BDRIVE_E2E_SERVE=1, deterministic seeded hub on
:8993) wired as Playwright webServer; 4 shell specs green
- check-dist.sh guards against stale committed build output
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Replace the old "append conventions to CLAUDE.md" step with a two-file
pattern for teaching agents a newly mounted shared folder:
- <shared>/AGENTS.md (synced): the team's single source of truth for the
folder's structure and conventions — scaffolded once by the project
creator, read (never rewritten) by joiners.
- A repo-root AGENTS.md/CLAUDE.md pointer (per machine, not synced): the
awareness/routing layer. Required because discovery differs by
platform — Claude Code and Hermes load nested instruction files lazily
(only after entering the folder), and Codex never discovers them at
all (root→cwd path only).
SKILL.md gains a "Teaching agents the folder" section with the platform
discovery table and a first-contact orientation ritual; /beardrive:install
step 4 and /beardrive:init step 6 now offer both files as separate
consents; install.md step 3 gains the same never-sync-a-repo-root hard
rule init.md already had; README/CLAUDE.md descriptions updated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Pre-existing working-tree edits landed with this batch: SKILL.md and
/beardrive:init gain guidance for gbrain-backed shared folders — elect a
single enrichment owner (everyone else indexes read-only), route member
captures into per-member subtrees, treat conflict copies as the canary
for a second enricher, and follow the owner's pull→import→enrich→write
cycle discipline to avoid silently reverting human edits.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Clicking a project now lands on an index page (/<project-id>) instead of
redirecting to Insights: a tabbed guide for mounting the project locally
and wiring it to a coding agent, with the Insights dashboard embedded
below for admins/org-owners.
- Claude Code & Cowork share one tab guiding through the plugin
(/plugin marketplace add + /beardrive:install with this hub's URL and
the project id pre-filled); Hermes and Codex get the four-step CLI flow
(install, login, init, hooks install) with real copyable commands.
- /<project-id>/insights stays a dedicated deep-linkable route; the
sidebar project name is now a home link.
- Copy buttons, localStorage-persisted tab choice, scroll/back-forward
behavior consistent with the other views.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
- No-flicker polling: tree and heat refreshes compare fetched data and skip
DOM rebuilds when nothing changed; in-place listing re-renders preserve
scroll.
- RESTful routes: /<project>/insights and /<project>/history[/<path>]
replace query-param views; the reserved first segments survive refresh,
deep links, and back/forward. Per-route scroll restore (manual
scrollRestoration) returns the reader to where they were.
- History rows unified: every entry (recent changes and full history) is a
clickable row that opens the file — view/download version links removed;
old versions remain reachable via the blob API until the time-travel
viewer lands. Folder tree loses the per-dir history icon.
- Hot path: danger rows use the amber accent, ⚠ trails the filename, and a
tooltip explains the flag (reads/30d, days unchanged).
- Frontend responses send Cache-Control: no-cache so upgrades never leave
browsers on a stale embedded UI.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
History notes still clamp to one line so the feed stays scannable, but
clicking (or Enter on) the note expands the full text and back — links
inside keep working. Selecting a project now lands admins/org owners on
the Insights dashboard instead of the empty "select a file" pane;
members keep the placeholder, and routes that carry a path still open
that file or folder.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
AgentHeat aggregates agent-kind buckets per device per top-level folder;
the handler joins the device registry (name/OS) and sorts by total. Human
and share buckets are never consulted, so human actor identities cannot
appear in the response — asserted by test, along with registry join, root
folder bucketing, sort order, and invalid-by rejection.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
Insights (admin/org-owner) becomes a stacked dashboard driven by one heat
fetch plus the tree, with the all/human/agent lens applied throughout: a
dependency-free squarified treemap of every file (cell size = reads in the
window, color = staleness, ⚠ on hot+stale, one delegated click handler —
readable at 500+ files, group labels open folders, cells open files); the
reads×freshness scatter demoted to drill-down with density handling
(translucent dots, radius = agent share); and a hot-path top-20 list with
stacked agent/human bars replacing the plain danger list. The agent
coverage matrix section renders when the server provides the by=device
breakdown. Design addendum recorded in docs/design/read-heatmap.md;
calendar/streamgraph explicitly deferred.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt