diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl new file mode 100644 index 00000000..849aa56e --- /dev/null +++ b/.beads/issues.jsonl @@ -0,0 +1,8 @@ +{"id":"bd-1","title":"Add export/import commands","description":"Support bd export --format=jsonl and bd import for text-based git workflow","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-12T00:43:03.453438-07:00","updated_at":"2025-10-12T00:43:03.453438-07:00"} +{"id":"bd-2","title":"Add PostgreSQL backend","description":"Implement PostgreSQL storage backend as alternative to SQLite for larger teams","status":"open","priority":3,"issue_type":"feature","created_at":"2025-10-12T00:43:03.457453-07:00","updated_at":"2025-10-12T00:43:03.457453-07:00"} +{"id":"bd-3","title":"Document git workflow in README","description":"Add Git Workflow section to README explaining binary vs text approaches","status":"closed","priority":1,"issue_type":"chore","created_at":"2025-10-12T00:43:03.461615-07:00","updated_at":"2025-10-12T00:43:30.283178-07:00","closed_at":"2025-10-12T00:43:30.283178-07:00"} +{"id":"bd-4","title":"Add demo GIF/video showing bd quickstart in action","description":"Record asciinema or create animated GIF showing the full workflow","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-12T10:50:49.500051-07:00","updated_at":"2025-10-12T10:50:49.500051-07:00"} +{"id":"bd-5","title":"Implement MCP server for Claude Desktop","description":"Complete the claude-desktop-mcp example with working TypeScript implementation","status":"open","priority":1,"issue_type":"feature","created_at":"2025-10-12T10:50:50.942964-07:00","updated_at":"2025-10-12T10:50:50.942964-07:00"} +{"id":"bd-6","title":"Add migration scripts for GitHub Issues","description":"Create scripts to import from GitHub Issues API or exported JSON","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-12T10:50:52.140018-07:00","updated_at":"2025-10-12T10:50:52.140018-07:00"} +{"id":"bd-7","title":"Add performance benchmarks document","description":"Document actual performance metrics with hyperfine tests","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-12T10:50:53.294516-07:00","updated_at":"2025-10-12T10:50:53.294516-07:00"} +{"id":"bd-8","title":"Reach 1.0 release milestone","description":"Stabilize API, finalize documentation, comprehensive testing","status":"open","priority":1,"issue_type":"epic","created_at":"2025-10-12T10:50:54.457348-07:00","updated_at":"2025-10-12T10:50:54.457348-07:00"} diff --git a/.github/images/agent-using-beads.jpg b/.github/images/agent-using-beads.jpg new file mode 100644 index 00000000..11e1e83f Binary files /dev/null and b/.github/images/agent-using-beads.jpg differ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..a7b8ab86 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,225 @@ +# Instructions for AI Agents Working on Beads + +## Project Overview + +This is **beads** (command: `bd`), an issue tracker designed for AI-supervised coding workflows. We dogfood our own tool! + +## Issue Tracking + +We use bd (beads) for issue tracking instead of Markdown TODOs or external tools. + +### Quick Reference + +```bash +# Find ready work (no blockers) +bd ready --json + +# Create new issue +bd create "Issue title" -t bug|feature|task -p 0-4 -d "Description" --json + +# Update issue status +bd update --status in_progress --json + +# Link discovered work +bd dep add --type discovered-from + +# Complete work +bd close --reason "Done" --json + +# Show dependency tree +bd dep tree + +# Get issue details +bd show --json +``` + +### Workflow + +1. **Check for ready work**: Run `bd ready` to see what's unblocked +2. **Claim your task**: `bd update --status in_progress` +3. **Work on it**: Implement, test, document +4. **Discover new work**: If you find bugs or TODOs, create issues: + - `bd create "Found bug in auth" -t bug -p 1 --json` + - Link it: `bd dep add --type discovered-from` +5. **Complete**: `bd close --reason "Implemented"` +6. **Export**: Run `bd export -o .beads/issues.jsonl` before committing + +### Issue Types + +- `bug` - Something broken that needs fixing +- `feature` - New functionality +- `task` - Work item (tests, docs, refactoring) +- `epic` - Large feature composed of multiple issues +- `chore` - Maintenance work (dependencies, tooling) + +### Priorities + +- `0` - Critical (security, data loss, broken builds) +- `1` - High (major features, important bugs) +- `2` - Medium (nice-to-have features, minor bugs) +- `3` - Low (polish, optimization) +- `4` - Backlog (future ideas) + +### Dependency Types + +- `blocks` - Hard dependency (issue X blocks issue Y) +- `related` - Soft relationship (issues are connected) +- `parent-child` - Epic/subtask relationship +- `discovered-from` - Track issues discovered during work + +Only `blocks` dependencies affect the ready work queue. + +## Development Guidelines + +### Code Standards + +- **Go version**: 1.21+ +- **Linting**: `golangci-lint run ./...` (baseline warnings documented in LINTING.md) +- **Testing**: All new features need tests (`go test ./...`) +- **Documentation**: Update relevant .md files + +### File Organization + +``` +beads/ +├── cmd/bd/ # CLI commands +├── internal/ +│ ├── types/ # Core data types +│ └── storage/ # Storage layer +│ └── sqlite/ # SQLite implementation +├── examples/ # Integration examples +└── *.md # Documentation +``` + +### Before Committing + +1. **Run tests**: `go test ./...` +2. **Run linter**: `golangci-lint run ./...` (ignore baseline warnings) +3. **Export issues**: `bd export -o .beads/issues.jsonl` +4. **Update docs**: If you changed behavior, update README.md or other docs +5. **Git add both**: `git add .beads/issues.jsonl ` + +### Git Workflow + +```bash +# Make changes +git add + +# Export beads issues +bd export -o .beads/issues.jsonl +git add .beads/issues.jsonl + +# Commit +git commit -m "Your message" + +# After pull +git pull +bd import -i .beads/issues.jsonl # Sync SQLite cache +``` + +Or use the git hooks in `examples/git-hooks/` for automation. + +## Current Project Status + +Run `bd stats` to see overall progress. + +### Active Areas + +- **Core CLI**: Mature, but always room for polish +- **Examples**: Growing collection of agent integrations +- **Documentation**: Comprehensive but can always improve +- **MCP Server**: Planned (see bd-5) +- **Migration Tools**: Planned (see bd-6) + +### 1.0 Milestone + +We're working toward 1.0. Key blockers tracked in bd. Run: +```bash +bd dep tree bd-8 # Show 1.0 epic dependencies +``` + +## Common Tasks + +### Adding a New Command + +1. Create file in `cmd/bd/` +2. Add to root command in `cmd/bd/main.go` +3. Implement with Cobra framework +4. Add `--json` flag for agent use +5. Add tests in `cmd/bd/*_test.go` +6. Document in README.md + +### Adding Storage Features + +1. Update schema in `internal/storage/sqlite/schema.go` +2. Add migration if needed +3. Update `internal/types/types.go` if new types +4. Implement in `internal/storage/sqlite/sqlite.go` +5. Add tests +6. Update export/import in `cmd/bd/export.go` and `cmd/bd/import.go` + +### Adding Examples + +1. Create directory in `examples/` +2. Add README.md explaining the example +3. Include working code +4. Link from `examples/README.md` +5. Mention in main README.md + +## Questions? + +- Check existing issues: `bd list` +- Look at recent commits: `git log --oneline -20` +- Read the docs: README.md, TEXT_FORMATS.md, EXTENDING.md +- Create an issue if unsure: `bd create "Question: ..." -t task -p 2` + +## Important Files + +- **README.md** - Main documentation (keep this updated!) +- **EXTENDING.md** - Database extension guide +- **TEXT_FORMATS.md** - JSONL format analysis +- **CONTRIBUTING.md** - Contribution guidelines +- **SECURITY.md** - Security policy + +## Pro Tips for Agents + +- Always use `--json` flags for programmatic use +- Link discoveries with `discovered-from` to maintain context +- Check `bd ready` before asking "what next?" +- Export to JSONL before committing (or use git hooks) +- Use `bd dep tree` to understand complex dependencies +- Priority 0-1 issues are usually more important than 2-4 + +## Building and Testing + +```bash +# Build +go build -o bd ./cmd/bd + +# Test +go test ./... + +# Test with coverage +go test -coverprofile=coverage.out ./... +go tool cover -html=coverage.out + +# Run locally +./bd init --prefix test +./bd create "Test issue" -p 1 +./bd ready +``` + +## Release Process (Maintainers) + +1. Update version in code (if applicable) +2. Update CHANGELOG.md (if exists) +3. Run full test suite +4. Tag release: `git tag v0.x.0` +5. Push tag: `git push origin v0.x.0` +6. GitHub Actions handles the rest + +--- + +**Remember**: We're building this tool to help AI agents like you! If you find the workflow confusing or have ideas for improvement, create an issue with your feedback. + +Happy coding! 🔗 diff --git a/README.md b/README.md index cea9e0a5..bd7a0303 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,24 @@ A lightweight, dependency-aware issue tracker designed for AI-supervised coding workflows. Track dependencies, find ready work, and let agents chain together tasks automatically. +## The Problem + +You're 200 messages deep in a coding session with your AI agent. You've discovered 12 bugs, planned 8 features, debated 3 architectural changes. The agent asks: **"What should I work on next?"** + +You scroll up. Your `TODO.md` has 47 unchecked boxes. Half are blocked by other tasks. Some are duplicates. You have no idea what's actually ready to work on. + +**The agent has forgotten. You've lost track. Work is being duplicated.** + +This is the reality of AI-assisted development: +- **Agents hit context limits** - Long conversations lose early tasks +- **TODOs don't track dependencies** - No way to know what's blocked +- **Markdown doesn't scale** - Finding ready work means manual scanning +- **No shared state** - Agent on your laptop, agent on your desktop, both out of sync + +**Agents need external memory. You need dependency tracking. Both of you need to know what's ready to work on.** + +![AI Agent using Beads](https://raw.githubusercontent.com/steveyegge/beads/main/.github/images/agent-using-beads.jpg) + ## Features - ✨ **Zero setup** - `bd init` creates project-local database @@ -20,16 +38,29 @@ A lightweight, dependency-aware issue tracker designed for AI-supervised coding ## Installation +### Quick Install (Recommended) + ```bash -go install github.com/steveyegge/beads/cmd/bd@latest +curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/install.sh | bash ``` -Or build from source: +The installer will: +- Detect your platform (macOS/Linux, amd64/arm64) +- Install via `go install` if Go is available +- Fall back to building from source if needed +- Guide you through PATH setup if necessary + +### Manual Install ```bash +# Using go install (requires Go 1.21+) +go install github.com/steveyegge/beads/cmd/bd@latest + +# Or build from source git clone https://github.com/steveyegge/beads cd beads go build -o bd ./cmd/bd +sudo mv bd /usr/local/bin/ # or anywhere in your PATH ``` ## Quick Start @@ -346,17 +377,20 @@ This pattern enables powerful integrations while keeping bd simple and focused. ## Comparison to Other Tools -| Feature | bd | GitHub Issues | Jira | Linear | -|---------|-------|---------------|------|--------| -| Zero setup | ✅ | ❌ | ❌ | ❌ | -| Dependency tracking | ✅ | ⚠️ | ✅ | ✅ | -| Ready work detection | ✅ | ❌ | ❌ | ❌ | -| Agent-friendly (JSON) | ✅ | ⚠️ | ⚠️ | ⚠️ | -| Distributed via git | ✅ | ❌ | ❌ | ❌ | -| Works offline | ✅ | ❌ | ❌ | ❌ | -| AI-resolvable conflicts | ✅ | ❌ | ❌ | ❌ | -| Extensible database | ✅ | ❌ | ❌ | ❌ | -| No server required | ✅ | ❌ | ❌ | ❌ | +| Feature | bd | Taskwarrior | GitHub Issues | Jira | Linear | +|---------|-------|-------------|---------------|------|--------| +| Zero setup | ✅ | ✅ | ❌ | ❌ | ❌ | +| Dependency tracking | ✅ | ✅ | ⚠️ | ✅ | ✅ | +| Ready work detection | ✅ | ⚠️ | ❌ | ❌ | ❌ | +| Agent-friendly (JSON) | ✅ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | +| Distributed via git | ✅ | ⚠️ | ❌ | ❌ | ❌ | +| Works offline | ✅ | ✅ | ❌ | ❌ | ❌ | +| AI-resolvable conflicts | ✅ | ❌ | ❌ | ❌ | ❌ | +| Extensible database | ✅ | ❌ | ❌ | ❌ | ❌ | +| No server required | ✅ | ✅ | ❌ | ❌ | ❌ | +| Built for AI agents | ✅ | ❌ | ❌ | ❌ | ❌ | + +**vs. Taskwarrior**: Taskwarrior is great for personal task management, but bd is designed specifically for AI agents. bd has explicit dependency types (`discovered-from`), JSON-first API design, and JSONL storage optimized for git merging. Taskwarrior's sync server requires setup; bd uses git automatically. ## Why bd? @@ -510,6 +544,220 @@ Git may show a conflict, but resolution is simple: **keep both lines** (both cha See **[TEXT_FORMATS.md](TEXT_FORMATS.md)** for detailed analysis of JSONL merge strategies and conflict resolution. +## Examples + +Check out the **[examples/](examples/)** directory for: +- **[Python agent](examples/python-agent/)** - Full agent implementation in Python +- **[Bash agent](examples/bash-agent/)** - Shell script agent example +- **[Git hooks](examples/git-hooks/)** - Automatic export/import on git operations +- **[Claude Desktop MCP](examples/claude-desktop-mcp/)** - MCP server integration (coming soon) + +## FAQ + +### Why not just use GitHub Issues? + +GitHub Issues requires internet, has API rate limits, and isn't designed for agents. bd works offline, has no limits, and gives you `bd ready --json` to instantly find unblocked work. Plus, bd's distributed database means agents on multiple machines share state via git—no API calls needed. + +### How is this different from Taskwarrior? + +Taskwarrior is excellent for personal task management, but bd is built for AI agents: +- **Explicit agent semantics**: `discovered-from` dependency type, `bd ready` for queue management +- **JSON-first design**: Every command has `--json` output +- **Git-native sync**: No sync server setup required +- **Merge-friendly JSONL**: One issue per line, AI-resolvable conflicts +- **Extensible SQLite**: Add your own tables without forking + +### Can I use bd without AI agents? + +Absolutely! bd is a great CLI issue tracker for humans too. The `bd ready` command is useful for anyone managing dependencies. Think of it as "Taskwarrior meets git." + +### What happens if two agents work on the same issue? + +The last agent to export/commit wins. This is the same as any git-based workflow. To prevent conflicts: +- Have agents claim work with `bd update --status in_progress` +- Query by assignee: `bd ready --assignee agent-name` +- Review git diffs before merging + +For true multi-agent coordination, you'd need additional tooling (like locks or a coordination server). bd handles the simpler case: multiple humans/agents working on different tasks, syncing via git. + +### Do I need to run export/import manually? + +No! Install the git hooks from [examples/git-hooks/](examples/git-hooks/): +```bash +cd examples/git-hooks && ./install.sh +``` + +The hooks automatically export before commits and import after pulls/merges/checkouts. Set it up once, forget about it. + +### Can I track issues for multiple projects? + +Yes! bd uses project-local databases: +```bash +cd ~/project1 && bd init --prefix proj1 +cd ~/project2 && bd init --prefix proj2 +``` + +Each project gets its own `.beads/` directory with its own database and JSONL file. bd auto-discovers the correct database based on your current directory (walks up like git). + +### How do I migrate from GitHub Issues / Jira / Linear? + +We don't have automated migration tools yet, but you can: +1. Export issues from your current tracker (usually CSV or JSON) +2. Write a simple script to convert to bd's JSONL format +3. Import with `bd import -i issues.jsonl` + +See [examples/](examples/) for scripting patterns. Contributions welcome! + +### Is this production-ready? + +bd is in active development and used for real projects. The core functionality (create, update, dependencies, ready work) is stable. However: +- No 1.0 release yet +- API may change before 1.0 +- Use for development/internal projects first +- Expect rapid iteration + +Follow the repo for updates! + +### How does bd handle scale? + +bd uses SQLite, which handles millions of rows efficiently. For a typical project with thousands of issues: +- Commands complete in <100ms +- Full-text search is instant +- Dependency graphs traverse quickly +- JSONL files stay small (one line per issue) + +For extremely large projects (100k+ issues), you might want to filter exports or use multiple databases per component. + +### Can I use bd for non-code projects? + +Sure! bd is just an issue tracker. Use it for: +- Writing projects (chapters as issues, dependencies as outlines) +- Research projects (papers, experiments, dependencies) +- Home projects (renovations with blocking tasks) +- Any workflow with dependencies + +The agent-friendly design works for any AI-assisted workflow. + +## Troubleshooting + +### `bd: command not found` + +bd is not in your PATH. Either: +```bash +# Check if installed +go list -f {{.Target}} github.com/steveyegge/beads/cmd/bd + +# Add Go bin to PATH +export PATH="$PATH:$(go env GOPATH)/bin" + +# Or reinstall +go install github.com/steveyegge/beads/cmd/bd@latest +``` + +### `database is locked` + +Another bd process is accessing the database, or SQLite didn't close properly. Solutions: +```bash +# Find and kill hanging processes +ps aux | grep bd +kill + +# Remove lock files (safe if no bd processes running) +rm .beads/*.db-journal .beads/*.db-wal .beads/*.db-shm +``` + +### `failed to import: issue already exists` + +You're trying to import issues that conflict with existing ones. Options: +```bash +# Skip existing issues (only import new ones) +bd import -i issues.jsonl --skip-existing + +# Or clear database and re-import everything +rm .beads/*.db +bd import -i .beads/issues.jsonl +``` + +### Git merge conflict in `issues.jsonl` + +When both sides add issues, you'll get conflicts. Resolution: +1. Open `.beads/issues.jsonl` +2. Look for `<<<<<<< HEAD` markers +3. Most conflicts can be resolved by **keeping both sides** +4. Each line is independent unless IDs conflict +5. For same-ID conflicts, keep the newest (check `updated_at`) + +Example resolution: +```bash +# After resolving conflicts manually +git add .beads/issues.jsonl +git commit +bd import -i .beads/issues.jsonl # Sync to SQLite +``` + +See [TEXT_FORMATS.md](TEXT_FORMATS.md) for detailed merge strategies. + +### `bd ready` shows nothing but I have open issues + +Those issues probably have open blockers. Check: +```bash +# See blocked issues +bd blocked + +# Show dependency tree +bd dep tree + +# Remove blocking dependency if needed +bd dep remove +``` + +Remember: Only `blocks` dependencies affect ready work. + +### Permission denied on git hooks + +Git hooks need execute permissions: +```bash +chmod +x .git/hooks/pre-commit +chmod +x .git/hooks/post-merge +chmod +x .git/hooks/post-checkout +``` + +Or use the installer: `cd examples/git-hooks && ./install.sh` + +### `bd init` fails with "directory not empty" + +`.beads/` already exists. Options: +```bash +# Use existing database +bd list # Should work if already initialized + +# Or remove and reinitialize (DESTROYS DATA!) +rm -rf .beads/ +bd init +``` + +### Export/import is slow + +For large databases (10k+ issues): +```bash +# Export only open issues +bd export --format=jsonl --status=open -o .beads/issues.jsonl + +# Or filter by priority +bd export --format=jsonl --priority=0 --priority=1 -o critical.jsonl +``` + +Consider splitting large projects into multiple databases. + +### Agent creates duplicate issues + +Agents may not realize an issue already exists. Prevention strategies: +- Have agents search first: `bd list --json | grep "title"` +- Use labels to mark auto-created issues: `bd create "..." -l auto-generated` +- Review and deduplicate periodically: `bd list | sort` + +True deduplication logic would require fuzzy matching - contributions welcome! + ## Documentation - **[README.md](README.md)** - You are here! Complete guide diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..1dac9334 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,88 @@ +# Security Policy + +## Reporting Security Issues + +If you discover a security vulnerability in bd, please report it responsibly: + +**Email**: security@steveyegge.com (or open a private security advisory on GitHub) + +Please include: +- Description of the vulnerability +- Steps to reproduce +- Potential impact +- Suggested fix (if any) + +We will respond within 48 hours and work with you to address the issue. + +## Security Considerations + +### Database Security + +bd stores issue data locally in: +- SQLite databases (`.beads/*.db`) - local only, gitignored +- JSONL files (`.beads/issues.jsonl`) - committed to git + +**Important**: +- Do not store sensitive information (passwords, API keys, secrets) in issue descriptions or metadata +- Issue data is committed to git and will be visible to anyone with repository access +- bd does not encrypt data at rest (it's a local development tool) + +### Git Workflow Security + +- bd uses standard git operations (no custom protocols) +- Export/import operations read and write local files only +- No network communication except through git itself +- Git hooks (if used) run with your local user permissions + +### Command Injection Protection + +bd uses parameterized SQL queries to prevent SQL injection. However: +- Do not pass untrusted input directly to `bd` commands +- Issue IDs are validated against the pattern `^[a-z0-9-]+$` +- File paths are validated before reading/writing + +### Dependency Security + +bd has minimal dependencies: +- Go standard library +- SQLite (via modernc.org/sqlite - pure Go implementation) +- Cobra CLI framework + +All dependencies are regularly updated. Run `go mod verify` to check integrity. + +## Supported Versions + +We provide security updates for: + +| Version | Supported | +| ------- | ------------------ | +| main | :white_check_mark: | +| < 1.0 | :x: | + +Once version 1.0 is released, we will support the latest major version and one previous major version. + +## Best Practices + +1. **Don't commit secrets** - Never put API keys, passwords, or credentials in issue descriptions +2. **Review before export** - Check `.beads/issues.jsonl` before committing sensitive project details +3. **Use private repos** - If your issues contain proprietary information, use private git repositories +4. **Validate git hooks** - If using automated export/import hooks, review them for safety +5. **Regular updates** - Keep bd updated to the latest version: `go install github.com/steveyegge/beads/cmd/bd@latest` + +## Known Limitations + +- bd is designed for **development/internal use**, not production secret management +- Issue data is stored in plain text (both SQLite and JSONL) +- No built-in encryption or access control (relies on filesystem permissions) +- No audit logging beyond git history + +For sensitive workflows, consider using bd only for non-sensitive task tracking. + +## Security Updates + +Security updates will be announced via: +- GitHub Security Advisories +- Release notes on GitHub +- Git commit messages (tagged with `[security]`) + +Subscribe to the repository for notifications. diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..61f6282d --- /dev/null +++ b/examples/README.md @@ -0,0 +1,39 @@ +# Beads Examples + +This directory contains examples of how to integrate bd with AI agents and workflows. + +## Examples + +- **[python-agent/](python-agent/)** - Simple Python agent that discovers ready work and completes tasks +- **[bash-agent/](bash-agent/)** - Bash script showing the full agent workflow +- **[git-hooks/](git-hooks/)** - Pre-configured git hooks for automatic export/import +- **[claude-desktop-mcp/](claude-desktop-mcp/)** - MCP server for Claude Desktop integration + +## Quick Start + +```bash +# Try the Python agent example +cd python-agent +python agent.py + +# Try the bash agent example +cd bash-agent +./agent.sh + +# Install git hooks +cd git-hooks +./install.sh +``` + +## Creating Your Own Agent + +The basic agent workflow: + +1. **Find ready work**: `bd ready --json --limit 1` +2. **Claim the task**: `bd update --status in_progress --json` +3. **Do the work**: Execute the task +4. **Discover new issues**: `bd create "Found bug" --json` +5. **Link discoveries**: `bd dep add --type discovered-from` +6. **Complete the task**: `bd close --reason "Done" --json` + +All commands support `--json` for easy parsing. diff --git a/examples/bash-agent/README.md b/examples/bash-agent/README.md new file mode 100644 index 00000000..395cdf0b --- /dev/null +++ b/examples/bash-agent/README.md @@ -0,0 +1,124 @@ +# Bash Agent Example + +A bash script demonstrating how an AI agent can use bd to manage tasks autonomously. + +## Features + +- Pure bash implementation (no Python/Node required) +- Colorized terminal output +- Automatic work discovery +- Random issue creation to simulate real agent behavior +- Dependency linking with `discovered-from` +- Statistics display + +## Prerequisites + +- bash 4.0+ +- bd installed: `go install github.com/steveyegge/beads/cmd/bd@latest` +- jq for JSON parsing: `brew install jq` (macOS) or `apt install jq` (Linux) +- A beads database initialized: `bd init` + +## Usage + +```bash +# Make executable +chmod +x agent.sh + +# Run with default 10 iterations +./agent.sh + +# Run with custom iteration limit +./agent.sh 20 +``` + +## What It Does + +The agent runs in a loop: + +1. Looks for ready work (no blockers) +2. Claims the task (sets status to `in_progress`) +3. "Works" on it (simulates 1 second of work) +4. 50% chance to discover a follow-up issue +5. If discovered, creates and links the new issue +6. Completes the original task +7. Shows statistics and repeats + +## Example Output + +``` +🚀 Beads Agent starting... + Max iterations: 10 + +═══════════════════════════════════════════════════ + Beads Statistics +═══════════════════════════════════════════════════ +Open: 5 In Progress: 0 Closed: 2 + +═══════════════════════════════════════════════════ + Iteration 1/10 +═══════════════════════════════════════════════════ +ℹ Looking for ready work... +ℹ Claiming task: bd-3 +✓ Task claimed +ℹ Working on: Fix authentication bug (bd-3) + Priority: 1 +⚠ Discovered issue while working! +✓ Created issue: bd-8 +✓ Linked bd-8 ← discovered-from ← bd-3 +ℹ Completing task: bd-3 +✓ Task completed: bd-3 +``` + +## Use Cases + +**Continuous Integration** +```bash +# Run agent in CI to process testing tasks +./agent.sh 5 +``` + +**Cron Jobs** +```bash +# Run agent every hour +0 * * * * cd /path/to/project && /path/to/agent.sh 3 +``` + +**One-off Task Processing** +```bash +# Process exactly one task and exit +./agent.sh 1 +``` + +## Customization + +Edit the script to customize behavior: + +```bash +# Change discovery probability (line ~80) +if [[ $((RANDOM % 2)) -eq 0 ]]; then # 50% chance +# Change to: +if [[ $((RANDOM % 10)) -lt 3 ]]; then # 30% chance + +# Add assignee filtering +bd ready --json --assignee "bot" --limit 1 + +# Add priority filtering +bd ready --json --priority 1 --limit 1 + +# Add custom labels +bd create "New task" -l "automated,agent-discovered" +``` + +## Integration with Real Agents + +This script is a starting point. To integrate with a real LLM: + +1. Replace `do_work()` with calls to your LLM API +2. Parse the LLM's response for tasks to create +3. Use issue IDs to maintain context +4. Track conversation state in issue metadata + +## See Also + +- [../python-agent/](../python-agent/) - Python version with more flexibility +- [../git-hooks/](../git-hooks/) - Automatic export/import on git operations diff --git a/examples/bash-agent/agent.sh b/examples/bash-agent/agent.sh new file mode 100755 index 00000000..f68ea263 --- /dev/null +++ b/examples/bash-agent/agent.sh @@ -0,0 +1,182 @@ +#!/usr/bin/env bash +# +# Simple AI agent workflow using bd (Beads issue tracker). +# +# This demonstrates the full lifecycle of an agent managing tasks: +# - Find ready work +# - Claim and execute +# - Discover new issues +# - Link discoveries +# - Complete and move on + +set -euo pipefail + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${BLUE}ℹ ${NC}$1" +} + +log_success() { + echo -e "${GREEN}✓${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}⚠${NC} $1" +} + +log_error() { + echo -e "${RED}✗${NC} $1" +} + +# Check if bd is installed +if ! command -v bd &> /dev/null; then + log_error "bd is not installed" + echo "Install with: go install github.com/steveyegge/beads/cmd/bd@latest" + exit 1 +fi + +# Check if we're in a beads-initialized directory +if ! bd list &> /dev/null; then + log_error "Not in a beads-initialized directory" + echo "Run: bd init" + exit 1 +fi + +# Find ready work +find_ready_work() { + bd ready --json --limit 1 2>/dev/null | jq -r '.[0] // empty' +} + +# Extract field from JSON +get_field() { + local json="$1" + local field="$2" + echo "$json" | jq -r ".$field" +} + +# Claim a task +claim_task() { + local issue_id="$1" + log_info "Claiming task: $issue_id" + bd update "$issue_id" --status in_progress --json > /dev/null + log_success "Task claimed" +} + +# Simulate doing work (in real agent, this would call LLM/execute code) +do_work() { + local issue="$1" + local issue_id=$(get_field "$issue" "id") + local title=$(get_field "$issue" "title") + local priority=$(get_field "$issue" "priority") + + echo "" + log_info "Working on: $title ($issue_id)" + echo " Priority: $priority" + + # Simulate work delay + sleep 1 + + # Simulate discovering new work (50% chance) + if [[ $((RANDOM % 2)) -eq 0 ]]; then + log_warning "Discovered issue while working!" + + # Create new issue + local new_issue=$(bd create "Follow-up: $title" \ + -d "Discovered while working on $issue_id" \ + -p 2 \ + -t task \ + --json) + + local new_id=$(echo "$new_issue" | jq -r '.id') + log_success "Created issue: $new_id" + + # Link it back to parent + bd dep add "$new_id" "$issue_id" --type discovered-from + log_success "Linked $new_id ← discovered-from ← $issue_id" + + return 0 # Discovered new work + fi + + return 1 # No new work discovered +} + +# Complete a task +complete_task() { + local issue_id="$1" + local reason="${2:-Completed successfully}" + + log_info "Completing task: $issue_id" + bd close "$issue_id" --reason "$reason" --json > /dev/null + log_success "Task completed: $issue_id" +} + +# Show statistics +show_stats() { + echo "" + echo "═══════════════════════════════════════════════════" + echo " Beads Statistics" + echo "═══════════════════════════════════════════════════" + bd stats + echo "" +} + +# Main agent loop +run_agent() { + local max_iterations="${1:-10}" + local iteration=0 + + echo "" + echo "🚀 Beads Agent starting..." + echo " Max iterations: $max_iterations" + show_stats + + while [[ $iteration -lt $max_iterations ]]; do + iteration=$((iteration + 1)) + + echo "" + echo "═══════════════════════════════════════════════════" + echo " Iteration $iteration/$max_iterations" + echo "═══════════════════════════════════════════════════" + + # Find ready work + log_info "Looking for ready work..." + ready_work=$(find_ready_work) + + if [[ -z "$ready_work" ]]; then + log_warning "No ready work found. Agent idle." + break + fi + + issue_id=$(get_field "$ready_work" "id") + + # Claim it + claim_task "$issue_id" + + # Do the work + if do_work "$ready_work"; then + log_info "New work discovered, will process in next iteration" + fi + + # Complete it + complete_task "$issue_id" + + # Brief pause between iterations + sleep 0.5 + done + + echo "" + log_success "Agent finished after $iteration iterations" + show_stats +} + +# Handle Ctrl-C gracefully +trap 'echo ""; log_warning "Agent interrupted by user"; exit 130' INT + +# Run the agent +run_agent "${1:-10}" diff --git a/examples/claude-desktop-mcp/README.md b/examples/claude-desktop-mcp/README.md new file mode 100644 index 00000000..7c526ca7 --- /dev/null +++ b/examples/claude-desktop-mcp/README.md @@ -0,0 +1,208 @@ +# Claude Desktop MCP Server for Beads + +> **Note**: This is a reference implementation showing how to integrate bd with Claude Desktop via MCP (Model Context Protocol). + +## What This Provides + +An MCP server that exposes bd functionality to Claude Desktop, allowing Claude to: +- Query ready work +- Create and update issues +- Manage dependencies +- Track discovered work + +## Implementation Status + +This is a **documentation stub** showing the intended integration pattern. Full implementation coming soon! + +## Planned Features + +```typescript +// MCP server will expose these tools to Claude: + +// Find ready work +{ + "name": "beads_ready_work", + "description": "Find issues with no blocking dependencies", + "parameters": { + "limit": "number", + "priority": "number (0-4)", + "assignee": "string" + } +} + +// Create issue +{ + "name": "beads_create_issue", + "description": "Create a new issue", + "parameters": { + "title": "string", + "description": "string", + "priority": "number (0-4)", + "type": "bug|feature|task|epic|chore" + } +} + +// Update issue +{ + "name": "beads_update_issue", + "description": "Update issue status or fields", + "parameters": { + "id": "string", + "status": "open|in_progress|blocked|closed", + "priority": "number", + "assignee": "string" + } +} + +// Add dependency +{ + "name": "beads_add_dependency", + "description": "Link issues with dependencies", + "parameters": { + "from": "string (issue ID)", + "to": "string (issue ID)", + "type": "blocks|related|parent-child|discovered-from" + } +} +``` + +## How It Would Work + +1. Install the MCP server for Claude Desktop +2. Claude gains access to bd commands +3. During coding sessions, Claude can: + - Check for ready work: "What should I work on next?" + - Create issues: "I found a bug, let me track it" + - Link discoveries: "This is related to the issue we're working on" + - Update status: "Marking bd-5 as completed" + +## Example Conversation + +``` +User: What's ready to work on? + +Claude: Let me check the ready work queue... +[Calls beads_ready_work()] + +I found 3 ready issues: +1. bd-12: Fix authentication bug (priority 0, bug) +2. bd-15: Add dark mode toggle (priority 1, feature) +3. bd-18: Update documentation (priority 2, task) + +Which would you like to work on? + +User: Let's do bd-12 + +Claude: Great! I'll mark bd-12 as in progress. +[Calls beads_update_issue("bd-12", status="in_progress")] + +Let me investigate the authentication code... +[Works on the issue] + +I found the bug in auth.js:45 - there's a race condition. While fixing this, I noticed we're also missing rate limiting. Should I track that as a separate issue? + +User: Yes please + +Claude: [Calls beads_create_issue("Add rate limiting to auth endpoints", type="task", priority=1)] +Created bd-23: Add rate limiting to auth endpoints + +[Calls beads_add_dependency("bd-23", "bd-12", type="discovered-from")] +Linked bd-23 as discovered from bd-12 + +Now I'll complete the auth bug fix... +``` + +## Implementation Guide + +To implement this MCP server: + +1. Create a Node.js/TypeScript project +2. Use the MCP SDK: `npm install @anthropic/mcp-sdk` +3. Implement tool handlers that call `bd` commands via child_process +4. Register with Claude Desktop's config + +Example skeleton: + +```typescript +import { Server } from "@anthropic/mcp-sdk"; +import { exec } from "child_process"; +import { promisify } from "util"; + +const execAsync = promisify(exec); + +const server = new Server({ + name: "beads", + version: "1.0.0" +}); + +// Register ready work tool +server.tool("beads_ready_work", async (params) => { + const { stdout } = await execAsync( + `bd ready --json --limit ${params.limit || 10}` + ); + return JSON.parse(stdout); +}); + +// Register create issue tool +server.tool("beads_create_issue", async (params) => { + const { stdout } = await execAsync( + `bd create "${params.title}" -d "${params.description}" -p ${params.priority} -t ${params.type} --json` + ); + return JSON.parse(stdout); +}); + +// ... more tools ... + +server.start(); +``` + +## Installation (Future) + +```bash +# Install the MCP server +npm install -g beads-mcp-server + +# Configure Claude Desktop +# Add to ~/Library/Application Support/Claude/claude_desktop_config.json +{ + "mcpServers": { + "beads": { + "command": "beads-mcp-server", + "args": [] + } + } +} + +# Restart Claude Desktop +``` + +## Alternative: Direct bd Usage + +Until the MCP server is available, you can instruct Claude to use bd directly: + +```markdown +# In your CLAUDE.md or project instructions: + +We use Beads (bd) for issue tracking. Available commands: + +- `bd ready --json` - Find ready work +- `bd create "title" -p 1 -t bug --json` - Create issue +- `bd update bd-1 --status in_progress --json` - Update status +- `bd dep add bd-2 bd-1 --type discovered-from` - Link issues +- `bd close bd-1 --reason "Done" --json` - Complete work + +All commands support --json for parsing. Please use bd to track work during our sessions. +``` + +## Contributing + +Interested in building this MCP server? We welcome contributions! + +See [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines. + +## See Also + +- [MCP Documentation](https://docs.anthropic.com/claude/docs/model-context-protocol) +- [MCP SDK](https://github.com/anthropics/mcp-sdk) +- [Claude Desktop](https://claude.ai/desktop) +- [../python-agent/](../python-agent/) - Python implementation pattern diff --git a/examples/git-hooks/README.md b/examples/git-hooks/README.md new file mode 100644 index 00000000..fefebdda --- /dev/null +++ b/examples/git-hooks/README.md @@ -0,0 +1,183 @@ +# Git Hooks for Beads + +Automatic export/import of beads issues during git operations. + +## What These Hooks Do + +- **pre-commit**: Exports SQLite → JSONL before every commit +- **post-merge**: Imports JSONL → SQLite after git pull/merge +- **post-checkout**: Imports JSONL → SQLite after branch switching + +This keeps your `.beads/issues.jsonl` (committed to git) in sync with your local SQLite database (gitignored). + +## Installation + +### Quick Install + +```bash +cd /path/to/your/project +./examples/git-hooks/install.sh +``` + +The installer will prompt before overwriting existing hooks. + +### Manual Install + +```bash +# Copy hooks to .git/hooks/ +cp examples/git-hooks/pre-commit .git/hooks/ +cp examples/git-hooks/post-merge .git/hooks/ +cp examples/git-hooks/post-checkout .git/hooks/ + +# Make them executable +chmod +x .git/hooks/pre-commit +chmod +x .git/hooks/post-merge +chmod +x .git/hooks/post-checkout +``` + +## Usage + +Once installed, the hooks run automatically: + +```bash +# Creating/updating issues +bd create "New feature" -p 1 +bd update bd-1 --status in_progress + +# Committing changes - hook exports automatically +git add . +git commit -m "Update feature" +# 🔗 Exporting beads issues to JSONL... +# ✓ Beads issues exported and staged + +# Pulling changes - hook imports automatically +git pull +# 🔗 Importing beads issues from JSONL... +# ✓ Beads issues imported successfully + +# Switching branches - hook imports automatically +git checkout feature-branch +# 🔗 Importing beads issues from JSONL... +# ✓ Beads issues imported successfully +``` + +## How It Works + +### The Workflow + +1. You work with bd commands (`create`, `update`, `close`) +2. Changes are stored in SQLite (`.beads/*.db`) - fast local queries +3. Before commit, hook exports to JSONL (`.beads/issues.jsonl`) - git-friendly +4. JSONL is committed to git (source of truth) +5. After pull/merge/checkout, hook imports JSONL back to SQLite +6. Your local SQLite cache is now in sync with git + +### Why This Design? + +**SQLite for speed**: +- Fast queries (dependency trees, ready work) +- Rich SQL capabilities +- Sub-100ms response times + +**JSONL for git**: +- Clean diffs (one issue per line) +- Mergeable (independent lines) +- Human-readable +- AI-resolvable conflicts + +Best of both worlds! + +## Troubleshooting + +### Hook not running + +```bash +# Check if hook is executable +ls -l .git/hooks/pre-commit +# Should show -rwxr-xr-x + +# Make it executable if needed +chmod +x .git/hooks/pre-commit +``` + +### Export/import fails + +```bash +# Check if bd is in PATH +which bd + +# Check if you're in a beads-initialized directory +bd list +``` + +### Merge conflicts in issues.jsonl + +If you get merge conflicts in `.beads/issues.jsonl`: + +1. Most conflicts are safe to resolve by keeping both sides +2. Each line is an independent issue +3. Look for `<<<<<<< HEAD` markers +4. Keep all lines that don't conflict +5. For actual conflicts on the same issue, choose the newest + +Example conflict: + +``` +<<<<<<< HEAD +{"id":"bd-3","title":"Updated title","status":"closed","updated_at":"2025-10-12T10:00:00Z"} +======= +{"id":"bd-3","title":"Updated title","status":"in_progress","updated_at":"2025-10-12T09:00:00Z"} +>>>>>>> feature-branch +``` + +Resolution: Keep the HEAD version (newer timestamp). + +After resolving: +```bash +git add .beads/issues.jsonl +git commit +bd import -i .beads/issues.jsonl # Sync to SQLite +``` + +## Uninstalling + +```bash +rm .git/hooks/pre-commit +rm .git/hooks/post-merge +rm .git/hooks/post-checkout +``` + +## Customization + +### Skip hook for one commit + +```bash +git commit --no-verify -m "Skip hooks" +``` + +### Add to existing hooks + +If you already have git hooks, you can append to them: + +```bash +# Append to existing pre-commit +cat examples/git-hooks/pre-commit >> .git/hooks/pre-commit +``` + +### Filter exports + +Export only specific issues: + +```bash +# Edit pre-commit hook, change: +bd export --format=jsonl -o .beads/issues.jsonl + +# To: +bd export --format=jsonl --status=open -o .beads/issues.jsonl +``` + +## See Also + +- [Git hooks documentation](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) +- [../../TEXT_FORMATS.md](../../TEXT_FORMATS.md) - JSONL merge strategies +- [../../GIT_WORKFLOW.md](../../GIT_WORKFLOW.md) - Design rationale diff --git a/examples/git-hooks/install.sh b/examples/git-hooks/install.sh new file mode 100755 index 00000000..e694887f --- /dev/null +++ b/examples/git-hooks/install.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# +# Install Beads git hooks +# +# This script copies the hooks to .git/hooks/ and makes them executable + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +HOOKS_DIR="$(git rev-parse --git-dir)/hooks" + +# Check if we're in a git repository +if ! git rev-parse --git-dir &> /dev/null; then + echo "Error: Not in a git repository" + exit 1 +fi + +echo "Installing Beads git hooks to $HOOKS_DIR" +echo "" + +# Install pre-commit hook +if [[ -f "$HOOKS_DIR/pre-commit" ]]; then + echo "⚠ $HOOKS_DIR/pre-commit already exists" + read -p "Overwrite? (y/n) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Skipping pre-commit" + else + cp "$SCRIPT_DIR/pre-commit" "$HOOKS_DIR/pre-commit" + chmod +x "$HOOKS_DIR/pre-commit" + echo "✓ Installed pre-commit hook" + fi +else + cp "$SCRIPT_DIR/pre-commit" "$HOOKS_DIR/pre-commit" + chmod +x "$HOOKS_DIR/pre-commit" + echo "✓ Installed pre-commit hook" +fi + +# Install post-merge hook +if [[ -f "$HOOKS_DIR/post-merge" ]]; then + echo "⚠ $HOOKS_DIR/post-merge already exists" + read -p "Overwrite? (y/n) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Skipping post-merge" + else + cp "$SCRIPT_DIR/post-merge" "$HOOKS_DIR/post-merge" + chmod +x "$HOOKS_DIR/post-merge" + echo "✓ Installed post-merge hook" + fi +else + cp "$SCRIPT_DIR/post-merge" "$HOOKS_DIR/post-merge" + chmod +x "$HOOKS_DIR/post-merge" + echo "✓ Installed post-merge hook" +fi + +# Install post-checkout hook +if [[ -f "$HOOKS_DIR/post-checkout" ]]; then + echo "⚠ $HOOKS_DIR/post-checkout already exists" + read -p "Overwrite? (y/n) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Skipping post-checkout" + else + cp "$SCRIPT_DIR/post-checkout" "$HOOKS_DIR/post-checkout" + chmod +x "$HOOKS_DIR/post-checkout" + echo "✓ Installed post-checkout hook" + fi +else + cp "$SCRIPT_DIR/post-checkout" "$HOOKS_DIR/post-checkout" + chmod +x "$HOOKS_DIR/post-checkout" + echo "✓ Installed post-checkout hook" +fi + +echo "" +echo "✓ Beads git hooks installed successfully!" +echo "" +echo "These hooks will:" +echo " • Export issues to JSONL before every commit" +echo " • Import issues from JSONL after merges" +echo " • Import issues from JSONL after branch checkouts" +echo "" +echo "To uninstall, simply delete the hooks from $HOOKS_DIR" diff --git a/examples/git-hooks/post-checkout b/examples/git-hooks/post-checkout new file mode 100755 index 00000000..e40c8197 --- /dev/null +++ b/examples/git-hooks/post-checkout @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# +# Beads post-checkout hook +# Automatically imports JSONL to SQLite database after checking out branches +# +# Install: cp examples/git-hooks/post-checkout .git/hooks/post-checkout && chmod +x .git/hooks/post-checkout + +# Arguments provided by git: +# $1 = ref of previous HEAD +# $2 = ref of new HEAD +# $3 = flag (1 if branch checkout, 0 if file checkout) + +# Only run on branch checkouts +if [[ "$3" != "1" ]]; then + exit 0 +fi + +set -e + +# Check if bd is installed +if ! command -v bd &> /dev/null; then + exit 0 +fi + +# Check if issues.jsonl exists +if [[ ! -f .beads/issues.jsonl ]]; then + exit 0 +fi + +# Import issues from JSONL +echo "🔗 Importing beads issues from JSONL..." + +if bd import -i .beads/issues.jsonl 2>/dev/null; then + echo "✓ Beads issues imported successfully" +else + echo "Warning: bd import failed" +fi + +exit 0 diff --git a/examples/git-hooks/post-merge b/examples/git-hooks/post-merge new file mode 100755 index 00000000..913ced5c --- /dev/null +++ b/examples/git-hooks/post-merge @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# +# Beads post-merge hook +# Automatically imports JSONL to SQLite database after pulling/merging +# +# Install: cp examples/git-hooks/post-merge .git/hooks/post-merge && chmod +x .git/hooks/post-merge + +set -e + +# Check if bd is installed +if ! command -v bd &> /dev/null; then + echo "Warning: bd not found in PATH, skipping import" + exit 0 +fi + +# Check if issues.jsonl exists +if [[ ! -f .beads/issues.jsonl ]]; then + # No JSONL file, nothing to import + exit 0 +fi + +# Import issues from JSONL +echo "🔗 Importing beads issues from JSONL..." + +if bd import -i .beads/issues.jsonl 2>/dev/null; then + echo "✓ Beads issues imported successfully" +else + echo "Warning: bd import failed" + echo "You may need to resolve conflicts manually" + exit 1 +fi + +exit 0 diff --git a/examples/git-hooks/pre-commit b/examples/git-hooks/pre-commit new file mode 100755 index 00000000..516bde60 --- /dev/null +++ b/examples/git-hooks/pre-commit @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# +# Beads pre-commit hook +# Automatically exports SQLite database to JSONL before committing +# +# Install: cp examples/git-hooks/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit + +set -e + +# Check if bd is installed +if ! command -v bd &> /dev/null; then + echo "Warning: bd not found in PATH, skipping export" + exit 0 +fi + +# Check if .beads directory exists +if [[ ! -d .beads ]]; then + # No beads database, nothing to do + exit 0 +fi + +# Export issues to JSONL +echo "🔗 Exporting beads issues to JSONL..." + +if bd export --format=jsonl -o .beads/issues.jsonl 2>/dev/null; then + # Add the JSONL file to the commit + git add .beads/issues.jsonl + echo "✓ Beads issues exported and staged" +else + echo "Warning: bd export failed, continuing anyway" +fi + +exit 0 diff --git a/examples/python-agent/README.md b/examples/python-agent/README.md new file mode 100644 index 00000000..692966d8 --- /dev/null +++ b/examples/python-agent/README.md @@ -0,0 +1,88 @@ +# Python Agent Example + +A simple Python script demonstrating how an AI agent can use bd to manage tasks. + +## Features + +- Finds ready work using `bd ready --json` +- Claims tasks by updating status +- Simulates discovering new issues during work +- Links discovered issues with `discovered-from` dependency +- Completes tasks and moves to the next one + +## Prerequisites + +- Python 3.7+ +- bd installed: `go install github.com/steveyegge/beads/cmd/bd@latest` +- A beads database initialized: `bd init` + +## Usage + +```bash +# Make the script executable +chmod +x agent.py + +# Run the agent +./agent.py +``` + +## What It Does + +1. Queries for ready work (no blocking dependencies) +2. Claims the highest priority task +3. "Works" on the task (simulated) +4. If the task involves implementation, discovers a testing task +5. Creates the new testing task and links it with `discovered-from` +6. Completes the original task +7. Repeats until no ready work remains + +## Example Output + +``` +🚀 Beads Agent starting... + +============================================================ +Iteration 1/10 +============================================================ + +📋 Claiming task: bd-1 +🤖 Working on: Implement user authentication (bd-1) + Priority: 1, Type: feature + +💡 Discovered: Missing test coverage for this feature +✨ Creating issue: Add tests for Implement user authentication +🔗 Linking bd-2 ← discovered-from ← bd-1 +✅ Completing task: bd-1 - Implemented successfully + +🔄 New work discovered and linked. Running another cycle... +``` + +## Integration with Real Agents + +To integrate with a real LLM-based agent: + +1. Replace `simulate_work()` with actual LLM calls +2. Parse the LLM's response for discovered issues/bugs +3. Use the issue ID to track context across conversations +4. Export/import JSONL to share state across agent sessions + +## Advanced Usage + +```python +# Create an agent with custom behavior +agent = BeadsAgent() + +# Find specific types of work +ready = agent.run_bd("ready", "--priority", "1", "--assignee", "bot") + +# Create issues with labels +agent.run_bd("create", "New task", "-l", "urgent,backend") + +# Query dependency tree +tree = agent.run_bd("dep", "tree", "bd-1") +``` + +## See Also + +- [../bash-agent/](../bash-agent/) - Bash version of this example +- [../claude-desktop-mcp/](../claude-desktop-mcp/) - MCP server for Claude Desktop diff --git a/examples/python-agent/agent.py b/examples/python-agent/agent.py new file mode 100755 index 00000000..851430df --- /dev/null +++ b/examples/python-agent/agent.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +""" +Simple AI agent workflow using bd (Beads issue tracker). + +This demonstrates how an agent can: +1. Find ready work +2. Claim and execute tasks +3. Discover new issues during work +4. Link discoveries back to parent tasks +5. Complete work and move on +""" + +import json +import subprocess +import sys +from typing import Optional + + +class BeadsAgent: + """Simple agent that manages tasks using bd.""" + + def __init__(self): + self.current_task = None + + def run_bd(self, *args) -> dict: + """Run bd command and parse JSON output.""" + cmd = ["bd"] + list(args) + ["--json"] + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + + if result.stdout.strip(): + return json.loads(result.stdout) + return {} + + def find_ready_work(self) -> Optional[dict]: + """Find the highest priority ready work.""" + ready = self.run_bd("ready", "--limit", "1") + + if isinstance(ready, list) and len(ready) > 0: + return ready[0] + return None + + def claim_task(self, issue_id: str) -> dict: + """Claim a task by setting status to in_progress.""" + print(f"📋 Claiming task: {issue_id}") + return self.run_bd("update", issue_id, "--status", "in_progress") + + def create_issue(self, title: str, description: str = "", + priority: int = 2, issue_type: str = "task") -> dict: + """Create a new issue.""" + print(f"✨ Creating issue: {title}") + args = ["create", title, "-p", str(priority), "-t", issue_type] + if description: + args.extend(["-d", description]) + return self.run_bd(*args) + + def link_discovery(self, discovered_id: str, parent_id: str): + """Link a discovered issue back to its parent.""" + print(f"🔗 Linking {discovered_id} ← discovered-from ← {parent_id}") + subprocess.run( + ["bd", "dep", "add", discovered_id, parent_id, "--type", "discovered-from"], + check=True + ) + + def complete_task(self, issue_id: str, reason: str = "Completed"): + """Mark task as complete.""" + print(f"✅ Completing task: {issue_id} - {reason}") + return self.run_bd("close", issue_id, "--reason", reason) + + def simulate_work(self, issue: dict) -> bool: + """Simulate doing work on an issue. + + In a real agent, this would call an LLM, execute code, etc. + Returns True if work discovered new issues. + """ + issue_id = issue["id"] + title = issue["title"] + + print(f"\n🤖 Working on: {title} ({issue_id})") + print(f" Priority: {issue['priority']}, Type: {issue['issue_type']}") + + # Simulate discovering a bug while working + if "implement" in title.lower() or "add" in title.lower(): + print("\n💡 Discovered: Missing test coverage for this feature") + new_issue = self.create_issue( + f"Add tests for {title}", + description=f"While implementing {issue_id}, noticed missing tests", + priority=1, + issue_type="task" + ) + self.link_discovery(new_issue["id"], issue_id) + return True + + return False + + def run_once(self) -> bool: + """Execute one work cycle. Returns True if work was found.""" + # Find ready work + issue = self.find_ready_work() + + if not issue: + print("📭 No ready work found.") + return False + + # Claim the task + self.claim_task(issue["id"]) + + # Do the work (simulated) + discovered_new_work = self.simulate_work(issue) + + # Complete the task + self.complete_task(issue["id"], "Implemented successfully") + + if discovered_new_work: + print("\n🔄 New work discovered and linked. Running another cycle...") + + return True + + def run(self, max_iterations: int = 10): + """Run the agent for multiple iterations.""" + print("🚀 Beads Agent starting...\n") + + for i in range(max_iterations): + print(f"\n{'='*60}") + print(f"Iteration {i+1}/{max_iterations}") + print(f"{'='*60}") + + if not self.run_once(): + break + + print("\n✨ Agent finished!") + + +def main(): + """Main entry point.""" + try: + agent = BeadsAgent() + agent.run() + except subprocess.CalledProcessError as e: + print(f"Error running bd: {e}", file=sys.stderr) + print(f"Make sure bd is installed: go install github.com/steveyegge/beads/cmd/bd@latest") + sys.exit(1) + except KeyboardInterrupt: + print("\n\n👋 Agent interrupted by user") + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/install.sh b/install.sh new file mode 100755 index 00000000..277cf2a1 --- /dev/null +++ b/install.sh @@ -0,0 +1,232 @@ +#!/usr/bin/env bash +# +# Beads (bd) installation script +# Usage: curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/install.sh | bash +# + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${BLUE}==>${NC} $1" +} + +log_success() { + echo -e "${GREEN}==>${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}==>${NC} $1" +} + +log_error() { + echo -e "${RED}Error:${NC} $1" >&2 +} + +# Detect OS and architecture +detect_platform() { + local os arch + + case "$(uname -s)" in + Darwin) + os="darwin" + ;; + Linux) + os="linux" + ;; + *) + log_error "Unsupported operating system: $(uname -s)" + exit 1 + ;; + esac + + case "$(uname -m)" in + x86_64|amd64) + arch="amd64" + ;; + aarch64|arm64) + arch="arm64" + ;; + *) + log_error "Unsupported architecture: $(uname -m)" + exit 1 + ;; + esac + + echo "${os}-${arch}" +} + +# Check if Go is installed +check_go() { + if command -v go &> /dev/null; then + log_info "Go detected: $(go version)" + return 0 + else + return 1 + fi +} + +# Install using go install +install_with_go() { + log_info "Installing bd using 'go install'..." + + if go install github.com/steveyegge/beads/cmd/bd@latest; then + log_success "bd installed successfully via go install" + + # Check if GOPATH/bin is in PATH + local gopath_bin="$(go env GOPATH)/bin" + if [[ ":$PATH:" != *":$gopath_bin:"* ]]; then + log_warning "GOPATH/bin is not in your PATH" + echo "" + echo "Add this to your shell profile (~/.bashrc, ~/.zshrc, etc.):" + echo " export PATH=\"\$PATH:$gopath_bin\"" + echo "" + fi + + return 0 + else + log_error "go install failed" + return 1 + fi +} + +# Build from source +build_from_source() { + log_info "Building bd from source..." + + local tmp_dir + tmp_dir=$(mktemp -d) + + cd "$tmp_dir" + log_info "Cloning repository..." + + if git clone --depth 1 https://github.com/steveyegge/beads.git; then + cd beads + log_info "Building binary..." + + if go build -o bd ./cmd/bd; then + # Determine install location + local install_dir + if [[ -w /usr/local/bin ]]; then + install_dir="/usr/local/bin" + else + install_dir="$HOME/.local/bin" + mkdir -p "$install_dir" + fi + + log_info "Installing to $install_dir..." + if [[ -w "$install_dir" ]]; then + mv bd "$install_dir/" + else + sudo mv bd "$install_dir/" + fi + + log_success "bd installed to $install_dir/bd" + + # Check if install_dir is in PATH + if [[ ":$PATH:" != *":$install_dir:"* ]]; then + log_warning "$install_dir is not in your PATH" + echo "" + echo "Add this to your shell profile (~/.bashrc, ~/.zshrc, etc.):" + echo " export PATH=\"\$PATH:$install_dir\"" + echo "" + fi + + cd - > /dev/null + rm -rf "$tmp_dir" + return 0 + else + log_error "Build failed" + cd - > /dev/null + rm -rf "$tmp_dir" + return 1 + fi + else + log_error "Failed to clone repository" + rm -rf "$tmp_dir" + return 1 + fi +} + +# Install Go if not present (optional) +offer_go_installation() { + log_warning "Go is not installed" + echo "" + echo "bd requires Go 1.21 or later. You can:" + echo " 1. Install Go from https://go.dev/dl/" + echo " 2. Use your package manager:" + echo " - macOS: brew install go" + echo " - Ubuntu/Debian: sudo apt install golang" + echo " - Other Linux: Check your distro's package manager" + echo "" + echo "After installing Go, run this script again." + exit 1 +} + +# Verify installation +verify_installation() { + if command -v bd &> /dev/null; then + log_success "bd is installed and ready!" + echo "" + bd version 2>/dev/null || echo "bd (development build)" + echo "" + echo "Get started:" + echo " cd your-project" + echo " bd init" + echo " bd quickstart" + echo "" + return 0 + else + log_error "bd was installed but is not in PATH" + return 1 + fi +} + +# Main installation flow +main() { + echo "" + echo "🔗 Beads (bd) Installer" + echo "" + + log_info "Detecting platform..." + local platform + platform=$(detect_platform) + log_info "Platform: $platform" + + # Try go install first + if check_go; then + if install_with_go; then + verify_installation + exit 0 + fi + fi + + # If go install failed or Go not present, try building from source + log_warning "Falling back to building from source..." + + if ! check_go; then + offer_go_installation + fi + + if build_from_source; then + verify_installation + exit 0 + fi + + # All methods failed + log_error "Installation failed" + echo "" + echo "Manual installation:" + echo " 1. Install Go from https://go.dev/dl/" + echo " 2. Run: go install github.com/steveyegge/beads/cmd/bd@latest" + echo "" + exit 1 +} + +main "$@"