diff --git a/cmd/bd/setup.go b/cmd/bd/setup.go index 36b2caf1..7bf7321a 100644 --- a/cmd/bd/setup.go +++ b/cmd/bd/setup.go @@ -15,7 +15,7 @@ var ( var setupCmd = &cobra.Command{ Use: "setup", Short: "Setup integration with AI editors", - Long: `Setup integration files for AI editors like Claude Code, Cursor, and Aider.`, + Long: `Setup integration files for AI editors like Claude Code, Cursor, Aider, and Factory.ai Droid.`, } var setupCursorCmd = &cobra.Command{ @@ -66,6 +66,31 @@ must confirm using Aider's /run command.`, }, } +var setupFactoryCmd = &cobra.Command{ + Use: "factory", + Short: "Setup Factory.ai (Droid) integration", + Long: `Install Beads workflow configuration for Factory.ai Droid. + +Creates or updates AGENTS.md with bd workflow instructions. +Factory Droids automatically read AGENTS.md on session start. + +AGENTS.md is the standard format used across AI coding assistants +(Factory, Cursor, Aider, Gemini CLI, Jules, and more).`, + Run: func(cmd *cobra.Command, args []string) { + if setupCheck { + setup.CheckFactory() + return + } + + if setupRemove { + setup.RemoveFactory() + return + } + + setup.InstallFactory() + }, +} + var setupClaudeCmd = &cobra.Command{ Use: "claude", Short: "Setup Claude Code integration", @@ -92,6 +117,9 @@ agents from forgetting bd workflow after context compaction.`, } func init() { + setupFactoryCmd.Flags().BoolVar(&setupCheck, "check", false, "Check if Factory.ai integration is installed") + setupFactoryCmd.Flags().BoolVar(&setupRemove, "remove", false, "Remove bd section from AGENTS.md") + setupClaudeCmd.Flags().BoolVar(&setupProject, "project", false, "Install for this project only (not globally)") setupClaudeCmd.Flags().BoolVar(&setupCheck, "check", false, "Check if Claude integration is installed") setupClaudeCmd.Flags().BoolVar(&setupRemove, "remove", false, "Remove bd hooks from Claude settings") @@ -103,6 +131,7 @@ func init() { setupAiderCmd.Flags().BoolVar(&setupCheck, "check", false, "Check if Aider integration is installed") setupAiderCmd.Flags().BoolVar(&setupRemove, "remove", false, "Remove bd config from Aider") + setupCmd.AddCommand(setupFactoryCmd) setupCmd.AddCommand(setupClaudeCmd) setupCmd.AddCommand(setupCursorCmd) setupCmd.AddCommand(setupAiderCmd) diff --git a/cmd/bd/setup/factory.go b/cmd/bd/setup/factory.go new file mode 100644 index 00000000..0246b685 --- /dev/null +++ b/cmd/bd/setup/factory.go @@ -0,0 +1,298 @@ +package setup + +import ( + "fmt" + "os" + "strings" +) + +// Factory/Droid integration markers for AGENTS.md +const ( + factoryBeginMarker = "" + factoryEndMarker = "" +) + +const factoryBeadsSection = ` +## Issue Tracking with bd (beads) + +**IMPORTANT**: This project uses **bd (beads)** for ALL issue tracking. Do NOT use markdown TODOs, task lists, or other tracking methods. + +### Why bd? + +- Dependency-aware: Track blockers and relationships between issues +- Git-friendly: Auto-syncs to JSONL for version control +- Agent-optimized: JSON output, ready work detection, discovered-from links +- Prevents duplicate tracking systems and confusion + +### Quick Start + +**Check for ready work:** + +` + "```bash" + ` +bd ready --json +` + "```" + ` + +**Create new issues:** + +` + "```bash" + ` +bd create "Issue title" --description="Detailed context" -t bug|feature|task -p 0-4 --json +bd create "Issue title" --description="What this issue is about" -p 1 --deps discovered-from:bd-123 --json +` + "```" + ` + +**Claim and update:** + +` + "```bash" + ` +bd update bd-42 --status in_progress --json +bd update bd-42 --priority 1 --json +` + "```" + ` + +**Complete work:** + +` + "```bash" + ` +bd close bd-42 --reason "Completed" --json +` + "```" + ` + +### Issue Types + +- ` + "`bug`" + ` - Something broken +- ` + "`feature`" + ` - New functionality +- ` + "`task`" + ` - Work item (tests, docs, refactoring) +- ` + "`epic`" + ` - Large feature with subtasks +- ` + "`chore`" + ` - Maintenance (dependencies, tooling) + +### Priorities + +- ` + "`0`" + ` - Critical (security, data loss, broken builds) +- ` + "`1`" + ` - High (major features, important bugs) +- ` + "`2`" + ` - Medium (default, nice-to-have) +- ` + "`3`" + ` - Low (polish, optimization) +- ` + "`4`" + ` - Backlog (future ideas) + +### Workflow for AI Agents + +1. **Check ready work**: ` + "`bd ready`" + ` shows unblocked issues +2. **Claim your task**: ` + "`bd update --status in_progress`" + ` +3. **Work on it**: Implement, test, document +4. **Discover new work?** Create linked issue: + - ` + "`bd create \"Found bug\" --description=\"Details about what was found\" -p 1 --deps discovered-from:`" + ` +5. **Complete**: ` + "`bd close --reason \"Done\"`" + ` + +### Auto-Sync + +bd automatically syncs with git: + +- Exports to ` + "`.beads/issues.jsonl`" + ` after changes (5s debounce) +- Imports from JSONL when newer (e.g., after ` + "`git pull`" + `) +- No manual export/import needed! + +### Important Rules + +- ✅ Use bd for ALL task tracking +- ✅ Always use ` + "`--json`" + ` flag for programmatic use +- ✅ Link discovered work with ` + "`discovered-from`" + ` dependencies +- ✅ Check ` + "`bd ready`" + ` before asking "what should I work on?" +- ❌ Do NOT create markdown TODO lists +- ❌ Do NOT use external issue trackers +- ❌ Do NOT duplicate tracking systems + +For more details, see README.md and docs/QUICKSTART.md. + + +` + +// InstallFactory installs Factory.ai/Droid integration +func InstallFactory() { + agentsPath := "AGENTS.md" + + fmt.Println("Installing Factory.ai (Droid) integration...") + + // Check if AGENTS.md exists + var currentContent string + data, err := os.ReadFile(agentsPath) + if err == nil { + currentContent = string(data) + } else if !os.IsNotExist(err) { + fmt.Fprintf(os.Stderr, "Error: failed to read AGENTS.md: %v\n", err) + os.Exit(1) + } + + // If file exists, check if we already have beads section + if currentContent != "" { + if strings.Contains(currentContent, factoryBeginMarker) { + // Update existing section + newContent := updateBeadsSection(currentContent) + if err := atomicWriteFile(agentsPath, []byte(newContent)); err != nil { + fmt.Fprintf(os.Stderr, "Error: write AGENTS.md: %v\n", err) + os.Exit(1) + } + fmt.Println("✓ Updated existing beads section in AGENTS.md") + } else { + // Append to existing file + newContent := currentContent + "\n\n" + factoryBeadsSection + if err := atomicWriteFile(agentsPath, []byte(newContent)); err != nil { + fmt.Fprintf(os.Stderr, "Error: write AGENTS.md: %v\n", err) + os.Exit(1) + } + fmt.Println("✓ Added beads section to existing AGENTS.md") + } + } else { + // Create new AGENTS.md with template + newContent := createNewAgentsFile() + if err := atomicWriteFile(agentsPath, []byte(newContent)); err != nil { + fmt.Fprintf(os.Stderr, "Error: write AGENTS.md: %v\n", err) + os.Exit(1) + } + fmt.Println("✓ Created new AGENTS.md with beads integration") + } + + fmt.Printf("\n✓ Factory.ai (Droid) integration installed\n") + fmt.Printf(" File: %s\n", agentsPath) + fmt.Println("\nFactory Droid will automatically read AGENTS.md on session start.") + fmt.Println("No additional configuration needed!") +} + +// CheckFactory checks if Factory.ai integration is installed +func CheckFactory() { + agentsPath := "AGENTS.md" + + // Check if AGENTS.md exists + data, err := os.ReadFile(agentsPath) + if os.IsNotExist(err) { + fmt.Println("✗ AGENTS.md not found") + fmt.Println(" Run: bd setup factory") + os.Exit(1) + } else if err != nil { + fmt.Fprintf(os.Stderr, "Error: failed to read AGENTS.md: %v\n", err) + os.Exit(1) + } + + // Check if it contains beads section + content := string(data) + if strings.Contains(content, factoryBeginMarker) { + fmt.Println("✓ Factory.ai integration installed:", agentsPath) + fmt.Println(" Beads section found in AGENTS.md") + } else { + fmt.Println("⚠ AGENTS.md exists but no beads section found") + fmt.Println(" Run: bd setup factory (to add beads section)") + os.Exit(1) + } +} + +// RemoveFactory removes Factory.ai integration +func RemoveFactory() { + agentsPath := "AGENTS.md" + + fmt.Println("Removing Factory.ai (Droid) integration...") + + // Read current content + data, err := os.ReadFile(agentsPath) + if os.IsNotExist(err) { + fmt.Println("No AGENTS.md file found") + return + } else if err != nil { + fmt.Fprintf(os.Stderr, "Error: failed to read AGENTS.md: %v\n", err) + os.Exit(1) + } + + content := string(data) + + // Check if beads section exists + if !strings.Contains(content, factoryBeginMarker) { + fmt.Println("No beads section found in AGENTS.md") + return + } + + // Remove beads section + newContent := removeBeadsSection(content) + + // If file would be empty after removal, delete it + trimmed := strings.TrimSpace(newContent) + if trimmed == "" { + if err := os.Remove(agentsPath); err != nil { + fmt.Fprintf(os.Stderr, "Error: failed to remove AGENTS.md: %v\n", err) + os.Exit(1) + } + fmt.Println("✓ Removed AGENTS.md (file was empty after removing beads section)") + } else { + // Write back modified content + if err := atomicWriteFile(agentsPath, []byte(newContent)); err != nil { + fmt.Fprintf(os.Stderr, "Error: write AGENTS.md: %v\n", err) + os.Exit(1) + } + fmt.Println("✓ Removed beads section from AGENTS.md") + } +} + +// updateBeadsSection replaces the beads section in existing content +func updateBeadsSection(content string) string { + start := strings.Index(content, factoryBeginMarker) + end := strings.Index(content, factoryEndMarker) + + if start == -1 || end == -1 || start > end { + // Markers not found or invalid, append instead + return content + "\n\n" + factoryBeadsSection + } + + // Replace section between markers (including end marker line) + endOfEndMarker := end + len(factoryEndMarker) + // Find the next newline after end marker + nextNewline := strings.Index(content[endOfEndMarker:], "\n") + if nextNewline != -1 { + endOfEndMarker += nextNewline + 1 + } + + return content[:start] + factoryBeadsSection + content[endOfEndMarker:] +} + +// removeBeadsSection removes the beads section from content +func removeBeadsSection(content string) string { + start := strings.Index(content, factoryBeginMarker) + end := strings.Index(content, factoryEndMarker) + + if start == -1 || end == -1 || start > end { + return content + } + + // Find the next newline after end marker + endOfEndMarker := end + len(factoryEndMarker) + nextNewline := strings.Index(content[endOfEndMarker:], "\n") + if nextNewline != -1 { + endOfEndMarker += nextNewline + 1 + } + + // Also remove leading blank lines before the section + trimStart := start + for trimStart > 0 && (content[trimStart-1] == '\n' || content[trimStart-1] == '\r') { + trimStart-- + } + + return content[:trimStart] + content[endOfEndMarker:] +} + +// createNewAgentsFile creates a new AGENTS.md with a basic template +func createNewAgentsFile() string { + return `# Project Instructions for AI Agents + +This file provides instructions and context for AI coding agents working on this project. + +` + factoryBeadsSection + ` + +## Build & Test + +_Add your build and test commands here_ + +` + "```bash" + ` +# Example: +# npm install +# npm test +` + "```" + ` + +## Architecture Overview + +_Add a brief overview of your project architecture_ + +## Conventions & Patterns + +_Add your project-specific conventions here_ +` +} diff --git a/docs/CLI_REFERENCE.md b/docs/CLI_REFERENCE.md index e20a605f..d0df387c 100644 --- a/docs/CLI_REFERENCE.md +++ b/docs/CLI_REFERENCE.md @@ -557,16 +557,19 @@ bd sync # Force immediate sync, bypass debounce ```bash # Setup editor integration (choose based on your editor) +bd setup factory # Factory.ai Droid - creates/updates AGENTS.md (universal standard) bd setup claude # Claude Code - installs SessionStart/PreCompact hooks bd setup cursor # Cursor IDE - creates .cursor/rules/beads.mdc bd setup aider # Aider - creates .aider.conf.yml # Check if integration is installed +bd setup factory --check bd setup claude --check bd setup cursor --check bd setup aider --check # Remove integration +bd setup factory --remove bd setup claude --remove bd setup cursor --remove bd setup aider --remove @@ -580,6 +583,7 @@ bd setup claude --stealth # Use stealth mode (flush only, no git operations) ``` **What each setup does:** +- **Factory.ai** (`bd setup factory`): Creates or updates AGENTS.md with beads workflow instructions (works with multiple AI tools using the AGENTS.md standard) - **Claude Code** (`bd setup claude`): Adds hooks to Claude Code's settings.json that run `bd prime` on SessionStart and PreCompact events - **Cursor** (`bd setup cursor`): Creates `.cursor/rules/beads.mdc` with workflow instructions - **Aider** (`bd setup aider`): Creates `.aider.conf.yml` with bd workflow instructions diff --git a/docs/SETUP.md b/docs/SETUP.md index 320851e9..8bcb11a2 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -5,10 +5,11 @@ ## Overview -The `bd setup` command configures beads integration with AI coding tools. It supports three integrations: +The `bd setup` command configures beads integration with AI coding tools. It supports four integrations: | Tool | Command | Integration Type | |------|---------|-----------------| +| [Factory.ai (Droid)](#factoryai-droid) | `bd setup factory` | AGENTS.md file (universal standard) | | [Claude Code](#claude-code) | `bd setup claude` | SessionStart/PreCompact hooks | | [Cursor IDE](#cursor-ide) | `bd setup cursor` | Rules file (.cursor/rules/beads.mdc) | | [Aider](#aider) | `bd setup aider` | Config file (.aider.conf.yml) | @@ -17,16 +18,107 @@ The `bd setup` command configures beads integration with AI coding tools. It sup ```bash # Install integration for your tool +bd setup factory # For Factory.ai Droid (and other AGENTS.md-compatible tools) bd setup claude # For Claude Code bd setup cursor # For Cursor IDE bd setup aider # For Aider # Verify installation +bd setup factory --check bd setup claude --check bd setup cursor --check bd setup aider --check ``` +## Factory.ai (Droid) + +Factory.ai Droid integration uses the AGENTS.md standard, which is compatible with multiple AI coding assistants. + +### Installation + +```bash +# Create or update AGENTS.md with beads integration +bd setup factory +``` + +### What Gets Installed + +Creates or updates `AGENTS.md` in your project root with: +- Issue tracking workflow instructions +- Quick command reference +- Issue types and priorities +- Auto-sync explanation +- Important rules for AI agents + +The beads section is wrapped in HTML comments (``) for safe updates. + +### AGENTS.md Standard + +AGENTS.md is an industry-standard format for AI coding agent instructions, supported by: +- **Factory.ai Droid** - Specialized coding agents +- **Cursor** - Also reads AGENTS.md (in addition to .cursor/rules) +- **Aider** - Can be configured to read AGENTS.md +- **Gemini CLI** - Google's command-line AI assistant +- **Jules** - Google's coding assistant +- **Codex** - OpenAI's code generation model +- **Zed** - AI-enhanced editor +- And many more emerging tools + +Using AGENTS.md means one configuration file works across your entire AI tool ecosystem. + +### Flags + +| Flag | Description | +|------|-------------| +| `--check` | Check if beads section exists in AGENTS.md | +| `--remove` | Remove beads section from AGENTS.md | + +### Examples + +```bash +# Check if beads section is in AGENTS.md +bd setup factory --check +# Output: ✓ Factory.ai integration installed: AGENTS.md +# Beads section found in AGENTS.md + +# Remove beads section +bd setup factory --remove +``` + +### How It Works + +Factory Droid and other AGENTS.md-compatible tools automatically read `AGENTS.md` from: +1. Current working directory (`./AGENTS.md`) +2. Parent directories up to repo root +3. Personal override (`~/.factory/AGENTS.md`) + +The beads section teaches AI agents: +- To use `bd ready` for finding work +- To use `bd create` for tracking new issues +- To use `bd sync` at session end +- The complete workflow pattern and best practices + +### Updating Existing AGENTS.md + +If you already have an AGENTS.md file with other project instructions: +- `bd setup factory` will **append** the beads section +- Re-running it will **update** the existing beads section (idempotent) +- The markers (``) ensure safe updates + +### When to Use This vs Other Integrations + +**Use Factory integration when:** +- ✅ You use Factory.ai Droid +- ✅ You want one config file for multiple AI tools +- ✅ You prefer the AGENTS.md standard +- ✅ Your team uses multiple AI coding assistants + +**Use other integrations when:** +- ✅ You only use Claude Code → `bd setup claude` (hooks are more dynamic) +- ✅ You need tool-specific features (like Claude's stealth mode) + +You can use multiple integrations simultaneously - they complement each other! + ## Claude Code Claude Code integration uses hooks to automatically inject beads workflow context at session start and before context compaction. @@ -185,22 +277,31 @@ This respects Aider's philosophy of keeping humans in control while still levera ## Comparison -| Feature | Claude Code | Cursor | Aider | -|---------|-------------|--------|-------| -| Command execution | Automatic | Automatic | Manual (/run) | -| Context injection | Hooks | Rules file | Config file | -| Global install | Yes | No (per-project) | No (per-project) | -| Stealth mode | Yes | N/A | N/A | +| Feature | Factory.ai | Claude Code | Cursor | Aider | +|---------|-----------|-------------|--------|-------| +| Command execution | Automatic | Automatic | Automatic | Manual (/run) | +| Context injection | AGENTS.md | Hooks | Rules file | Config file | +| Global install | No (per-project) | Yes | No (per-project) | No (per-project) | +| Stealth mode | N/A | Yes | N/A | N/A | +| Standard format | Yes (AGENTS.md) | No (proprietary) | No (proprietary) | No (proprietary) | +| Multi-tool compatible | Yes | No | No | No | ## Best Practices -1. **Install globally for Claude Code** - You'll get beads context in every project automatically +1. **Start with Factory integration** - Creates AGENTS.md which works across multiple AI tools: + ```bash + bd setup factory + ``` -2. **Install per-project for Cursor/Aider** - These tools expect project-local configuration +2. **Add tool-specific integrations as needed** - Claude hooks, Cursor rules, or Aider config for tool-specific features -3. **Use stealth mode in CI/CD** - `bd setup claude --stealth` avoids git operations that might fail in automated environments +3. **Install globally for Claude Code** - You'll get beads context in every project automatically -4. **Run `bd doctor` after setup** - Verifies the integration is working: +4. **Use stealth mode in CI/CD** - `bd setup claude --stealth` avoids git operations that might fail in automated environments + +5. **Commit AGENTS.md to git** - This ensures all team members and AI tools get the same instructions + +6. **Run `bd doctor` after setup** - Verifies the integration is working: ```bash bd doctor | grep -i claude # Claude Integration: Hooks installed (CLI mode)