config

package
v0.15.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2026 License: AGPL-3.0 Imports: 12 Imported by: 0

Documentation

Overview

Package config manages beardrive's global state under the beardrive home directory (default ~/.bdrive, overridable with $BDRIVE_HOME): the device identity and the registry of mounted folders.

Index

Constants

View Source
const DefaultServer = "https://beardrive.ai"

DefaultServer is used wherever a server is needed and none is configured: bare `bdrive login`, and `bdrive init` on a never-logged-in device.

View Source
const ProjectDir = ".bdrive"

ProjectDir is the per-folder settings directory at the mount root. It carries the mount's stable identity, so a project keeps syncing after the folder is renamed or moved — nothing is keyed by the path. It travels with the folder (copy the folder to a new machine and `bdrive init` resumes the same project) but is never synced, and it holds no session credentials — those stay in the bdrive home.

Variables

View Source
var ReservedDirs = map[string]bool{".git": true, ProjectDir: true}

ReservedDirs are directory names BearDrive never syncs, at any depth in a mount: .bdrive is the mount's own identity (syncing it would let one device silently repoint another) and .git carries hook scripts that would run on a teammate's next commit. The rule lives here beside ProjectDir because two packages enforce it — the sync engine on scan and on materialize, the hub on every destination path a client names — and two copies would drift.

Match through ReservedDir, never by indexing this map: the comparison is case-insensitive because BearDrive's primary filesystems (APFS, NTFS) are. An exact-match guard lets ".GIT/hooks/pre-commit" through, and the filesystem then resolves it into the real .git/hooks.

Functions

func AgentConfigDir added in v0.15.0

func AgentConfigDir(name string) bool

AgentConfigDir reports whether a path segment names an agent's configuration directory — the keys of agentHookConfigs — under the same case and trailing-dot folding ReservedDir explains.

It exists for one caller: `bdrive init` refusing such a directory as a MOUNT ROOT. The reserved-path rule only covers segments BELOW a root, so mounting ~/.claude leaves its settings.json a top-level file with no directory segment to match on — along with .credentials.json and every saved session under projects/. Only that direction leaks: a mount that CONTAINS ~/.claude sees .claude/settings.json, reserved at any depth.

Exported here rather than spelled as a literal list in cmd/bdrive for the reason agentHookConfigs' own comment gives: a second copy of that list is how .mcp.json drifted out of it once already.

func AgentHookConfig added in v0.15.0

func AgentHookConfig(p string) bool

AgentHookConfig reports whether a slash-separated path is an agent's project-level hook configuration. See agentHookConfigs.

func Home

func Home() (string, error)

Home returns the beardrive home directory ($BDRIVE_HOME or ~/.bdrive).

func IsMount added in v0.4.0

func IsMount(folder string) bool

IsMount reports whether folder is a BearDrive mount root, i.e. has a .bdrive/config.json — even an unparseable one, so callers that must not treat a mount as plain files (e.g. a parent mount's scanner) stay safe.

func LoadMounts

func LoadMounts() (map[string]MountInfo, error)

LoadMounts returns the mount-ID → mount registry.

func NewMountID

func NewMountID() string

NewMountID mints a stable mount identity.

func ReservedDir added in v0.15.0

func ReservedDir(name string) bool

ReservedDir reports whether a path segment names a reserved directory, under every spelling a filesystem folds onto the same directory.

Case is one such folding (APFS, NTFS). Trailing dots and spaces are another: NTFS and SMB strip them when opening a path, so ".git./hooks/pre-commit" IS .git/hooks/pre-commit there — the same executable-hook plant an exact-match guard let through as ".GIT".

func ReservedName added in v0.15.0

func ReservedName(name string) bool

ReservedName reports whether a bare file name never syncs. Case-insensitive for the same reason as ReservedDir.

func ReservedPath added in v0.15.0

func ReservedPath(p string) bool

ReservedPath reports whether a slash-separated path is one BearDrive never carries: under a reserved directory, named like one, a reserved file name, or an agent's project-level hook config.

func SaveMounts

func SaveMounts(m map[string]MountInfo) error

SaveMounts writes the registry, stamping an identity on any row that has none. Every row written before Dev/Ino existed carries zeros, and the move-vs-copy discriminator is only consulted when a row HAS one — so without this backfill the guard is inert on every mount already enrolled on every machine, which is to say on all of them. The stamp is taken while the recorded path still holds this mount, which is the only moment the answer is unambiguous; a row whose path has already stopped answering is left alone rather than given the identity of whatever is sitting there now.

func SaveSettings

func SaveSettings(s Settings) error

SaveSettings persists the device settings.

func ValidMountID added in v0.15.0

func ValidMountID(id string) bool

ValidMountID reports whether id may be used as a mount identity.

func VolumeDir

func VolumeDir(mountID string) (string, error)

VolumeDir returns the local store dir of a mount, keyed by its stable mount ID (never the folder path — that's what makes renames/moves free).

The id is validated here, where it becomes a path: LoadProject checks the one it reads out of a folder's config, but mounts.json is unmarshalled into a map whose KEYS nothing looks at, and `bdrive resume` — what the login agent runs at every boot — builds this path out of the key. A registry entry is plain JSON in $BDRIVE_HOME that anything running as the user can write.

Types

type Device

type Device struct {
	ID     string `json:"id"`
	Name   string `json:"name"`
	Author string `json:"author"`
}

Device identifies this machine and its operator in journals.

func LoadDevice

func LoadDevice() (Device, error)

LoadDevice loads the device identity, creating one on first use.

type MountInfo

type MountInfo struct {
	Path   string `json:"path"`
	Volume string `json:"volume,omitempty"`
	Remote string `json:"remote,omitempty"`
	// Dev+Ino are the filesystem's identity for Path at the time this row was
	// written. They are what tells a MOVED folder (rename: same inode, new
	// path) from a second folder carrying a copy of the same
	// .bdrive/config.json (new inode). Zero on rows written before this field
	// existed, and on platforms with no such identity; see dirID.
	Dev uint64 `json:"dev,omitempty"`
	Ino uint64 `json:"ino,omitempty"`
}

MountInfo is the registry's view of one mount: where the folder currently lives. The source of truth for identity/settings is the folder's own .bdrive/config.json; the registry only remembers the last-known path (for `bdrive status` and the daemon) and self-heals when the folder moves.

type Project

type Project struct {
	// ID is the stable mount identity (m-xxxxxxxx). The volume store, the
	// daemon, and the registry are keyed by it, never by the folder path.
	ID     string `json:"id"`
	Volume string `json:"volume,omitempty"`
	Remote string `json:"remote,omitempty"`
	// Include optionally narrows what syncs: when non-empty, only paths
	// matching one of these patterns (gitignore-style, same syntax as
	// .bdriveignore) are scanned and materialized.
	Include []string `json:"include,omitempty"`
}

Project holds the settings stored in <folder>/.bdrive/config.json.

func EnrollMount added in v0.15.0

func EnrollMount(folder string) (Project, bool, error)

EnrollMount is ResolveMount plus the one thing ResolveMount refuses to do: create this device's registry row for a project. It is the enrollment gesture, so exactly one caller has any business using it — `bdrive init` (startSync).

func LoadProject

func LoadProject(folder string) (Project, bool, error)

LoadProject reads <folder>/.bdrive/config.json; ok is false if it does not exist.

func ResolveMount

func ResolveMount(folder string) (Project, bool, error)

ResolveMount loads a folder's project settings and self-heals the registry: if the folder was renamed or moved, the registry entry is updated to the new path so `bdrive status` and the daemon find it again.

It never CREATES a row. Enrolling this device in a project is `bdrive init` (EnrollMount) and nothing else: .bdrive/config.json travels with a folder — a clone, an unpacked archive, a colleague's copy — so its presence is not consent to sync, and syncBlocked's "init" arm is the gate that says so. Creating the row here made that gate unreachable for every command that resolves a folder before consulting it (`bdrive restore`, `bdrive forget`): one run inside an attacker-supplied folder put an attacker-chosen remote in the registry, and the login autostart runs `bdrive resume`, which starts a daemon for every enrolled row. A function every folder-taking command calls must not be a write with a read-shaped name.

func SaveProject

func SaveProject(folder string, p Project) (Project, error)

SaveProject writes <folder>/.bdrive/config.json, assigning a mount ID on first save.

type Settings

type Settings struct {
	// Server is the default bdrive web server for `bdrive init`.
	Server string `json:"server,omitempty"`
	// Token authenticates this device to Server (minted by `bdrive login`).
	// Sent as a Bearer header.
	Token string `json:"token,omitempty"`
	// Email and Name identify the signed-in account; journal ops carry them
	// so history shows who changed what.
	Email string `json:"email,omitempty"`
	Name  string `json:"name,omitempty"`
}

Settings are device-wide defaults, stored at $BDRIVE_HOME/settings.json.

func LoadSettings

func LoadSettings() (Settings, error)

LoadSettings reads the device settings; a missing file is zero settings.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL