Files
beads/examples/library-usage
Abhinav Gupta ac8ef9b9e3 test: replace manual os.Chdir with t.Chdir in tests (#457)
Replaces manual working directory save/restore patterns
with Go's built-in `t.Chdir()` helper across 23 test files.

The manual pattern involved calling `os.Getwd()` to save
the original directory, using `defer os.Chdir(origWd)` for
restoration, and manually handling errors during directory
changes. This boilerplate has been replaced with single
`t.Chdir(path)` calls that handle cleanup automatically.

The `t.Chdir()` method automatically restores the working
directory when the test completes, eliminating the need for
manual defer statements and error handling.

Total:
~75 instances replaced (assuming Claude's math is right)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-04 11:21:43 -08:00
..

Beads Library Usage Example

This example demonstrates using Beads as a Go library in external projects (like VC).

Why Use Beads as a Library?

Instead of spawning bd CLI processes:

  • Direct API access - Call functions directly instead of parsing JSON output
  • Type safety - Compile-time checking of types and interfaces
  • Performance - No process spawn overhead
  • Transactions - Access to database transactions for complex operations
  • Shared database - Multiple components can use same database connection
  • Error handling - Proper Go error types instead of parsing stderr

Installation

In your Go project:

go get github.com/steveyegge/beads@latest

Basic Usage

package main

import (
    "context"
    "log"
    
    "github.com/steveyegge/beads"
)

func main() {
    ctx := context.Background()
    
    // Find and open database
    dbPath := beads.FindDatabasePath()
    store, err := beads.NewSQLiteStorage(dbPath)
    if err != nil {
        log.Fatal(err)
    }
    defer store.Close()
    
    // Get ready work
    ready, err := store.GetReadyWork(ctx, beads.WorkFilter{
        Status: beads.StatusOpen,
        Limit: 10,
    })
    if err != nil {
        log.Fatal(err)
    }
    
    // Process ready issues...
}

Running This Example

# From this directory
cd examples/library-usage

# Make sure there's a Beads database
bd init --prefix demo

# Run the example
go run main.go

Available Operations

The beads.Storage interface provides:

Issues

  • CreateIssue(ctx, issue, actor) - Create a new issue
  • CreateIssues(ctx, issues, actor) - Batch create issues
  • GetIssue(ctx, id) - Get issue by ID
  • UpdateIssue(ctx, id, updates, actor) - Update issue fields
  • CloseIssue(ctx, id, reason, actor) - Close an issue
  • SearchIssues(ctx, query, filter) - Search with filters

Dependencies

  • AddDependency(ctx, dep, actor) - Add dependency between issues
  • RemoveDependency(ctx, issueID, dependsOnID, actor) - Remove dependency
  • GetDependencies(ctx, issueID) - Get what this issue depends on
  • GetDependents(ctx, issueID) - Get what depends on this issue
  • GetDependencyTree(ctx, issueID, maxDepth, showAllPaths) - Visualize tree

Labels

  • AddLabel(ctx, issueID, label, actor) - Add label to issue
  • RemoveLabel(ctx, issueID, label, actor) - Remove label
  • GetLabels(ctx, issueID) - Get all labels for an issue
  • GetIssuesByLabel(ctx, label) - Find issues with label

Ready Work & Blocking

  • GetReadyWork(ctx, filter) - Find issues with no blockers
  • GetBlockedIssues(ctx) - Find blocked issues with blocker info
  • GetEpicsEligibleForClosure(ctx) - Find completable epics

Comments & Events

  • AddIssueComment(ctx, issueID, author, text) - Add comment
  • GetIssueComments(ctx, issueID) - Get all comments
  • GetEvents(ctx, issueID, limit) - Get audit trail

Statistics

  • GetStatistics(ctx) - Get aggregate metrics

Types

All types are exported via the beads package:

// Core types
beads.Issue
beads.Status (Open, InProgress, Closed, Blocked)
beads.IssueType (Bug, Feature, Task, Epic, Chore)
beads.Priority (0-4)

// Relationships
beads.Dependency
beads.DependencyType (Blocks, Related, ParentChild, DiscoveredFrom)

// Metadata
beads.Label
beads.Comment
beads.Event

// Queries
beads.IssueFilter
beads.WorkFilter
beads.BlockedIssue
beads.EpicStatus
beads.Statistics

VC Integration Example

For VC (VibeCoder), the integration would look like:

// In VC's storage layer
type VCStorage struct {
    beads beads.Storage
}

func NewVCStorage(dbPath string) (*VCStorage, error) {
    store, err := beads.NewSQLiteStorage(dbPath)
    if err != nil {
        return nil, err
    }
    
    return &VCStorage{beads: store}, nil
}

// Claim ready work for executor
func (s *VCStorage) ClaimWork(ctx context.Context, executorID string) (*beads.Issue, error) {
    ready, err := s.beads.GetReadyWork(ctx, beads.WorkFilter{
        Status: beads.StatusOpen,
        Limit: 1,
    })
    if err != nil {
        return nil, err
    }
    
    if len(ready) == 0 {
        return nil, nil // No work available
    }
    
    issue := ready[0]
    
    // Claim it
    updates := map[string]interface{}{
        "status": beads.StatusInProgress,
        "assignee": executorID,
    }
    
    if err := s.beads.UpdateIssue(ctx, issue.ID, updates, executorID); err != nil {
        return nil, err
    }
    
    return issue, nil
}

Best Practices

  1. Context - Always pass context.Context for cancellation support
  2. Actor - Provide meaningful actor strings for audit trail
  3. Error handling - Check all errors; database operations can fail
  4. Close - Always defer store.Close() after opening
  5. Transactions - For complex multi-step operations, consider using the underlying database connection directly

See Also