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)W- Worktree management (beads-worktree-menu)
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 an interactive buffer:
- Total issues
- Issue counts by status (Open, In Progress, Blocked, Closed)
- Ready to work issues
- Average lead time
Interactive Features:
All statistic numbers are clickable! Click on any number to instantly view those issues in a filtered list:
- Click Total Issues → View all issues
- Click Open → View open issues only
- Click In Progress → View in-progress issues only
- Click Blocked → View blocked issues
- Click Closed → View closed issues
- Click Ready → View ready-to-work issues
Keyboard Shortcuts:
g- Refresh statisticsq- Quit statistics buffer
Example Workflow:
- Run
M-x beads-stats(orSfrom beads-main menu) - See at-a-glance view of project health
- Click on "Open: 30" to see all open issues
- Work on issues, then return to stats with
M-x beads-stats - Click on "Ready: 15" to find next issue to work on
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")
;; Default limit for list operations (default: 0, meaning no limit)
;; Set to a positive integer to limit the number of issues returned
(setq beads-list-default-limit 50)
;; 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-list-default-limit 0) ; 0 = no limit
(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 |
beads-worktree-menu |
W |
Main menu | Worktree management |
beads-agent-sling |
w |
Agent menu | Sling to worktree |
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
beads.el includes integration with AI coding agents, allowing you to start agents that work on issues directly from Emacs. The agent system uses sesman for session management, providing context-aware session selection.
- Start an agent on an issue from
beads-listorbeads-show: pressA - Jump to agent buffer:
M-x beads-agent-jump - Stop an agent:
M-x beads-agent-stop - Browse sessions:
M-x beads-sesman-browser
Each agent session is associated with:
- Issue ID: The beads issue being worked on
- Backend: The AI agent implementation (e.g.,
claude-code-ide) - Working Directory: Either the main project or a git worktree
Session Naming: Sessions are named <issue-id>@<directory>, e.g.,
beads.el-42@~/projects/beads.el/.
Sessions are linked to three context types:
- Agent buffer: The terminal buffer where the AI agent runs
- Worktree directory (primary): When using git worktrees, the session is linked to the worktree directory
- Main project (fallback): Also linked to the main repository for context from anywhere in the project
This triple linking means sesman automatically selects the right session whether you're in the agent buffer, editing files in the worktree, or working anywhere in the project.
When beads-agent-use-worktrees is enabled (default: t), each agent session
gets its own git worktree:
- Worktrees are created as siblings to the main repo
- Named after the issue ID (e.g.,
~/projects/beads.el-42/) - Branch is created with the same name as the issue ID
- Issues are automatically imported from the main repo's JSONL
This provides isolation between concurrent agent sessions.
The beads-sesman-map provides these commands (bind to a prefix like C-c C-s):
| Key | Command | Description |
|---|---|---|
s |
beads-sesman-start |
Start new session |
q |
beads-sesman-quit |
Quit current session |
r |
beads-sesman-restart |
Restart current session |
b |
beads-sesman-browser |
Open session browser |
l |
beads-sesman-link |
Link session to context |
Example configuration:
(use-package beads
:load-path "~/path/to/beads.el/lisp"
:bind-keymap ("C-c C-s" . beads-sesman-map))
;; Sesman integration is automatically enabled when beads-sesman is loadedThe agent transient menu (M-x beads-agent) provides:
Agent Actions:
s- Start agent on issuew- Sling to worktree (flexible agent assignment)S- Stop agent sessionj- Jump to agent bufferp- Send prompt to agent
Session Management:
l- List active sessionsc- Cleanup stale sessions
M-x beads-sesman-browser opens an interactive buffer showing all sessions:
beads.el-42@~/projects/beads.el-42
Issue: beads.el-42
Backend: claude-code-ide
Started: 2025-12-14T10:30:00+0100
Worktree: ~/projects/beads.el-42
beads.el-43@~/projects/beads.el-43
Issue: beads.el-43
Backend: claude-code-ide
Started: 2025-12-14T11:00:00+0100
Worktree: ~/projects/beads.el-43
From the browser, you can:
- Select a session to make it current
- Quit sessions
- Link sessions to buffers/directories
;; Use default backend without prompting
(setq beads-agent-default-backend "claude-code-ide")
;; Disable automatic status update to in_progress
(setq beads-agent-auto-set-in-progress nil)
;; Disable worktree creation (work in main repo)
(setq beads-agent-use-worktrees nil)
;; Custom worktree parent directory
(setq beads-agent-worktree-parent "~/worktrees/")
;; Configure restart delay (seconds)
(setq beads-sesman-restart-delay 0.5)Currently implemented:
- claude-code-ide: Integration with Claude Code via claude-code-ide.el
Placeholder backends (not yet implemented):
- efrit
- claudemacs
- claude-code.el
To use AI agents, you need:
- Install claude-code-ide.el package
- Install Claude Code CLI:
npm install -g @anthropic-ai/claude-code - Ensure
claudecommand is in your PATH
The sling workflow (M-x beads-agent-sling or w from agent menu) provides
flexible agent assignment to worktrees. This enables parallel development with
multiple agents working in isolated worktrees.
Workflow Options:
- New Worktree: Create a new worktree and start an agent there
- Existing Worktree: Start an agent in a pre-existing worktree
Menu Options:
N- Select "New worktree" modeE- Select "Existing worktree" modei- Set issue (optional - agent can work without specific issue)n- Set worktree name (defaults to issue ID if set)e- Select existing worktree from listb- Select backendx- Execute sling (start agent)v- Preview configurationR- Reset all fields
Example: Sling issue to new worktree:
M-x beads-agent-sling(orwfrom agent menu)- Press
iand select an issue (e.g.,beads.el-42) - Press
Nto select "New worktree" mode (name auto-defaults to issue ID) - Press
xto create worktree and start agent
Example: Sling to existing worktree:
M-x beads-agent-sling- Press
Eto select "Existing worktree" mode - Press
eand select a worktree from the completion list - Optionally press
ito associate with an issue - Press
xto start agent in the selected worktree
beads.el provides a transient menu for managing git worktrees with beads integration. Worktrees allow multiple working directories sharing the same git repository, enabling parallel development.
Access via M-x beads-worktree-menu or W from the main beads menu.
Create Worktree:
-n- Worktree name (completion suggests issue IDs)-b- Branch name (optional, defaults to worktree name)
Remove Worktree:
-t- Target worktree to remove-f- Force removal (skip safety checks)
Actions:
c- Create worktreel- List all worktreesr- Remove worktreei- Info about current worktree
The l command opens a tabulated list showing all worktrees:
| Column | Description |
|---|---|
| Name | Worktree name |
| Branch | Git branch |
| State | Beads state (shared/redirect/none) |
| Main | Whether this is the main repository |
| Path | Filesystem path |
Keybindings in list:
RET- Show worktree infod- Remove worktree at pointg- Refresh listc- Create new worktreeq- Quit
When creating worktrees via bd worktree create, beads automatically sets up
a redirect file so all worktrees share the same .beads database:
- shared: Main repository with the actual
.beadsdirectory - redirect: Worktree with
.beads/redirectpointing to main repo - none: Directory without beads integration
This ensures consistent issue state across all worktrees.
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
├── beads-agent.el # AI agent integration
├── beads-worktree.el # Worktree management transient
├── beads-command-worktree.el # EIEIO classes for bd worktree
├── beads-completion.el # Completion tables and helpers
├── beads-reader.el # Reader functions for transient infixes
├── 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
├── beads-agent-test.el # Agent integration tests
└── beads-worktree-test.el # Worktree menu tests
Process Execution:
- EIEIO command classes:
beads-command,beads-command-list, etc. - 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: 2889
- Overall coverage: >75%
- Core modules: >80%
- UI modules: >70%
- Agent modules: >80%
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.