fix(beads): init db for tracked beads after clone (#376)

When a repo with tracked .beads/ is added as a rig, the beads.db file
doesn't exist because it's gitignored. Previously, bd init was only run
if prefix detection succeeded. If there were no issues in issues.jsonl,
detection failed and bd init was never run, causing "Error: no beads
database found" when running bd commands.

Changes:
- Always run bd init when tracked beads exist but db is missing
- Detect prefix from existing issues in issues.jsonl
- Only error on prefix mismatch if user explicitly passed --prefix
- If no issues exist, use the derived/provided prefix

Fixes #72

Co-authored-by: julianknutsen <julianknutsen@users.noreply.github>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Julian Knutsen
2026-01-12 07:03:47 +00:00
committed by GitHub
parent a144c99f46
commit add77eea84
2 changed files with 451 additions and 20 deletions

View File

@@ -232,6 +232,9 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) {
return nil, fmt.Errorf("directory already exists: %s", rigPath)
}
// Track whether user explicitly provided --prefix (before deriving)
userProvidedPrefix := opts.BeadsPrefix != ""
// Derive defaults
if opts.BeadsPrefix == "" {
opts.BeadsPrefix = deriveBeadsPrefix(opts.Name)
@@ -339,35 +342,44 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) {
}
fmt.Printf(" ✓ Created mayor clone\n")
// Check if source repo has .beads/ with its own prefix - if so, use that prefix.
// This ensures we use the project's existing beads database instead of creating a new one.
// Without this, routing would fail when trying to access existing issues because the
// rig config would have a different prefix than what the issues actually use.
sourceBeadsConfig := filepath.Join(mayorRigPath, ".beads", "config.yaml")
if _, err := os.Stat(sourceBeadsConfig); err == nil {
// Check if source repo has tracked .beads/ directory.
// If so, we need to initialize the database (beads.db is gitignored so it doesn't exist after clone).
sourceBeadsDir := filepath.Join(mayorRigPath, ".beads")
sourceBeadsDB := filepath.Join(sourceBeadsDir, "beads.db")
if _, err := os.Stat(sourceBeadsDir); err == nil {
// Tracked beads exist - try to detect prefix from existing issues
sourceBeadsConfig := filepath.Join(sourceBeadsDir, "config.yaml")
if sourcePrefix := detectBeadsPrefixFromConfig(sourceBeadsConfig); sourcePrefix != "" {
fmt.Printf(" Detected existing beads prefix '%s' from source repo\n", sourcePrefix)
// Only error on mismatch if user explicitly provided --prefix
if userProvidedPrefix && opts.BeadsPrefix != sourcePrefix {
return nil, fmt.Errorf("prefix mismatch: source repo uses '%s' but --prefix '%s' was provided; use --prefix %s to match existing issues", sourcePrefix, opts.BeadsPrefix, sourcePrefix)
}
// Use detected prefix (overrides derived prefix)
opts.BeadsPrefix = sourcePrefix
rigConfig.Beads.Prefix = sourcePrefix
// Re-save rig config with detected prefix
if err := m.saveRigConfig(rigPath, rigConfig); err != nil {
return nil, fmt.Errorf("updating rig config with detected prefix: %w", err)
}
// Initialize bd database with the detected prefix.
// beads.db is gitignored so it doesn't exist after clone - we need to create it.
// bd init --prefix will create the database and auto-import from issues.jsonl.
sourceBeadsDB := filepath.Join(mayorRigPath, ".beads", "beads.db")
if _, err := os.Stat(sourceBeadsDB); os.IsNotExist(err) {
cmd := exec.Command("bd", "init", "--prefix", sourcePrefix) // sourcePrefix validated by isValidBeadsPrefix
cmd.Dir = mayorRigPath
if output, err := cmd.CombinedOutput(); err != nil {
fmt.Printf(" Warning: Could not init bd database: %v (%s)\n", err, strings.TrimSpace(string(output)))
}
// Configure custom types for Gas Town (beads v0.46.0+)
configCmd := exec.Command("bd", "config", "set", "types.custom", constants.BeadsCustomTypes)
configCmd.Dir = mayorRigPath
_, _ = configCmd.CombinedOutput() // Ignore errors - older beads don't need this
} else {
// Detection failed (no issues yet) - use derived/provided prefix
fmt.Printf(" Using prefix '%s' for tracked beads (no existing issues to detect from)\n", opts.BeadsPrefix)
}
// Initialize bd database if it doesn't exist.
// beads.db is gitignored so it won't exist after clone - we need to create it.
// bd init --prefix will create the database and auto-import from issues.jsonl.
if _, err := os.Stat(sourceBeadsDB); os.IsNotExist(err) {
cmd := exec.Command("bd", "init", "--prefix", opts.BeadsPrefix) // opts.BeadsPrefix validated earlier
cmd.Dir = mayorRigPath
if output, err := cmd.CombinedOutput(); err != nil {
fmt.Printf(" Warning: Could not init bd database: %v (%s)\n", err, strings.TrimSpace(string(output)))
}
// Configure custom types for Gas Town (beads v0.46.0+)
configCmd := exec.Command("bd", "config", "set", "types.custom", constants.BeadsCustomTypes)
configCmd.Dir = mayorRigPath
_, _ = configCmd.CombinedOutput() // Ignore errors - older beads don't need this
}
}