-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
Problem
There's no per-project way to configure Dolt credentials. This creates a dilemma when you have a mix of local and remote projects:
project-a/ → remote Dolt on VPS (database "app_a")
project-b/ → remote Dolt on VPS (database "app_b")
project-c/ → local embedded Dolt, no remote server at all
If I set BEADS_DOLT_* env vars globally (e.g., in .zshrc), then project-c breaks - it tries to connect to the remote server where no database exists for it, instead of using local embedded Dolt.
If I don't set them globally, then project-a and project-b can't connect to the remote server without external tooling.
Why external tooling doesn't work
direnv / .zshrc functions - only work in interactive terminals. Tools like Claude Code execute each shell command in a separate non-interactive subprocess (/bin/sh -c "..."). The direnv hook (eval "$(direnv hook zsh)") never fires, and .zshrc functions aren't loaded. Same applies to any AI coding agent, CI/CD pipeline, or script that spawns bd as a subprocess.
Shell wrapper script (current workaround) - a bd script in PATH that finds .beads/.env, exports vars, and calls the real binary. Works everywhere but is fragile: breaks on go install updates (overwrites the wrapper), requires manual setup per machine, and adds an indirection layer.
metadata.json - supports dolt_server_host/dolt_server_user but dolt_server_port is deprecated, and password is intentionally env-only (configfile.go:34). Credentials end up split across two config sources.
The common thread: the solution needs to live inside bd itself, not in the shell environment.
Proposed Solution
Auto-load .beads/.env into process environment before any GetDolt*() calls.
Implementation
In PersistentPreRun (cmd/bd/main.go), after beadsDir is resolved (~line 476) but before configfile.Load() (~line 492):
envFile := filepath.Join(beadsDir, ".env")
if _, err := os.Stat(envFile); err == nil {
_ = gotenv.Load(envFile)
}gotenv (github.com/subosio/gotenv) is already an indirect dependency via viper. gotenv.Load() is non-overriding - shell env always wins.
.beads/.env format
BEADS_DOLT_SERVER_HOST=<server-ip>
BEADS_DOLT_SERVER_PORT=3306
BEADS_DOLT_SERVER_USER=<username>
BEADS_DOLT_PASSWORD=<password>
How it solves the problem
project-a/.beads/.envexists → connects to remote serverproject-b/.beads/.envexists → connects to remote serverproject-c/has no.beads/.env→ uses local embedded Dolt (current default, unchanged)
No global env vars needed. No external tools. No shell wrappers. Works in terminals, AI agents, CI/CD, scripts - anywhere bd runs.
Env var precedence (preserved)
shell environment > .beads/.env > metadata.json defaults
Scope limitation
BEADS_DIR in .beads/.env would NOT affect config.yaml discovery (loaded earlier in init() → config.Initialize()). This is acceptable - the primary use case is BEADS_DOLT_* connection params.
Environment
- beads v0.59.0 (dev)
- macOS, multiple projects with mix of local and remote Dolt