A comprehensive Emacs interface for Beads, providing a keyboard-driven, transient-based UI for managing issues without leaving your editor.
- 📋 Tabulated List Mode: Browse issues with sortable columns (ID, status, priority, type, title)
- 🔍 Issue Detail View: Rich formatting with markdown-like rendering and clickable issue references
- ⌨️ Transient Menus: Magit-style keyboard-driven interface for all bd commands
- 🚀 Context-Aware: Automatically detects issue IDs from current buffer
- 💡 Eldoc Integration: Hover over issue references anywhere to see details
- 🎯 Complete Coverage: All bd CLI commands available through transients
- 🔗 Project Integration: Seamless integration with Emacs project.el
- Emacs: 27.1 or newer
- Dependencies:
transient(included in Emacs 28+, or install from MELPA)project(built-in)
- External:
bdexecutable in PATH
Note: beads.el is not yet available on MELPA. Until then, install from source using one of the methods below.
- Clone the repository:
git clone https://github.com/yourusername/beads.el.git ~/path/to/beads.el- Configure with use-package:
(use-package beads
:load-path "~/path/to/beads.el/lisp"
:commands (beads beads-list beads-ready beads-show beads-create)
:bind ("C-c b" . beads)
:hook (after-init . beads-eldoc-mode)) ; Enable eldoc supportFor Emacs 29 or newer, you can use the built-in package-vc feature:
(use-package beads
:vc (:fetcher github :repo "yourusername/beads.el")
:commands (beads beads-list beads-ready beads-show beads-create)
:bind ("C-c b" . beads)
:hook (after-init . beads-eldoc-mode)) ; Enable eldoc supportThis will automatically clone and install the package.
- Clone the repository:
git clone https://github.com/yourusername/beads.el.git ~/path/to/beads.el- Add to your
load-pathand require:
(add-to-list 'load-path "~/path/to/beads.el/lisp")
(require 'beads)- Optionally bind to a key:
(global-set-key (kbd "C-c b") 'beads)After cloning, byte-compile for faster loading:
cd ~/path/to/beads.el
eldev compileOr from within Emacs:
(byte-recompile-directory "~/path/to/beads.el/lisp" 0)Note: If eldev is not available, the Emacs method will still work for basic compilation.
-
Install bd CLI: Follow the installation instructions at Beads repository
-
Initialize Beads in your project (if not already done):
cd /path/to/your/project bd initOr from within Emacs:
M-x beads-init -
Verify bd is accessible: Check that
bdis in your PATH:which bd bd version
- Open Beads menu:
M-x beads(or your custom keybinding) - List issues: Press
l(list all) orr(ready issues) - Navigate: Use arrow keys or
n/pto move between issues - View issue: Press
RETorson an issue - Create issue: Press
cfrom main menu - Update issue: Press
ufrom list or show buffer - Close issue: Press
xfrom list or show buffer
Tip: Run M-x beads-quickstart to see an interactive tutorial within
Emacs, or run bd quickstart from the command line
The root transient menu provides access to all beads.el commands:
View Issues:
l- List all issues (beads-list)r- Show ready issues (beads-ready)b- Show blocked issues (beads-blocked)s- Show specific issue (beads-show)
Create/Edit:
c- Create new issue (beads-create)u- Update issue (beads-update)x- Close issue (beads-close)
Dependencies:
d- Manage dependencies (beads-dep)a- Add dependencyr- Remove dependencyt- Show dependency treel- List dependencies
Admin:
S- Show statistics (beads-stats)e- Export to JSONL (beads-export)i- Import from JSONL (beads-import)I- Initialize beads project (beads-init)
When viewing issue lists (via beads-list, beads-ready, beads-blocked):
Navigation:
n/p- Next/previous issueRET/s- Show issue detailsg- Refresh listq- Quit buffer
Sorting:
- Click column headers or use
Sto sort by different columns
Marking:
m- Mark issueu- Unmark issueM- Mark allU- Unmark all
When viewing issue details (via beads-show or pressing RET in list):
Navigation:
n/p- Next/previous sectionTAB- Jump to issue reference at point (bd-N links)g- Refresh issueq- Quit buffer
Actions:
- Issue references (bd-N) are clickable - press
RETor click to jump
beads.el provides eldoc integration that displays issue information when your cursor hovers over issue references in any buffer.
Supported Formats:
beads.el-22- Project-specific referencesbd-123- Standard Beads referencesworker-1,api-42- Anyproject-Nformat
Enable Eldoc Support:
;; Enable globally
(beads-eldoc-mode 1)What You Get:
When you position your cursor on an issue reference like beads.el-22:
- Echo area: Brief info (ID, status, title)
- Eldoc buffer: Full issue metadata (description, notes, dates, etc.)
How It Works:
- In beads buffers (list/show): Uses text properties for instant lookup
- In other buffers (code, markdown, org): Pattern matching with caching
- Performance: Issues are cached for 5 minutes (configurable)
Configuration:
;; Customize cache TTL (default: 300 seconds)
(setq beads-eldoc-cache-ttl 600) ; 10 minutes
;; Customize issue pattern (default supports all project-N formats)
(setq beads-eldoc-issue-pattern "\\b\\([a-zA-Z][a-zA-Z0-9._-]*-[0-9]+\\)\\b")Example Use Cases:
- Code comments: Hover over
;; Fix beads.el-22to see issue details - Commit messages: See issue info while writing git commits
- Org files: Get context on issues in your planning documents
- Markdown: Preview issue details in README or documentation
Tips:
- Cache automatically invalidates when you modify issues
- Works with any eldoc-compatible mode
- Combines with eldoc-box for richer display
Transient menu for creating new issues:
Basic:
-t- Issue type (bug, feature, task, epic, chore)-p- Priority (0=critical, 1=high, 2=medium, 3=low, 4=backlog)
Details:
-d- Description (supports multiline in minibuffer)-i- Custom ID (e.g., worker1-100 for parallel agents)-D- Dependencies (format: type:id,type:id)
Actions:
RET- Create issueP- Preview commandr- Reset all fields
Example workflow:
M-x beadsthenc- Enter title: "Fix authentication bug"
- Press
-tthen selectbug - Press
-pthen select1(high priority) - Press
RETto create
Context-aware transient menu for updating existing issues:
Context Detection:
- From list mode: Uses issue on current line
- From show mode: Uses displayed issue
- Otherwise: Prompts with completion
Fields:
-t- Change title-T- Change type-s- Change status (open, in_progress, blocked, closed)-p- Change priority-d- Update description-r- Set reason (for status changes)
Actions:
RET- Apply updatesP- Preview commandr- Reset all fields
Smart Updates: Only modified fields are sent to bd CLI (efficient!)
Quick transient for closing issues:
Required:
-r- Reason for closing (required field)
Actions:
RET- Close issue (with validation)r- Reset
Submenu for managing issue dependencies:
Dependency Types:
blocks- Hard dependency (affects ready queue)related- Soft relationshipparent-child- Epic/subtask hierarchydiscovered-from- Track discovery lineage
Actions:
a- Add dependency (specify from, to, type)r- Remove dependencyt- Show dependency tree (visual display)l- List dependencies for an issue
Display project statistics in special buffer:
- Issue counts by status
- Issue counts by type
- Priority breakdown
- Other metrics
Press g to refresh, q to quit.
Export (beads-export):
-o- Output path (default: .beads/issues.jsonl)--no-auto-flush- Disable automatic flushing
Import (beads-import):
-i- Input path (required)--dry-run- Preview changes without applying--resolve-collisions- Auto-resolve ID conflicts
Useful for syncing issues across branches or sharing with team.
;; Path to bd executable (default: "bd")
(setq beads-executable "/path/to/bd")
;; Database path (default: auto-discover from .beads directory)
(setq beads-db-path "/custom/path/to/beads.db")
;; Actor name for operations (default: nil, uses bd default)
(setq beads-actor "your-name")
;; Enable debug logging (default: nil)
(setq beads-enable-debug t)Full example with customization and keybindings:
(use-package beads
:load-path "~/path/to/beads.el/lisp" ; or use :vc for Emacs 29+
:commands (beads beads-list beads-ready beads-show beads-create)
:custom
(beads-executable "bd") ; path to bd executable
(beads-db-path nil) ; nil = auto-discover
(beads-actor nil) ; nil = use bd default
(beads-enable-debug nil) ; enable for troubleshooting
:bind
(("C-c b" . beads)
("C-c b l" . beads-list)
("C-c b r" . beads-ready)
("C-c b c" . beads-create)
("C-c b s" . beads-show))
:hook (after-init . beads-eldoc-mode)) ; Enable eldoc support;; Open beads for current project
(defun my/beads-for-project ()
"Open beads main menu for current project."
(interactive)
(let ((default-directory (projectile-project-root)))
(beads)))
(define-key projectile-command-map "b" 'my/beads-for-project)| Command | Default Key | Context | Description |
|---|---|---|---|
beads |
- | Global | Open main menu |
beads-list |
l |
Main menu | List all issues |
beads-ready |
r |
Main menu | Show ready issues |
beads-blocked |
b |
Main menu | Show blocked issues |
beads-show |
s or RET |
List mode | Show issue details |
beads-create |
c |
Main menu | Create new issue |
beads-update |
u |
Main menu | Update issue |
beads-close |
x |
Main menu | Close issue |
beads-dep |
d |
Main menu | Dependency submenu |
beads-stats |
S |
Main menu | Show statistics |
beads-export |
e |
Main menu | Export to JSONL |
beads-import |
i |
Main menu | Import from JSONL |
beads-init |
I |
Main menu | Initialize project |
Within list/show buffers:
n/p- Navigateg- Refreshq- QuitRET- Show/follow
| Task | CLI Command | beads.el Workflow |
|---|---|---|
| List ready issues | bd ready |
M-x beads-ready |
| Create issue | bd create "Title" -t bug |
M-x beads-create |
| Update status | bd update bd-42 -s ... |
M-x beads-update |
| Show issue | bd show bd-42 |
M-x beads-show |
| Add dependency | bd dep add ... |
M-x beads-dep then a |
| Show dependency tree | bd dep tree bd-1 |
M-x beads-dep then t |
| Close issue | bd close bd-42 -r ... |
M-x beads-close |
| View statistics | bd stats |
M-x beads-stats |
Advantages of beads.el:
- No need to remember CLI syntax
- Context-aware (auto-detects issue IDs)
- Visual feedback with colors and formatting
- Keyboard-driven (no mouse required)
- Transient menus show all available options
- Clickable references between issues
- Integrated with Emacs workflow
Error: Beads: bd executable not found
Solution: Ensure bd is in your PATH, or set beads-executable:
(setq beads-executable "/full/path/to/bd")Error: Could not find .beads directory
Solution: Run M-x beads-init to initialize beads in your project, or
navigate to a directory containing a .beads folder.
Error: Failed to parse JSON output
Solution: Ensure your bd CLI is up-to-date. All beads.el commands use
--json flag which requires bd with JSON support.
Debug: Enable debug logging to see raw bd output:
(setq beads-enable-debug t)
;; Check *beads-debug* buffer for detailsError: Cannot find transient library
Solution: Install transient from MELPA:
(use-package transient :ensure t)Or upgrade to Emacs 28+ where transient is built-in.
Symptoms: Commands take several seconds to complete
Solutions:
- Check bd CLI performance directly:
time bd list --json - Ensure database is not corrupted:
bd export -o backup.jsonl - Reduce issue count if database is very large (>10k issues)
- Check disk I/O if database is on slow filesystem
Solution: Ensure your Emacs uses UTF-8 encoding:
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)lisp/
├── beads.el # Core: process, JSON, project
├── beads-list.el # Tabulated list mode
├── beads-show.el # Issue detail view
├── beads-eldoc.el # Eldoc integration for issue refs
├── beads-create.el # Create transient
├── beads-update.el # Update transient
├── beads-misc.el # Misc transients (close/dep/stats/etc)
├── beads-main.el # Root transient menu
├── Makefile # Test runner
└── test/
├── beads-test.el # Core functionality tests
├── beads-list-test.el # List mode tests
├── beads-show-test.el # Show mode tests
├── beads-eldoc-test.el # Eldoc integration tests
├── beads-create-test.el # Create transient tests
├── beads-update-test.el # Update transient tests
├── beads-close-test.el # Close transient tests
├── beads-main-test.el # Main menu tests
└── beads-misc-test.el # Misc commands tests
Process Execution:
- Synchronous:
beads--run-commandfor quick operations - All commands use
--jsonflag for structured output - Error handling with user-friendly messages
Caching:
- Project root cached per directory
- Version info cached globally
- Database path cached per project
Context Detection:
- Check
major-modeto determine context - Extract issue ID from buffer name or current line
- Fall back to
completing-readwhen needed
Transient Menus:
- Infixes for arguments (stored in global state)
- Suffixes for actions (execute commands)
- Validation before execution
- Reset commands to clear state
# Run all tests
eldev test
# Run tests with verbose output
eldev -p -dtT test
# Run specific test file
eldev test test/beads-list-test.el
# Run tests with coverage
eldev test --coverage- Total tests: 883
- Overall coverage: >75%
- Core modules: >80%
- UI modules: >70%
- Eldoc module: >85%
All tests use mocking to avoid requiring a real bd database.
Contributions are welcome! Please:
- Add tests for new features
- Update README if adding user-facing functionality
- Follow conventions:
- Use
beads--prefix for internal functions - Use
beads-prefix for public functions - Add docstrings to all public functions
- Use 80-column width for code
- Use
- Run tests before submitting:
eldev test
- No real-time updates: Must manually refresh (
g) to see changes - No multi-selection: Marking issues is limited to visual feedback
- No inline editing: Must use transient menus to modify issues
- No undo: Operations execute immediately (use bd CLI to revert if needed)
Future improvements tracked in project issues.
Same license as the Beads project.
- Beads - The CLI issue tracker: https://github.com/steveyegge/beads
- Magit - Git porcelain that inspired this interface
- Org-mode - Alternative approach to issue tracking in Emacs
Built with ❤️ by the Beads team and AI-assisted coding.
Uses the excellent transient library by Jonas Bernoulli.