src.nth.io/

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Hoersten <[email protected]>2025-10-02 14:37:20 -0500
committerLuke Hoersten <[email protected]>2025-10-02 14:37:20 -0500
commit55d2fc1b3fe8e03fd6f5941017494534b374782a (patch)
tree7bc301dc3af197dfc7acecf7120f7f9b805c55d4
Initial commit.
-rw-r--r--.gitignore3
-rw-r--r--README.md174
-rw-r--r--claude-code-context.el188
-rw-r--r--claude-code-hook-example.json16
4 files changed, 381 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4fdcf6e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*~
+*.elc
+.DS_Store
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1be2357
--- /dev/null
+++ b/README.md
@@ -0,0 +1,174 @@
+# claude-code-context.el
+
+Share your Emacs buffer context automatically with [Claude Code](https://github.com/anthropics/claude-code).
+
+## Features
+
+- **Automatic context sharing**: Automatically sends your current file, line number, column, and text selection to Claude Code
+- **Flymake integration**: Optionally include linter/diagnostic output in the context
+- **Idle-timer based**: Updates context only when Emacs is idle to avoid performance impact
+- **Simple keybindings**: Easy-to-use commands for manual control
+
+## Installation
+
+### From MELPA (coming soon)
+
+```elisp
+(use-package claude-code-context
+ :config
+ (claude-code-context-mode 1))
+```
+
+### Manual Installation
+
+1. Clone this repository:
+ ```bash
+ git clone https://github.com/lhoersten/claude-code-context.git
+ ```
+
+2. Add to your Emacs configuration:
+ ```elisp
+ (add-to-list 'load-path "/path/to/claude-code-context")
+ (require 'claude-code-context)
+ (claude-code-context-mode 1)
+ ```
+
+## Configuration
+
+### Emacs Setup
+
+Add to your `init.el`:
+
+```elisp
+(require 'claude-code-context)
+
+;; Enable automatic context updates
+(claude-code-context-mode 1)
+
+;; Optional: customize the update interval (default: 2 seconds)
+(setq claude-code-context-update-interval 3)
+
+;; Optional: customize the context file location
+(setq claude-code-context-file "~/.emacs.d/claude-context.txt")
+```
+
+### Claude Code Hook Setup
+
+Add this hook configuration to your `~/.claude/settings.json`:
+
+```json
+{
+ "hooks": {
+ "UserPromptSubmit": [
+ {
+ "hooks": [
+ {
+ "type": "command",
+ "command": "CONTEXT_FILE=\"$HOME/.emacs.d/claude-context.txt\"; if [ -f \"$CONTEXT_FILE\" ]; then echo \"\\n---\\n## Emacs Context\\n\"; cat \"$CONTEXT_FILE\"; echo \"\\n---\"; fi"
+ }
+ ]
+ }
+ ]
+ }
+}
+```
+
+See [claude-code-hook-example.json](claude-code-hook-example.json) for a complete example.
+
+## Usage
+
+### Automatic Mode
+
+When `claude-code-context-mode` is enabled, your current buffer context is automatically written to `~/.emacs.d/claude-context.txt` every time Emacs is idle for the configured interval.
+
+### Manual Commands
+
+| Keybinding | Command | Description |
+|-------------|---------------------------------|------------------------------------------------|
+| `C-c C-l u` | `claude-code-update-context` | Manually update context |
+| `C-c C-l d` | `claude-code-add-diagnostics` | Add flymake diagnostics to context |
+| `C-c C-l c` | `claude-code-clear-context` | Clear the context file |
+| `C-c C-l m` | `claude-code-context-mode` | Toggle automatic context mode |
+
+### Workflow Example
+
+1. Open a file in Emacs
+2. Position your cursor where you want help
+3. Optionally select some code
+4. Use `C-c C-l d` to include any linter errors
+5. Switch to your terminal and ask Claude Code a question
+6. Claude Code will automatically see your Emacs context!
+
+## Context Format
+
+The context file includes:
+
+- **File**: Full path to the current buffer's file
+- **Line**: Current line number
+- **Column**: Current column number
+- **Selection**: Any highlighted text (if region is active)
+- **Diagnostics**: Flymake errors/warnings (when using `C-c C-l d`)
+
+Example context:
+
+```
+# Emacs Context for Claude Code
+# This file is automatically updated by Emacs
+
+File: /Users/username/project/src/main.py
+Line: 42, Column: 8
+Selection:
+```
+def process_data(items):
+ return [x * 2 for x in items]
+```
+
+Flymake Diagnostics:
+ 45 error e-f-b-c undefined variable 'result'
+ 52 warning e-f-b-c unused variable 'temp'
+```
+
+## Customization
+
+### Variables
+
+- `claude-code-context-file`: Location of the context file (default: `~/.emacs.d/claude-context.txt`)
+- `claude-code-context-update-interval`: Idle time in seconds before updating context (default: 2)
+
+### Custom Keybindings
+
+If you prefer different keybindings:
+
+```elisp
+(global-set-key (kbd "C-c u") 'claude-code-update-context)
+(global-set-key (kbd "C-c d") 'claude-code-add-diagnostics)
+```
+
+## How It Works
+
+1. **Emacs side**: This package writes your current buffer context to a file (`~/.emacs.d/claude-context.txt`)
+2. **Claude Code side**: A hook in Claude Code's settings reads this file before every prompt submission
+3. **Integration**: Claude Code automatically receives your Emacs context with each query
+
+## Troubleshooting
+
+**Context not appearing in Claude Code:**
+- Verify the hook is properly configured in `~/.claude/settings.json`
+- Check that the context file exists: `cat ~/.emacs.d/claude-context.txt`
+- Make sure `claude-code-context-mode` is enabled in Emacs
+
+**Performance issues:**
+- Increase `claude-code-context-update-interval` to reduce update frequency
+- Disable automatic mode and use manual commands only
+
+## Contributing
+
+Contributions are welcome! Please feel free to submit a Pull Request.
+
+## License
+
+GPL-3.0-or-later
+
+## Author
+
+Luke Hoersten <[email protected]>
diff --git a/claude-code-context.el b/claude-code-context.el
new file mode 100644
index 0000000..95168c1
--- /dev/null
+++ b/claude-code-context.el
@@ -0,0 +1,188 @@
+;;; claude-code-context.el --- Share Emacs context with Claude Code -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2025 Luke Hoersten
+
+;; Author: Luke Hoersten <[email protected]>
+;; URL: https://github.com/lhoersten/claude-code-context
+;; Version: 0.1.0
+;; Package-Requires: ((emacs "27.1"))
+;; Keywords: tools, ai, convenience
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package automatically shares your current Emacs buffer context
+;; (file, line, column, selection, and diagnostics) with Claude Code
+;; via a context file that Claude Code hooks can read.
+;;
+;; Setup:
+;; 1. Add to your init.el:
+;; (require 'claude-code-context)
+;; (claude-code-context-mode 1)
+;;
+;; 2. Add this hook to your ~/.claude/settings.json:
+;; {
+;; "hooks": {
+;; "UserPromptSubmit": [
+;; {
+;; "hooks": [
+;; {
+;; "type": "command",
+;; "command": "CONTEXT_FILE=\"$HOME/.emacs.d/claude-context.txt\"; if [ -f \"$CONTEXT_FILE\" ]; then echo \"\\n---\\n## Emacs Context\\n\"; cat \"$CONTEXT_FILE\"; echo \"\\n---\"; fi"
+;; }
+;; ]
+;; }
+;; ]
+;; }
+;; }
+;;
+;; Usage:
+;; - C-c C-l u : Manually update context
+;; - C-c C-l d : Add flymake diagnostics to context
+;; - C-c C-l c : Clear context
+;; - C-c C-l m : Toggle automatic context mode
+
+;;; Code:
+
+(defgroup claude-code-context nil
+ "Share Emacs context with Claude Code."
+ :group 'tools
+ :prefix "claude-code-context-")
+
+(defcustom claude-code-context-file
+ (expand-file-name "claude-context.txt" user-emacs-directory)
+ "File where Claude Code context is written."
+ :type 'file
+ :group 'claude-code-context)
+
+(defcustom claude-code-context-update-interval 2
+ "Seconds between context updates (to avoid excessive writes)."
+ :type 'integer
+ :group 'claude-code-context)
+
+(defvar claude-code-context-timer nil
+ "Timer for updating Claude Code context.")
+
+(defun claude-code--get-current-context ()
+ "Get current buffer context as a string."
+ (when (buffer-file-name)
+ (let* ((file (buffer-file-name))
+ (line (line-number-at-pos))
+ (col (current-column))
+ (selection (when (use-region-p)
+ (buffer-substring-no-properties (region-beginning) (region-end)))))
+ (concat
+ (format "File: %s\n" file)
+ (format "Line: %d, Column: %d\n" line col)
+ (when selection
+ (format "Selection:\n```\n%s\n```\n" selection))))))
+
+(defun claude-code--get-flymake-diagnostics ()
+ "Get flymake diagnostics for current buffer."
+ (when (and (bound-and-true-p flymake-mode)
+ (buffer-file-name))
+ (let ((diags (flymake-diagnostics)))
+ (when diags
+ (concat
+ "\nFlymake Diagnostics:\n"
+ (mapconcat
+ (lambda (diag)
+ (format " %4d %8s %-8s %s"
+ (line-number-at-pos (flymake-diagnostic-beg diag))
+ (flymake-diagnostic-type diag)
+ (flymake-diagnostic-backend diag)
+ (flymake-diagnostic-text diag)))
+ diags
+ "\n"))))))
+
+(defun claude-code-update-context ()
+ "Update Claude Code context file with current buffer state."
+ (interactive)
+ (let ((context (claude-code--get-current-context)))
+ (when context
+ (with-temp-file claude-code-context-file
+ (insert "# Emacs Context for Claude Code\n")
+ (insert "# This file is automatically updated by Emacs\n\n")
+ (insert context))
+ (message "Claude Code context updated"))))
+
+(defun claude-code-add-diagnostics ()
+ "Add flymake diagnostics to Claude Code context file."
+ (interactive)
+ (let ((context (claude-code--get-current-context))
+ (diags (claude-code--get-flymake-diagnostics)))
+ (when context
+ (with-temp-file claude-code-context-file
+ (insert "# Emacs Context for Claude Code\n")
+ (insert "# This file is automatically updated by Emacs\n\n")
+ (insert context)
+ (when diags
+ (insert diags)))
+ (message "Claude Code context updated with diagnostics"))))
+
+(defun claude-code-clear-context ()
+ "Clear the Claude Code context file."
+ (interactive)
+ (when (file-exists-p claude-code-context-file)
+ (delete-file claude-code-context-file)
+ (message "Claude Code context cleared")))
+
+(defun claude-code--update-context-timer ()
+ "Timer function to update context periodically."
+ (when (and (buffer-file-name)
+ (not (minibufferp)))
+ (claude-code-update-context)))
+
+(defun claude-code-context-mode-enable ()
+ "Enable automatic context updates."
+ (unless claude-code-context-timer
+ (setq claude-code-context-timer
+ (run-with-idle-timer claude-code-context-update-interval t
+ #'claude-code--update-context-timer))
+ (message "Claude Code context mode enabled")))
+
+(defun claude-code-context-mode-disable ()
+ "Disable automatic context updates."
+ (when claude-code-context-timer
+ (cancel-timer claude-code-context-timer)
+ (setq claude-code-context-timer nil)
+ (message "Claude Code context mode disabled")))
+
+;;;###autoload
+(define-minor-mode claude-code-context-mode
+ "Minor mode for automatic Claude Code context updates."
+ :global t
+ :lighter " CC"
+ :group 'claude-code-context
+ (if claude-code-context-mode
+ (claude-code-context-mode-enable)
+ (claude-code-context-mode-disable)))
+
+;; Keybindings
+(defvar claude-code-context-command-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "u") 'claude-code-update-context)
+ (define-key map (kbd "d") 'claude-code-add-diagnostics)
+ (define-key map (kbd "c") 'claude-code-clear-context)
+ (define-key map (kbd "m") 'claude-code-context-mode)
+ map)
+ "Keymap for claude-code-context commands.")
+
+(global-set-key (kbd "C-c C-l") claude-code-context-command-map)
+
+(provide 'claude-code-context)
+;;; claude-code-context.el ends here
diff --git a/claude-code-hook-example.json b/claude-code-hook-example.json
new file mode 100644
index 0000000..3e4c1a0
--- /dev/null
+++ b/claude-code-hook-example.json
@@ -0,0 +1,16 @@
+{
+ "description": "Example Claude Code hook configuration for Emacs context integration",
+ "note": "Add the 'hooks' section below to your ~/.claude/settings.json file",
+ "hooks": {
+ "UserPromptSubmit": [
+ {
+ "hooks": [
+ {
+ "type": "command",
+ "command": "CONTEXT_FILE=\"$HOME/.emacs.d/claude-context.txt\"; if [ -f \"$CONTEXT_FILE\" ]; then echo \"\\n---\\n## Emacs Context\\n\"; cat \"$CONTEXT_FILE\"; echo \"\\n---\"; fi"
+ }
+ ]
+ }
+ ]
+ }
+}