180 Commits
Author SHA1 Message Date
9bac355e5d chore: changelog for v0.10.0 (folds in un-changelogged v0.9.0) (#48)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
v0.10.0
2026-07-27 07:13:24 +09:00
11d667a447 fix(cli): report the real version for go-install builds (#47)
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>
2026-07-27 07:11:58 +09:00
Snow W. Lee (Sungwon)andGitHub 379b19a9ec feat(web): delete a project from its Settings page, behind type-the-name (#45) 2026-07-26 15:57:32 +09:00
6628718f1d fix(cli): agent hooks never sync folders this device didn't opt into (#44)
* 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>
2026-07-24 15:53:23 +09:00
4f5f517a6f feat(cli): bdrive export/import — move projects between hubs with full history (#43)
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>
v0.9.0
2026-07-23 19:04:05 -07:00
071e21cd1a ci: auto-bump beardrive-cloud OSS pin on merge; pre-PR diagram hook (#42)
* 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>
2026-07-22 15:24:18 -07:00
220e27a9c2 review fixes: gate init next-steps on background mode, shared stdinIsTTY, daemon reconnects on token change, whoami surfaces settings errors, doc staleness (#41)
- 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>
2026-07-22 15:23:56 -07:00
2b9beaf41a docs: architecture class diagrams + keep-updated-in-PRs workflow (#40)
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>
2026-07-22 15:23:18 -07:00
34afef17cc fix(cli): onboarding friction — headless login fallback, --version, init next steps, labeled authorship (#39)
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>
2026-07-22 09:35:48 -07:00
Snow LeeandClaude Fable 5 a00f7cd1a9 cli: hub-era help text; don't print unused projects.json path under SQL metadata
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>
2026-07-22 07:52:14 -07:00
Snow LeeandClaude Fable 5 1de5fb1633 build: fix Docker/Cloud Run source deploy ignores
.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
2026-07-21 23:51:20 -07:00
Snow LeeandClaude Fable 5 623da892d2 fix(auth): first-account bootstrap — admin emails activate on signup; add CI
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>
2026-07-21 23:24:25 -07:00
Snow LeeandClaude Opus 4.8 16210f3236 docs: use case — give coding agents the business context
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
2026-07-21 23:14:36 -07:00
Snow Lee dfef5720df webapp: organizations behind a Directory seam
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.
2026-07-20 03:06:19 -07:00
Snow LeeandClaude Opus 4.8 93f2c6bc84 docs: move Use cases below Manual setup
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>
2026-07-19 22:06:40 -07:00
Snow LeeandClaude Opus 4.8 16ababe37d docs: use cases — five job-shaped pages that route into the guides
"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>
2026-07-19 21:40:00 -07:00
Snow LeeandClaude Opus 4.8 8f239dfae4 docs: reorganize around the agent path, CLI becomes optional
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>
2026-07-19 20:52:20 -07:00
Snow LeeandClaude Opus 4.8 25f890c03f feat(brand): the Stack mark and Jersey 10 across app, auth, and docs
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>
2026-07-19 19:38:42 -07:00
b10c6f961e docs: a Starlight docs site for docs.beardrive.ai (#38)
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>
2026-07-19 17:29:33 -07:00
19da7dc890 site: move the landing page to the cloud module (#37)
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>
2026-07-19 16:58:45 -07:00
Snow W. Lee (Sungwon)andGitHub d835c18e6b Merge pull request #36 from runbear-io/web/column-md-width
One md-width column for app views; read only for rendered files
2026-07-19 16:38:02 -07:00
Snow LeeandClaude Fable 5 008e765ad5 chore: gitignore /docs/ (private notes) and /.review-shots/
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>
2026-07-19 16:37:40 -07:00
Snow LeeandClaude Fable 5 3f9e465463 refactor(web): one md-width column for app views; read is for rendered files only
- --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>
2026-07-19 16:37:40 -07:00
Snow LeeandClaude Opus 4.8 1b5a422af2 webapp: eight agents in the demo seed, and far less staleness
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
2026-07-19 16:29:41 -07:00
Snow LeeandClaude Opus 4.8 52f595efc0 webapp: seed the demo hub with a realistic wiki
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
2026-07-19 15:28:45 -07:00
Snow LeeandClaude Opus 4.8 afac6bef65 fix(web): design-review fixes to the column system
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>
2026-07-19 15:08:30 -07:00
Snow LeeandClaude Opus 4.8 6cc61292ee refactor(web): one column system for every view
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>
2026-07-19 14:50:38 -07:00
Snow LeeandClaude Opus 4.8 5c6099177b feat: bdrive skill install + one-paste Codex/Hermes setup guide
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>
2026-07-19 14:30:06 -07:00
Snow W. Lee (Sungwon)andGitHub 9c7fc34ac8 Merge pull request #35 from runbear-io/feat/frontend-stack-a
feat(web): Stack A — Tailwind v4 + shadcn/ui re-platform (react-virtual, react-table, RHF+zod, cmdk, sonner)
2026-07-19 14:03:44 -07:00
Snow LeeandClaude Fable 5 7f17c1be98 fix(web): design round-2 polish — mobile 44px vault buttons, uncapped mobile nav, faint informational text, centered mobile Revoke
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 13:49:30 -07:00
Snow LeeandClaude Fable 5 e5aeca675b fix(web): design-review round 1 — overlay double-centering, tree file/dir classes, palette chrome, table cards, AA labels, mobile targets
- translate:none on .modal/#palette (Tailwind v4 translate utility stacked on
  the house transform, shifting every overlay and clipping the palette input)
- virtualized tree rows regain dir/file classes (file rows had fold chevrons)
- palette input: single icon, no shadcn border/ring leak
- members/shares tables wrapped in the .admin-list card vocabulary
- section labels ghost→faint (3.6:1 → 5.75:1 AA); mobile 44px icon buttons,
  projects-section clipping; switcher opens below trigger (popper)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 13:35:11 -07:00
Snow LeeandClaude Fable 5 389c4ba550 fix: drop stray worktree gitlink (gitignore .claude/worktrees/); sonner radius token
CTO review findings 1+4: the agent-worktree gitlink re-staged by add -A would
break --recurse-submodules clones; sonner referenced undefined --radius.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 13:21:09 -07:00
Snow LeeandClaude Fable 5 fad9ae4f6b feat(web): react-table admin tables + RHF/zod forms; docs reflect the Stack A dependency set
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
2026-07-19 13:15:24 -07:00
Snow LeeandClaude Fable 5 2e835d266d feat(web): file tree virtualized with @tanstack/react-virtual
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
2026-07-19 13:08:39 -07:00
Snow LeeandClaude Fable 5 2993049bf4 feat(web): buttons on shadcn Button — house variants (primary/danger/subtle/toolbar) keep the exact look
cva variants map to the existing .pbtn/.danger-btn/.ai-btn/.btn classes, so
style.css owns appearance while shadcn adds focus-ring/disabled plumbing.
Migrated: modals, ShareDialog, EmptyState, Browser topbar. 53/53.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 13:05:13 -07:00
Snow LeeandClaude Fable 5 b7ce76b72e feat(web): palette on cmdk in a Radix Dialog — house fuzzy scorer kept (shouldFilter=false)
cmdk owns keyboard nav/selection/aria; matching, stemming, highlighting and
ordering unchanged. Specs target #palette input (cmdk owns the input id).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 12:57:08 -07:00
Snow LeeandClaude Fable 5 4a4e13f14c feat(web): modals on Radix Dialog — same imperative API, same classes, Radix-owned dismissal
modalPrompt/modalConfirm/ShareDialog render in DialogContent (.modal kept for
specs/styling); Escape pinned by spec first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 12:51:59 -07:00
Snow LeeandClaude Fable 5 cb06737af7 feat(web): project switcher on shadcn Select — specs moved to behavioral contract first
Trigger keeps #project-select + proj-mark; items portal'd with keyboard nav
from Radix; picking navigates (spec: open, both projects listed, pick → URL).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 12:49:19 -07:00
Snow LeeandClaude Fable 5 c1db12e75e feat(web): account menu on Radix DropdownMenu (non-modal for legacy click-through parity)
Ids preserved (#account-btn/#account-menu/#menu-*/#signout); Radix owns
Escape/outside dismissal + focus; dismissal behavior pinned by spec first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 12:47:47 -07:00
Snow LeeandClaude Fable 5 fe8911861c feat(web): search tooltip on Radix (shadcn) — portal'd, house-styled tipcard; provider at root
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 12:39:33 -07:00
Snow LeeandClaude Fable 5 65c4a29bf8 feat(web): toasts on sonner behind the same toast() API; specs pin behavior via expectToast
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 12:37:46 -07:00
Snow LeeandClaude Fable 5 407c443a40 feat(web): Stack A foundation — Tailwind v4 + shadcn/ui wired, zero visual change
Tailwind v4 via @tailwindcss/vite, theme+utilities only (no preflight) so
legacy style.css keeps owning base styles during migration; BearDrive tokens
mapped into @theme incl. shadcn semantic slots (primary=honey, popover=raise…).
shadcn components copied in (button, tooltip, dropdown-menu, dialog, select,
command, sonner, input, label, form, table) with radix-ui/cmdk/sonner/cva;
sonner pinned dark (next-themes dropped). Stack A libs installed:
react-virtual, react-table, react-hook-form + zod. 50/50 e2e unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 12:34:52 -07:00
Snow W. Lee (Sungwon)andGitHub 6826de29ee Merge pull request #34 from runbear-io/feat/nav-lucide-redesign
feat(web): nav redesign — lucide icons, project settings in header, workspace actions in org bar
2026-07-19 11:52:12 -07:00
Snow LeeandClaude Fable 5 703dda4dbd agents: beardrive-cto — architecture/reusability/scalability reviewer for backend + frontend
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 11:49:45 -07:00
Snow LeeandClaude Fable 5 4c59bbc794 fix(web): search tooltip painted under the section border — lift the header's stacking context
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 11:44:59 -07:00
Snow LeeandClaude Fable 5 7ddb211fcf feat(web): scoped insights/history keep the file or folder selected in the tree
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
2026-07-19 11:41:35 -07:00
Snow LeeandClaude Fable 5 d18ad1fa91 test(web): regression specs — ⋯ Insights scopes to the open file and selected folder
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 11:36:56 -07:00
Snow LeeandClaude Fable 5 288b426e82 fix(web): search tooltip clipped by the sidebar edge — right-align it
#sidebar is overflow:hidden; the centered card poked past its right edge.
The tooltip now grows leftward from the button, arrow anchored beneath it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbiaaVM2ACxeRi8ySG9ybc
2026-07-19 11:27:01 -07:00
Snow LeeandClaude Fable 5 3f974d96e4 feat(web): search moves beside the brand in the sidebar header, with a ⌘K hover tooltip
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
2026-07-19 11:24:07 -07:00
Snow LeeandClaude Fable 5 75f2b0bfe9 feat(web): topbar cleanup — centered 2x search, icon-only Share, History/Download into the ⋯ menu
- 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
2026-07-19 11:16:50 -07:00