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