Files
beads/examples/library-usage/main.go
beads/crew/dave b362b36824 feat: add session_id field to issue close/update mutations (bd-tksk)
Adds closed_by_session tracking for entity CV building per Gas Town
decision 009-session-events-architecture.md.

Changes:
- Add ClosedBySession field to Issue struct
- Add closed_by_session column to issues table (migration 034)
- Add --session flag to bd close command
- Support CLAUDE_SESSION_ID env var as fallback
- Add --session flag to bd update for status=closed
- Display closed_by_session in bd show output
- Update Storage interface to include session parameter in CloseIssue

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Executed-By: beads/crew/dave
Rig: beads
Role: crew
2025-12-31 13:14:15 -08:00

130 lines
3.8 KiB
Go

// Package main demonstrates using Beads as a Go library
//
// This example shows how an external project (like VC) can import and use
// Beads programmatically instead of spawning CLI processes.
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/steveyegge/beads/internal/beads"
)
func main() {
ctx := context.Background()
// Find the Beads database (looks for .beads/*.db in current/parent dirs)
dbPath := beads.FindDatabasePath()
if dbPath == "" {
log.Fatal("No Beads database found. Run 'bd init' first.")
}
fmt.Printf("Using database: %s\n\n", dbPath)
// Open the database
store, err := beads.NewSQLiteStorage(dbPath)
if err != nil {
log.Fatalf("Failed to open storage: %v", err)
}
defer store.Close()
// Example 1: Get ready work
fmt.Println("=== Ready Work ===")
ready, err := store.GetReadyWork(ctx, beads.WorkFilter{
Status: beads.StatusOpen,
Limit: 5,
})
if err != nil {
log.Fatalf("Failed to get ready work: %v", err)
}
for _, issue := range ready {
fmt.Printf("- %s: %s (priority %d)\n", issue.ID, issue.Title, issue.Priority)
}
// Example 2: Create an issue
fmt.Println("\n=== Creating Issue ===")
newIssue := &beads.Issue{
ID: "", // Empty = auto-generate
Title: "Example library-created issue",
Description: "This issue was created programmatically using Beads as a library",
Status: beads.StatusOpen,
Priority: 2,
IssueType: beads.TypeTask,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
if err := store.CreateIssue(ctx, newIssue, "library-example"); err != nil {
log.Fatalf("Failed to create issue: %v", err)
}
fmt.Printf("Created issue: %s\n", newIssue.ID)
// Example 3: Add a dependency
fmt.Println("\n=== Adding Dependency ===")
dep := &beads.Dependency{
IssueID: newIssue.ID,
DependsOnID: "bd-1", // Assumes bd-1 exists
Type: beads.DepDiscoveredFrom,
CreatedAt: time.Now(),
CreatedBy: "library-example",
}
if err := store.AddDependency(ctx, dep, "library-example"); err != nil {
// Don't fail if bd-1 doesn't exist
fmt.Printf("Note: Could not add dependency (bd-1 may not exist): %v\n", err)
} else {
fmt.Printf("Added dependency: %s discovered-from bd-1\n", newIssue.ID)
}
// Example 4: Add a label
fmt.Println("\n=== Adding Label ===")
if err := store.AddLabel(ctx, newIssue.ID, "library-usage", "library-example"); err != nil {
log.Fatalf("Failed to add label: %v", err)
}
fmt.Printf("Added label 'library-usage' to %s\n", newIssue.ID)
// Example 5: Add a comment
fmt.Println("\n=== Adding Comment ===")
comment, err := store.AddIssueComment(ctx, newIssue.ID, "library-example", "This is a programmatic comment")
if err != nil {
log.Fatalf("Failed to add comment: %v", err)
}
fmt.Printf("Added comment #%d\n", comment.ID)
// Example 6: Update issue status
fmt.Println("\n=== Updating Status ===")
updates := map[string]interface{}{
"status": beads.StatusInProgress,
}
if err := store.UpdateIssue(ctx, newIssue.ID, updates, "library-example"); err != nil {
log.Fatalf("Failed to update issue: %v", err)
}
fmt.Printf("Updated %s status to in_progress\n", newIssue.ID)
// Example 7: Get statistics
fmt.Println("\n=== Statistics ===")
stats, err := store.GetStatistics(ctx)
if err != nil {
log.Fatalf("Failed to get statistics: %v", err)
}
fmt.Printf("Total issues: %d\n", stats.TotalIssues)
fmt.Printf("Open: %d | In Progress: %d | Closed: %d | Blocked: %d | Ready: %d\n",
stats.OpenIssues, stats.InProgressIssues, stats.ClosedIssues,
stats.BlockedIssues, stats.ReadyIssues)
// Example 8: Close the issue
fmt.Println("\n=== Closing Issue ===")
if err := store.CloseIssue(ctx, newIssue.ID, "Completed demo", "library-example", ""); err != nil {
log.Fatalf("Failed to close issue: %v", err)
}
fmt.Printf("Closed issue %s\n", newIssue.ID)
fmt.Println("\n✅ Library usage demo complete!")
}