Skip to content

Commit ac987ad

Browse files
ElleNajtclaude
andcommitted
Support Claude Code hooks with org-mode task tracking
- Add claude-code-event-hook system for unified event handling - Implement claude-code-org-notifications.el for persistent task tracking - Add smart notification system with queue management and workspace integration - Support auto-advance queue mode for streamlined task processing - Include perspective.el integration for workspace navigation - Add comprehensive documentation for hooks and notification features 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 8e79be3 commit ac987ad

4 files changed

Lines changed: 886 additions & 130 deletions

File tree

CHANGELOG.md

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,6 @@
22

33
All notable changes to claude-code.el will be documented in this file.
44

5-
### [0.4.3]
6-
7-
### Added
8-
- New `claude-code-vterm-multiline-delay` customization variable to control the delay before processing buffered vterm output
9-
- Default value changed from 0.001 to 0.01 seconds (10ms) to better reduce flickering
10-
- Allows fine-tuning the balance between flickering reduction and responsiveness
11-
12-
### Fixed
13-
- Fix bug in eat keybindings
14-
15-
## [0.4.2]
16-
17-
### Changed
18-
- File references now use `@file:line` format instead of verbose context format
19-
20-
## [0.4.1]
21-
22-
### Changed
23-
- upgrade to the latest transient release
24-
255
## [0.4.0]
266

277
### Changed

README.md

Lines changed: 144 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ An Emacs interface for [Claude Code CLI](https://github.com/anthropics/claude-co
1414
- **Continue Conversations** - Resume previous sessions or fork to earlier points
1515
- **Read-Only Mode** - Toggle to select and copy text with normal Emacs commands and keybindings
1616
- **Mode Cycling** - Quick switch between default, auto-accept edits, and plan modes
17-
- **Desktop Notifications** - Get notified when Claude finishes processing
17+
- **Enhanced Notifications** - Clickable notifications with optional Org mode task tracking
18+
- **Workspace Integration** - Navigate to workspaces containing Claude buffers with perspective.el support
1819
- **Terminal Choice** - Works with both eat and vterm backends
1920
- **Fully Customizable** - Configure keybindings, notifications, and display preferences
2021

@@ -26,6 +27,7 @@ An Emacs interface for [Claude Code CLI](https://github.com/anthropics/claude-co
2627
- [Claude Code CLI](https://github.com/anthropics/claude-code) installed and configured
2728
- Required: transient (0.7.5+)
2829
- Optional: eat (0.9.2+) for eat backend, vterm for vterm backend
30+
- Optional: perspective.el for workspace navigation features
2931

3032
### Using builtin use-package (Emacs 30+)
3133

@@ -220,6 +222,20 @@ You can change this behavior by customizing `claude-code-newline-keybinding-styl
220222
- `claude-code-send-2` (`C-c c 2`) - Send "2" to Claude (useful for selecting the second option when Claude presents a numbered menu)
221223
- `claude-code-send-3` (`C-c c 3`) - Send "3" to Claude (useful for selecting the third option when Claude presents a numbered menu)
222224

225+
#### Workspace Navigation Commands
226+
227+
- `claude-code-goto-recent-workspace` (`C-c c w`) - Go to the most recent workspace from the taskmaster org file
228+
- `claude-code-goto-recent-workspace-and-clear` (`C-c c W`) - Go to the most recent workspace and mark the org entry as DONE
229+
230+
#### Queue Management Commands
231+
232+
- `claude-code-queue-browse` (`C-c c q`) - Browse and select from the task queue using minibuffer completion
233+
- `claude-code-queue-next` - Navigate to the next entry in the task queue
234+
- `claude-code-queue-previous` - Navigate to the previous entry in the task queue
235+
- `claude-code-queue-skip` - Skip (delete) the current queue entry and advance to the next
236+
- `claude-code-queue-status` - Show current queue position and total number of entries
237+
- `claude-code-toggle-auto-advance-queue` - Toggle auto-advance mode on/off
238+
223239
## Desktop Notifications
224240

225241
claude-code.el notifies you when Claude finishes processing and is waiting for input. By default, it displays a message in the minibuffer and pulses the modeline for visual feedback.
@@ -290,113 +306,133 @@ For Windows, you can use PowerShell to create toast notifications:
290306

291307
*Note: Linux and Windows examples are untested. Feedback and improvements are welcome!*
292308

293-
### Claude Code Hooks Integration
309+
### Enhanced Notification System
310+
311+
The enhanced notification system provides smart, context-aware notifications with queue management:
294312

295-
claude-code.el provides integration to **receive** hook events from Claude Code CLI via emacsclient.
313+
- **Smart Visibility Detection**: Popup notifications only appear when the Claude buffer is not currently visible in your active perspective
314+
- **Always Queue**: Task entries are always added to the taskmaster.org file regardless of buffer visibility
315+
- **Queue Counter**: Notifications show the current number of entries in the task queue
316+
- **Auto-dismiss**: Simple notifications auto-dismiss after 2 seconds to reduce clutter
317+
- **No Duplicates**: Each buffer is limited to one queue entry (existing entries are replaced)
318+
- **Automatic Cleanup**: Queue entries are automatically removed when Claude buffers are closed
296319

297-
See [`examples/hooks/claude-code-hook-examples.el`](examples/hooks/claude-code-hook-examples.el) for comprehensive examples of hook listeners and setup functions.
320+
### Org Mode Task Tracking
298321

299-
#### Hook API
322+
claude-code.el includes an optional Org mode integration that automatically tracks completed Claude tasks in a persistent log:
300323

301-
- `claude-code-event-hook` - Emacs hook run when Claude Code CLI triggers events
302-
- `claude-code-handle-hook` - **Unified entry point** for all Claude Code CLI hooks. Call this from your CLI hooks with `(type buffer-name &rest args)` and JSON data as additional emacsclient arguments
324+
#### Features
325+
326+
- **Persistent Task Log**: All completed Claude tasks are saved to `~/.claude/taskmaster.org`
327+
- **Automatic Timestamps**: Each task entry includes completion timestamp
328+
- **Clickable Buffer Links**: Elisp links in org entries allow instant buffer switching
329+
- **Smart Display**: Popup notifications only appear when Claude buffer is not currently visible (taskmaster.org entries are always created)
330+
- **Dual Event Tracking**: Captures both task completion and session stop events
331+
- **Automatic Queue Cleanup**: Queue entries are automatically removed when Claude buffers are closed
332+
- **No Duplicates**: Each buffer is limited to one queue entry to prevent clutter
303333

304334
#### Setup
305335

306-
Before configuring hooks, you need to start the Emacs server so that `emacsclient` can communicate with your Emacs instance:
336+
To enable Org mode notifications, add this to your configuration:
307337

308338
```elisp
309-
;; Start the Emacs server (add this to your init.el)
310-
(start-server)
339+
;; Load the org notifications system
340+
(require 'claude-code-org-notifications)
341+
342+
;; Set up the hook listener to receive events
343+
(claude-code-org-notifications-setup)
311344
312-
;; Add your hook listeners using standard Emacs functions
313-
(add-hook 'claude-code-event-hook 'my-claude-hook-listener)
345+
;; Configure Claude Code CLI hooks in settings.json (this will set up the CLI side)
346+
(claude-code-setup-hooks)
314347
```
315348

316-
#### Custom Hook Listener
349+
This will:
350+
1. Set up the Emacs hook listener to receive Claude Code events
351+
2. Create the necessary directory structure (`~/.claude/`)
352+
3. Generate or update your Claude Code settings.json with notification hooks
353+
4. Enable automatic task logging to the taskmaster.org file
354+
355+
#### Hook Integration
356+
357+
The org-mode notifications now use the new Claude Code hooks system introduced in the supportClaudeCodeHooks branch. This provides better integration and more reliable event handling.
317358

318-
Hook listeners receive a message plist with these keys:
319-
- `:type` - Hook type (e.g., `'notification`, `'stop`, `'pre-tool-use`, `'post-tool-use`)
320-
- `:buffer-name` - Claude buffer name from `$CLAUDE_BUFFER_NAME`
321-
- `:json-data` - JSON payload from Claude CLI
322-
- `:args` - List of additional arguments (when using extended configuration)
359+
#### Manual Hook Configuration
360+
361+
If you prefer to manually configure hooks or already have a settings.json file, you can call:
323362

324363
```elisp
325-
;; Define your own hook listener function
326-
(defun my-claude-hook-listener (message)
327-
"Custom listener for Claude Code hooks.
328-
MESSAGE is a plist with :type, :buffer-name, :json-data, and :args keys."
329-
(let ((hook-type (plist-get message :type))
330-
(buffer-name (plist-get message :buffer-name))
331-
(json-data (plist-get message :json-data))
332-
(args (plist-get message :args)))
333-
(cond
334-
((eq hook-type 'notification)
335-
(message "Claude is ready in %s! JSON: %s" buffer-name json-data))
336-
((eq hook-type 'stop)
337-
(message "Claude finished in %s! JSON: %s" buffer-name json-data))
338-
(t
339-
(message "Claude hook: %s with JSON: %s" hook-type json-data)))))
340-
341-
;; Add the hook listener using standard Emacs hook functions
342-
(add-hook 'claude-code-event-hook 'my-claude-hook-listener)
364+
(claude-code-setup-hooks)
343365
```
344366

345-
See the examples file for complete listeners that demonstrate notifications, logging, org-mode integration, and using extra arguments from the `:args` field.
346-
347-
#### Claude Code CLI Configuration
348-
349-
Configure Claude Code CLI hooks to call `claude-code-handle-hook` via emacsclient by passing JSON data as an additional argument:
350-
351-
```json
352-
{
353-
"hooks": {
354-
"Notification": [
355-
{
356-
"matcher": "",
357-
"hooks": [
358-
{
359-
"type": "command",
360-
"command": "emacsclient --eval \"(claude-code-handle-hook 'notification \\\"$CLAUDE_BUFFER_NAME\\\")\" \"$(cat)\""
361-
}
362-
]
363-
}
364-
],
365-
"Stop": [
366-
{
367-
"matcher": "",
368-
"hooks": [
369-
{
370-
"type": "command",
371-
"command": "emacsclient --eval \"(claude-code-handle-hook 'stop \\\"$CLAUDE_BUFFER_NAME\\\")\" \"$(cat)\""
372-
}
373-
]
374-
}
375-
]
376-
}
377-
}
378-
```
367+
This function intelligently merges notification hooks with your existing configuration.
368+
369+
#### Hook Context Variables
370+
371+
Claude Code automatically exports the `CLAUDE_BUFFER_NAME` environment variable to the shell session, making it available to hooks and child processes. This allows hooks to:
372+
373+
- Identify which Claude buffer triggered the notification
374+
- Pass buffer context to external notification handlers
375+
- Enable buffer-specific actions in custom scripts
376+
377+
The environment variable contains the full buffer name (e.g., `*claude:/path/to/project:default*`) and is automatically set when Claude starts.
378+
379+
#### Queue Browser and Navigation
380+
381+
The notification system includes a powerful queue browser for managing multiple completed tasks:
379382

380-
The command pattern:
381-
```bash
382-
emacsclient --eval "(claude-code-handle-hook 'notification \"$CLAUDE_BUFFER_NAME\")" "$(cat)" "ARG1" "ARG2" "ARG3"
383+
- **Queue Browser**: Use `C-c c q` to browse and select from the task queue using minibuffer completion
384+
- **Numbered Entries**: Tasks are displayed as numbered list (e.g., "1. *claude:/path/to/project:default*")
385+
- **Direct Navigation**: Select any queue entry to instantly jump to that Claude buffer and workspace
386+
- **Position Tracking**: The system remembers your current position in the queue across commands
387+
388+
#### Workspace Integration
389+
390+
The notification system includes workspace support that integrates with project-based workflows:
391+
392+
- **Automatic Workspace Detection**: Claude automatically detects your current project/workspace directory when starting
393+
- **Clickable Workspace Links**: Org mode entries include clickable workspace links that switch to the workspace directory
394+
- **Workspace Buttons**: Notification popups include "Open Workspace" and "Open & Clear" buttons for quick workspace switching
395+
- **Multiple Instance Support**: Works seamlessly with multiple Claude instances in the same workspace
396+
- **Keyboard Commands**: Use `C-c c w` to go to the most recent workspace or `C-c c W` to go there and clear the org entry
397+
398+
When Claude completes a task, the workspace information is automatically extracted from the buffer name and included in both the org mode log entries and notification popups. The "Open & Clear" button and `C-c c W` command allow you to quickly navigate to a workspace and mark the corresponding org entry as DONE, helping you maintain a clean task queue.
399+
400+
#### Queue Navigation Commands
401+
402+
The notification system includes several commands for navigating and managing the task queue:
403+
404+
- **Browse Queue**: Use `claude-code-queue-browse` to view and select from all queue entries using minibuffer completion
405+
- **Next Entry**: Use `claude-code-queue-next` to advance to the next entry in the queue
406+
- **Previous Entry**: Use `claude-code-queue-previous` to go back to the previous queue entry
407+
- **Skip Entry**: Use `claude-code-queue-skip` to delete the current queue entry and advance to the next
408+
- **Queue Status**: Use `claude-code-queue-status` to show your current position and total queue size
409+
410+
These commands maintain queue position tracking, so you can navigate through your completed tasks systematically. The queue browser provides the most user-friendly interface with numbered entries and completion.
411+
412+
#### Auto-Advance Queue Mode
413+
414+
Claude-code.el includes an optional auto-advance mode for streamlined queue processing:
415+
416+
- **Auto-Advance Mode**: Enable `claude-code-auto-advance-queue` to automatically advance through the task queue
417+
- **Seamless Workflow**: When enabled, pressing enter in any Claude buffer clears it from the queue and jumps to the next waiting task
418+
- **Smart Navigation**: Automatically switches to a different Claude buffer's workspace and enters insert mode (with evil-mode)
419+
- **Intelligent Filtering**: Only advances to different Claude buffers, never stays in the current buffer
420+
- **Queue Status**: Shows remaining queue count when advancing
421+
- **Toggle Command**: Use `claude-code-toggle-auto-advance-queue` to quickly enable/disable the mode
422+
423+
To enable auto-advance mode in your configuration:
424+
425+
```elisp
426+
(setq claude-code-auto-advance-queue t)
383427
```
384428

385-
Where:
386-
- `"$(cat)"` - JSON data from stdin (always required)
387-
- `ARG1` is `"$PWD"` - current working directory
388-
- `ARG2` is `"$(date -Iseconds)"` - timestamp
389-
- `ARG3` is `"$$"` - process ID
429+
Or toggle it interactively:
390430

391-
`claude-code-handle-hook` creates a message plist sent to listeners:
392431
```elisp
393-
(list :type 'notification
394-
:buffer-name "$CLAUDE_BUFFER_NAME"
395-
:json-data "$(cat)"
396-
:args '("ARG1" "ARG2" "ARG3"))
432+
M-x claude-code-toggle-auto-advance-queue
397433
```
398434

399-
See the [Claude Code hooks documentation](https://docs.anthropic.com/en/docs/claude-code/hooks) for details on setting up CLI hooks.
435+
This mode is perfect for processing multiple completed Claude tasks efficiently - just respond to each task and you'll automatically be taken to the next different one. The system ensures you never get stuck in the same buffer and always advance to a truly different Claude instance.
400436

401437
## Tips and Tricks
402438

@@ -410,19 +446,19 @@ See the [Claude Code hooks documentation](https://docs.anthropic.com/en/docs/cla
410446
(setq auto-revert-use-notify nil)
411447
```
412448

413-
## Customization
449+
## Customization {#customization}
414450

415451
```elisp
416-
;; Set your key binding for the command map.
452+
;; Set your key binding for the command map
417453
(global-set-key (kbd "C-c C-a") claude-code-command-map)
418454
419-
;; Set terminal type for the Claude terminal emulation (default is "xterm-256color").
420-
;; This determines terminal capabilities like color support.
421-
;; See the documentation for eat-term-name for more information.
455+
;; Set terminal type for the Claude terminal emulation (default is "xterm-256color")
456+
;; This determines terminal capabilities like color support
457+
;; See the documentation for eat-term-name for more information
422458
(setq claude-code-term-name "xterm-256color")
423459
424-
;; Change the path to the Claude executable (default is "claude").
425-
;; Useful if Claude is not in your PATH or you want to use a specific version.
460+
;; Change the path to the Claude executable (default is "claude")
461+
;; Useful if Claude is not in your PATH or you want to use a specific version
426462
(setq claude-code-program "/usr/local/bin/claude")
427463
428464
;; Set command line arguments for Claude
@@ -433,28 +469,28 @@ See the [Claude Code hooks documentation](https://docs.anthropic.com/en/docs/cla
433469
(add-hook 'claude-code-start-hook 'my-claude-setup-function)
434470
435471
;; Adjust initialization delay (default is 0.1 seconds)
436-
;; This helps prevent terminal layout issues if the buffer is displayed before Claude is fully ready.
472+
;; This helps prevent terminal layout issues if the buffer is displayed before Claude is fully ready
437473
(setq claude-code-startup-delay 0.2)
438474
439475
;; Configure the buffer size threshold for confirmation prompt (default is 100000 characters)
440476
;; If a buffer is larger than this threshold, claude-code-send-region will ask for confirmation
441-
;; before sending the entire buffer to Claude.
477+
;; before sending the entire buffer to Claude
442478
(setq claude-code-large-buffer-threshold 100000)
443479
444-
;; Configure key binding style for entering newlines and sending messages in Claude buffers.
480+
;; Configure key binding style for entering newlines and sending messages in Claude buffers
445481
;; Available styles:
446482
;; 'newline-on-shift-return - S-return inserts newline, RET sends message (default)
447483
;; 'newline-on-alt-return - M-return inserts newline, RET sends message
448484
;; 'shift-return-to-send - RET inserts newline, S-return sends message
449485
;; 'super-return-to-send - RET inserts newline, s-return sends message (Command+Return on macOS)
450486
(setq claude-code-newline-keybinding-style 'newline-on-shift-return)
451487
452-
;; Enable or disable notifications when Claude finishes and awaits input (default is t).
488+
;; Enable or disable notifications when Claude finishes and awaits input (default is t)
453489
(setq claude-code-enable-notifications t)
454490
455-
;; Customize the notification function (default is claude-code--default-notification).
456-
;; The function should accept two arguments: title and message.
457-
;; The default function displays a message and pulses the modeline for visual feedback.
491+
;; Customize the notification function (default is claude-code--default-notification)
492+
;; The function should accept two arguments: title and message
493+
;; The default function displays a message and pulses the modeline for visual feedback
458494
(setq claude-code-notification-function 'claude-code--default-notification)
459495
460496
;; Example: Use your own notification function
@@ -464,9 +500,9 @@ See the [Claude Code hooks documentation](https://docs.anthropic.com/en/docs/cla
464500
(message "[%s] %s" title message))
465501
(setq claude-code-notification-function 'my-claude-notification)
466502
467-
;; Configure kill confirmation behavior (default is t).
468-
;; When t, claude-code-kill prompts for confirmation before killing instances.
469-
;; When nil, kills Claude instances without confirmation.
503+
;; Configure kill confirmation behavior (default is t)
504+
;; When t, claude-code-kill prompts for confirmation before killing instances
505+
;; When nil, kills Claude instances without confirmation
470506
(setq claude-code-confirm-kill t)
471507
472508
;; Enable/disable window resize optimization (default is t)
@@ -482,6 +518,12 @@ See the [Claude Code hooks documentation](https://docs.anthropic.com/en/docs/cla
482518
;; when you run delete-other-windows or similar commands, keeping the
483519
;; Claude buffer visible and accessible.
484520
(setq claude-code-no-delete-other-windows t)
521+
522+
;; Enable auto-advance queue mode (default is nil)
523+
;; When enabled, pressing enter in a Claude buffer will clear it from the
524+
;; task queue and automatically advance to the next queue entry.
525+
;; This provides a streamlined workflow for processing multiple completed tasks.
526+
(setq claude-code-auto-advance-queue t)
485527
```
486528

487529
### Customizing Window Position
@@ -591,7 +633,6 @@ Or to apply it only to Claude buffers:
591633
(lambda ()
592634
;; Reduce line spacing to fix vertical bar gaps
593635
(setq-local line-spacing 0.1)))
594-
```
595636
596637
## Demo
597638
@@ -632,15 +673,9 @@ When using the vterm terminal backend, there are additional customization option
632673
```elisp
633674
;; Enable/disable buffering to prevent flickering on multi-line input (default is t)
634675
;; When enabled, vterm output that appears to be redrawing multi-line input boxes
635-
;; will be buffered briefly and processed in a single batch
676+
;; will be buffered briefly (1ms) and processed in a single batch
636677
;; This prevents flickering when Claude redraws its input box as it expands
637678
(setq claude-code-vterm-buffer-multiline-output t)
638-
639-
;; Control the delay before processing buffered vterm output (default is 0.01)
640-
;; This is the time in seconds that vterm waits to collect output bursts
641-
;; A longer delay may reduce flickering more but could feel less responsive
642-
;; The default of 0.01 seconds (10ms) provides a good balance
643-
(setq claude-code-vterm-multiline-delay 0.01)
644679
```
645680

646681
#### Vterm Scrollback Configuration

0 commit comments

Comments
 (0)