The status filter was treating 'all' as a literal status value instead of
a special case meaning 'show all statuses'. This caused the SQL query to
filter for 'WHERE status = all' which matched no issues.
Fixed by checking if status is 'all' and skipping the filter in that case.
- Fix list.go to skip status filter when status == 'all'
- Update CHANGELOG with fix details
- All tests pass
- Add DeleteIssues() method in sqlite.go for atomic batch deletion
- Support multiple issue IDs as arguments or from file
- Add --from-file flag to read IDs from file (supports comments)
- Add --dry-run mode for safe preview without deleting
- Add --cascade flag for recursive deletion of dependents
- Add --force flag to orphan dependents instead of failing
- Pre-collect connected issues before deletion for text reference updates
- Add orphan deduplication to prevent duplicate IDs
- Add rows.Err() checks in all row iteration loops
- Full transaction safety - all deletions succeed or none do
- Comprehensive statistics tracking (deleted, dependencies, labels, events)
- Update README and CHANGELOG with batch deletion docs
Fixed critical code review issues:
- Dry-run mode now properly uses dryRun parameter instead of deleting data
- Text references are pre-collected before deletion so they update correctly
- Added orphan deduplication and error checks
- Updated defer rollback pattern per Go best practices
- MCP server now uses daemon client by default with CLI fallback
- Added BEADS_USE_DAEMON environment variable (default: enabled)
- Created multi-repo integration test (all tests pass)
- Updated .gitignore for daemon runtime files
- Added SETUP_DAEMON.md with migration instructions
- Closed bd-105 (investigation complete) and bd-114 (multi-server confusion)
This enables single MCP server to handle multiple repos via daemon
with per-request context routing. No more multiple MCP server configs!
Amp-Thread-ID: https://ampcode.com/threads/T-c222692e-f6ef-4649-9726-db59470b82ef
Co-authored-by: Amp <amp@ampcode.com>
- Added per-request storage routing in daemon server
- Server now supports Cwd field in requests for database discovery
- Tree-walking to find .beads/*.db from any working directory
- Storage caching for performance across requests
- Created Python daemon client (bd_daemon_client.py)
- RPC over Unix socket communication
- Implements full BdClientBase interface
- Auto-discovery of daemon socket from working directory
- Refactored bd_client.py with abstract interface
- BdClientBase abstract class for common interface
- BdCliClient for CLI-based operations (renamed from BdClient)
- create_bd_client() factory with daemon/CLI fallback
- Backwards-compatible BdClient alias
Next: Update MCP server to use daemon client when available
The 'blocked' command doesn't have RPC support in the daemon yet.
When the daemon is running, store is nil, causing a panic.
This fix detects when daemon is running but store is nil, and opens
a direct database connection as a fallback. This allows the command
to work even when the daemon is active, until proper RPC support
is added.
The statsCmd was not checking if a daemon client was available before
trying to access the store directly. When the daemon is running, store
is nil, causing a panic.
This fix adds a check for daemonClient and uses RPC to get statistics
when the daemon is available, falling back to direct store access only
when running in direct mode.
Multiple dep commands were directly accessing store without checking if
daemon was available, causing nil pointer dereferences when daemon was
running.
Fixed commands:
- dep add: Now uses RPC when daemon is available
- dep remove: Now uses RPC when daemon is available
- dep tree: Added fallback to direct storage when daemon lacks RPC support
- dep cycles: Added fallback to direct storage when daemon lacks RPC support
The commands with RPC support (add/remove) now use the daemon client
when available. Commands without RPC support (tree/cycles) fall back
to opening a direct database connection when the daemon is running.
The vendorHash in the flake was outdated, causing build failures.
Updated to match current Go module dependencies.
Also bumped version to 0.9.9 to match current project version.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
The daemon command was failing to find the database while other commands
like 'bd list' could find it. This was because ensureBeadsDir() was not
using the same database discovery logic as other commands.
This fix updates ensureBeadsDir() to use beads.FindDatabasePath() API,
the same discovery mechanism used by all other commands, ensuring
consistent behavior across the CLI.
- Add 'bd epic status' to show epic completion with child progress
- Add 'bd epic close-eligible' to bulk-close completed epics
- Add GetEpicsEligibleForClosure() storage method
- Update 'bd stats' to show count of epics ready to close
- Add EpicStatus type for tracking epic/child relationships
- Support --eligible-only, --dry-run, and --json flags
- Fix golangci-lint config version requirement
Addresses GitHub issue #62 - epics now have visibility and
management tools for closure when all children are complete.
Amp-Thread-ID: https://ampcode.com/threads/T-e8ac3f48-f0cf-4858-8e8f-aace2481c30d
Co-authored-by: Amp <amp@ampcode.com>
Use _time_format=sqlite parameter in modernc.org/sqlite connection
string to ensure DATETIME columns use SQLite's native time format
(format 7 with timezone) instead of Go's default String() format.
This improves compatibility with SQLite's date/time functions and
ensures consistent time representation across the database.
- Create .gitignore file in .beads/ when running bd init
- Ignores *.db and *.db-* patterns to prevent database commits
- Add test coverage to verify .gitignore creation
- Add .claude/settings.local.json to project .gitignore
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Ben Madore <madorb@users.noreply.github.com>
- Remove ~/.beads/default.db fallback from FindDatabasePath()
- Update daemon to error if no database found instead of falling back
- Update main.go to require explicit database initialization
- Add help/version/quickstart to commands that don't need database
- Add MCP client debug logging for database routing
Amp-Thread-ID: https://ampcode.com/threads/T-2b757a14-cf10-400e-a83c-30349182dd82
Co-authored-by: Amp <amp@ampcode.com>
- Add TestInitCommand with subtests for default prefix, custom prefix, quiet flag, and prefix normalization
- Add TestInitAlreadyInitialized to verify re-initialization works correctly
- Tests verify database creation, config storage, and metadata
- Tests verify -q/--quiet flag suppresses output correctly
- All tests pass
The -q flag was already working correctly; this just adds test coverage.
- Add daemon client infrastructure to main.go with TryConnect logic
- Update PersistentPreRun to detect daemon socket and route through RPC
- Add --no-daemon flag to force direct storage mode
- Update all commands (create, update, close, show, list, ready) to use daemon when available
- Maintain backward compatibility with graceful fallback to direct mode
- All commands work identically in both daemon and direct modes
Part of bd-110 daemon architecture implementation.
Amp-Thread-ID: https://ampcode.com/threads/T-bfe2c083-be7c-4064-8673-fa69c22a730e
Co-authored-by: Amp <amp@ampcode.com>
The counter wasn't being properly reset after renumbering because
SyncAllCounters uses MAX(old, new) which kept higher values from
deleted issues.
Solution: Add ResetCounter() method to delete the counter entry,
then SyncAllCounters recreates it from the actual max ID in database.
Now after renumbering 108 issues to bd-1..bd-108, the counter is
correctly set to 108 and next issue will be bd-109.
After renumbering issues to bd-1 through bd-108, the counter was still
at the old value (346), causing next issue to be bd-347 instead of bd-109.
Fix: Call SyncAllCounters after renumbering to recalculate counter from
actual max ID in database.
Problem: Incremental flush merged dirty issues with existing JSONL, leaving
old IDs when issues were renamed (e.g., test-3 remained after renumbering to test-2).
Solution:
- Add needsFullExport flag to force complete JSONL rebuild from DB
- Skip loading existing JSONL when fullExport=true (start with empty map)
- Use markDirtyAndScheduleFullExport() in renumber and rename-prefix commands
- PersistentPostRun flushes immediately before process exits (respects fullExport)
Test: Verified renumber with gaps correctly exports only current IDs to JSONL
- Replace predictable temp IDs (temp-renumber-N) with UUIDs (temp-<uuid>)
- Fetch dependencies before ID updates to preserve them correctly
- Add comprehensive tests for renumbering with ID gaps, dependencies, and text refs
- All tests pass
Removed 237 issues that were accidentally added from wyvern project:
- 225 test issues (Test incremental 2, Test merged features)
- 12 wyvern deployment issues (SSL certs, Docker, OAuth, GCR, etc.)
Now down to 107 legitimate beads issues (IDs 1-344 with gaps).
Next step: renumber to compact ID space.
These commands modify issues in bulk but weren't triggering auto-export
to JSONL. This caused database and JSONL to get out of sync.
Added markDirtyAndScheduleFlush() calls to:
- bd renumber (after renumbering completes)
- bd rename-prefix (after prefix rename completes)
- bd compact (after single/batch compaction)
- bd delete (already had it)
Fixes the issue where massive cleanups weren't exported to JSONL.
Amp-Thread-ID: https://ampcode.com/threads/T-a43dc9fa-e9bc-43c7-9055-33acc08bc642
Co-authored-by: Amp <amp@ampcode.com>
- GetMetadata() failures now set lastHash='' instead of returning early
- Allows auto-import to recover from corrupt/missing metadata
- Prevents auto-import from being permanently disabled
- All tests pass
Amp-Thread-ID: https://ampcode.com/threads/T-4e4a57c4-9ac0-43dc-a78e-b7e88123cc65
Co-authored-by: Amp <amp@ampcode.com>
- Batch fetch all existing issues with SearchIssues() upfront
- Use O(1) map lookup instead of O(n) GetIssue() calls
- Improves performance dramatically with 1000+ issues
- All tests pass
- Added deduplicateIncomingIssues() to consolidate content-identical issues
- DetectCollisions now deduplicates within incoming batch before processing
- Keeps issue with smallest ID when duplicates found
- Added comprehensive test suite in collision_dedup_test.go
- Export clean JSONL with bd-421 fix applied
Amp-Thread-ID: https://ampcode.com/threads/T-c17dd8bf-c298-4a80-baa5-55fa7c7bb9a3
Co-authored-by: Amp <amp@ampcode.com>