feat: add Factory.ai (Droid) support to bd setup command (#598)

Adds Factory.ai (Droid) support to bd setup command via AGENTS.md integration.

- New command: bd setup factory (with --check and --remove flags)
- Creates/updates AGENTS.md with beads workflow instructions
- Uses HTML comment markers for safe idempotent updates
- Comprehensive documentation

Thanks @jordanhubbard!
This commit is contained in:
Jordan Hubbard
2025-12-16 13:42:43 -08:00
committed by GitHub
parent 1ba12e1620
commit e0528de590
4 changed files with 444 additions and 12 deletions

View File

@@ -15,7 +15,7 @@ var (
var setupCmd = &cobra.Command{ var setupCmd = &cobra.Command{
Use: "setup", Use: "setup",
Short: "Setup integration with AI editors", 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{ 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{ var setupClaudeCmd = &cobra.Command{
Use: "claude", Use: "claude",
Short: "Setup Claude Code integration", Short: "Setup Claude Code integration",
@@ -92,6 +117,9 @@ agents from forgetting bd workflow after context compaction.`,
} }
func init() { 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(&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(&setupCheck, "check", false, "Check if Claude integration is installed")
setupClaudeCmd.Flags().BoolVar(&setupRemove, "remove", false, "Remove bd hooks from Claude settings") 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(&setupCheck, "check", false, "Check if Aider integration is installed")
setupAiderCmd.Flags().BoolVar(&setupRemove, "remove", false, "Remove bd config from Aider") setupAiderCmd.Flags().BoolVar(&setupRemove, "remove", false, "Remove bd config from Aider")
setupCmd.AddCommand(setupFactoryCmd)
setupCmd.AddCommand(setupClaudeCmd) setupCmd.AddCommand(setupClaudeCmd)
setupCmd.AddCommand(setupCursorCmd) setupCmd.AddCommand(setupCursorCmd)
setupCmd.AddCommand(setupAiderCmd) setupCmd.AddCommand(setupAiderCmd)

298
cmd/bd/setup/factory.go Normal file
View File

@@ -0,0 +1,298 @@
package setup
import (
"fmt"
"os"
"strings"
)
// Factory/Droid integration markers for AGENTS.md
const (
factoryBeginMarker = "<!-- BEGIN BEADS INTEGRATION -->"
factoryEndMarker = "<!-- END BEADS INTEGRATION -->"
)
const factoryBeadsSection = `<!-- BEGIN BEADS INTEGRATION -->
## 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 <id> --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:<parent-id>`" + `
5. **Complete**: ` + "`bd close <id> --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.
<!-- END BEADS INTEGRATION -->
`
// 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_
`
}

View File

@@ -557,16 +557,19 @@ bd sync # Force immediate sync, bypass debounce
```bash ```bash
# Setup editor integration (choose based on your editor) # 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 claude # Claude Code - installs SessionStart/PreCompact hooks
bd setup cursor # Cursor IDE - creates .cursor/rules/beads.mdc bd setup cursor # Cursor IDE - creates .cursor/rules/beads.mdc
bd setup aider # Aider - creates .aider.conf.yml bd setup aider # Aider - creates .aider.conf.yml
# Check if integration is installed # Check if integration is installed
bd setup factory --check
bd setup claude --check bd setup claude --check
bd setup cursor --check bd setup cursor --check
bd setup aider --check bd setup aider --check
# Remove integration # Remove integration
bd setup factory --remove
bd setup claude --remove bd setup claude --remove
bd setup cursor --remove bd setup cursor --remove
bd setup aider --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:** **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 - **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 - **Cursor** (`bd setup cursor`): Creates `.cursor/rules/beads.mdc` with workflow instructions
- **Aider** (`bd setup aider`): Creates `.aider.conf.yml` with bd workflow instructions - **Aider** (`bd setup aider`): Creates `.aider.conf.yml` with bd workflow instructions

View File

@@ -5,10 +5,11 @@
## Overview ## 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 | | 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 | | [Claude Code](#claude-code) | `bd setup claude` | SessionStart/PreCompact hooks |
| [Cursor IDE](#cursor-ide) | `bd setup cursor` | Rules file (.cursor/rules/beads.mdc) | | [Cursor IDE](#cursor-ide) | `bd setup cursor` | Rules file (.cursor/rules/beads.mdc) |
| [Aider](#aider) | `bd setup aider` | Config file (.aider.conf.yml) | | [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 ```bash
# Install integration for your tool # 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 claude # For Claude Code
bd setup cursor # For Cursor IDE bd setup cursor # For Cursor IDE
bd setup aider # For Aider bd setup aider # For Aider
# Verify installation # Verify installation
bd setup factory --check
bd setup claude --check bd setup claude --check
bd setup cursor --check bd setup cursor --check
bd setup aider --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 (`<!-- BEGIN/END BEADS INTEGRATION -->`) 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 (`<!-- BEGIN/END BEADS INTEGRATION -->`) 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
Claude Code integration uses hooks to automatically inject beads workflow context at session start and before context compaction. 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 ## Comparison
| Feature | Claude Code | Cursor | Aider | | Feature | Factory.ai | Claude Code | Cursor | Aider |
|---------|-------------|--------|-------| |---------|-----------|-------------|--------|-------|
| Command execution | Automatic | Automatic | Manual (/run) | | Command execution | Automatic | Automatic | Automatic | Manual (/run) |
| Context injection | Hooks | Rules file | Config file | | Context injection | AGENTS.md | Hooks | Rules file | Config file |
| Global install | Yes | No (per-project) | No (per-project) | | Global install | No (per-project) | Yes | No (per-project) | No (per-project) |
| Stealth mode | Yes | N/A | N/A | | 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 ## 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 ```bash
bd doctor | grep -i claude bd doctor | grep -i claude
# Claude Integration: Hooks installed (CLI mode) # Claude Integration: Hooks installed (CLI mode)