diff --git a/PROTOCOL.md b/PROTOCOL.md index 384ccf9..6614a08 100644 --- a/PROTOCOL.md +++ b/PROTOCOL.md @@ -132,46 +132,361 @@ According to the MCP spec, Claude should be able to call tools, but **current im ## Available MCP Tools -The extensions register these tools that Claude can (theoretically) call: +The VS Code extension registers 12 tools that Claude can call. Here's the complete specification: -### Core Tools +### 1. openFile -1. **openFile** - Open a file and optionally select text +**Description**: Open a file in the editor and optionally select a range of text - ```json - { - "filePath": "/path/to/file.js", - "startText": "function hello", // Find and select from this text - "endText": "}" // To this text - } - ``` +**Input**: -2. **openDiff** - Show a diff and wait for user action (blocking!) +```json +{ + "filePath": "/path/to/file.js", + "preview": false, + "startText": "function hello", + "endText": "}", + "selectToEndOfLine": false, + "makeFrontmost": true +} +``` + +- `filePath` (string, required): Path to the file to open +- `preview` (boolean, default: false): Whether to open in preview mode +- `startText` (string, optional): Text pattern to find selection start +- `endText` (string, optional): Text pattern to find selection end +- `selectToEndOfLine` (boolean, default: false): Extend selection to end of line +- `makeFrontmost` (boolean, default: true): Make the file the active editor tab + +**Output**: When `makeFrontmost=true`, returns simple message: + +```json +{ + "content": [ + { + "type": "text", + "text": "Opened file: /path/to/file.js" + } + ] +} +``` + +When `makeFrontmost=false`, returns detailed JSON: + +```json +{ + "content": [ + { + "type": "text", + "text": "{\"success\": true, \"filePath\": \"/absolute/path/to/file.js\", \"languageId\": \"javascript\", \"lineCount\": 42}" + } + ] +} +``` + +### 2. openDiff + +**Description**: Open a git diff for the file (blocking operation) + +**Input**: + +```json +{ + "old_file_path": "/path/to/original.js", + "new_file_path": "/path/to/modified.js", + "new_file_contents": "// Modified content...", + "tab_name": "Proposed changes" +} +``` + +- `old_file_path` (string): Path to original file +- `new_file_path` (string): Path to new file +- `new_file_contents` (string): Contents of the new file +- `tab_name` (string): Tab name for the diff view + +**Output**: Returns MCP-formatted response: + +```json +{ + "content": [ + { + "type": "text", + "text": "FILE_SAVED" + } + ] +} +``` + +or + +```json +{ + "content": [ + { + "type": "text", + "text": "DIFF_REJECTED" + } + ] +} +``` + +Based on whether the user saves or rejects the diff. + +### 3. getCurrentSelection - ```json - { - "old_file_path": "/path/to/original.js", - "new_file_path": "/path/to/modified.js", - "new_file_contents": "// Modified content...", - "tab_name": "Proposed changes" - } - ``` +**Description**: Get the current text selection in the active editor + +**Input**: None + +**Output**: Returns JSON-stringified selection data: + +```json +{ + "content": [ + { + "type": "text", + "text": "{\"success\": true, \"text\": \"selected content\", \"filePath\": \"/path/to/file\", \"selection\": {\"start\": {\"line\": 0, \"character\": 0}, \"end\": {\"line\": 0, \"character\": 10}}}" + } + ] +} +``` + +Or when no active editor: + +```json +{ + "content": [ + { + "type": "text", + "text": "{\"success\": false, \"message\": \"No active editor found\"}" + } + ] +} +``` + +### 4. getLatestSelection + +**Description**: Get the most recent text selection (even if not in active editor) + +**Input**: None + +**Output**: JSON-stringified selection data or `{success: false, message: "No selection available"}` + +### 5. getOpenEditors + +**Description**: Get information about currently open editors + +**Input**: None + +**Output**: Returns JSON-stringified array of open tabs: + +```json +{ + "content": [ + { + "type": "text", + "text": "{\"tabs\": [{\"uri\": \"file:///path/to/file\", \"isActive\": true, \"label\": \"filename.ext\", \"languageId\": \"javascript\", \"isDirty\": false}]}" + } + ] +} +``` + +### 6. getWorkspaceFolders + +**Description**: Get all workspace folders currently open in the IDE + +**Input**: None + +**Output**: Returns JSON-stringified workspace information: + +```json +{ + "content": [ + { + "type": "text", + "text": "{\"success\": true, \"folders\": [{\"name\": \"project-name\", \"uri\": \"file:///path/to/workspace\", \"path\": \"/path/to/workspace\"}], \"rootPath\": \"/path/to/workspace\"}" + } + ] +} +``` + +### 7. getDiagnostics + +**Description**: Get language diagnostics from VS Code + +**Input**: + +```json +{ + "uri": "file:///path/to/file.js" +} +``` + +- `uri` (string, optional): File URI to get diagnostics for. If not provided, gets diagnostics for all files. + +**Output**: Returns JSON-stringified array of diagnostics per file: + +```json +{ + "content": [ + { + "type": "text", + "text": "[{\"uri\": \"file:///path/to/file\", \"diagnostics\": [{\"message\": \"Error message\", \"severity\": \"Error\", \"range\": {\"start\": {\"line\": 0, \"character\": 0}}, \"source\": \"typescript\"}]}]" + } + ] +} +``` + +### 8. checkDocumentDirty + +**Description**: Check if a document has unsaved changes (is dirty) + +**Input**: + +```json +{ + "filePath": "/path/to/file.js" +} +``` + +- `filePath` (string, required): Path to the file to check + +**Output**: Returns document dirty status: + +```json +{ + "content": [ + { + "type": "text", + "text": "{\"success\": true, \"filePath\": \"/path/to/file.js\", \"isDirty\": true, \"isUntitled\": false}" + } + ] +} +``` + +Or when document not open: + +```json +{ + "content": [ + { + "type": "text", + "text": "{\"success\": false, \"message\": \"Document not open: /path/to/file.js\"}" + } + ] +} +``` + +### 9. saveDocument + +**Description**: Save a document with unsaved changes + +**Input**: + +```json +{ + "filePath": "/path/to/file.js" +} +``` + +- `filePath` (string, required): Path to the file to save + +**Output**: Returns save operation result: + +```json +{ + "content": [ + { + "type": "text", + "text": "{\"success\": true, \"filePath\": \"/path/to/file.js\", \"saved\": true, \"message\": \"Document saved successfully\"}" + } + ] +} +``` + +Or when document not open: + +```json +{ + "content": [ + { + "type": "text", + "text": "{\"success\": false, \"message\": \"Document not open: /path/to/file.js\"}" + } + ] +} +``` + +### 10. close_tab + +**Description**: Close a tab by name + +**Input**: + +```json +{ + "tab_name": "filename.js" +} +``` + +- `tab_name` (string, required): Name of the tab to close + +**Output**: Returns `{content: [{type: "text", text: "TAB_CLOSED"}]}` + +### 11. closeAllDiffTabs + +**Description**: Close all diff tabs in the editor + +**Input**: None + +**Output**: Returns `{content: [{type: "text", text: "CLOSED_${count}_DIFF_TABS"}]}` + +### 12. executeCode + +**Description**: Execute Python code in the Jupyter kernel for the current notebook file + +**Input**: + +```json +{ + "code": "print('Hello, World!')" +} +``` + +- `code` (string, required): The code to be executed on the kernel + +**Output**: Returns execution results with mixed content types: + +```json +{ + "content": [ + { + "type": "text", + "text": "Hello, World!" + }, + { + "type": "image", + "data": "base64_encoded_image_data", + "mimeType": "image/png" + } + ] +} +``` - Returns `FILE_SAVED` or `DIFF_REJECTED` based on user action. +**Notes**: -3. **getCurrentSelection** - Get the current text selection -4. **getOpenEditors** - List all open files -5. **getWorkspaceFolders** - Get project folders -6. **getDiagnostics** - Get errors/warnings from the IDE -7. **saveDocument** - Save a file -8. **close_tab** - Close a tab by name (note the inconsistent naming!) +- All code executed will persist across calls unless the kernel is restarted +- Avoid declaring variables or modifying kernel state unless explicitly requested +- Only available when working with Jupyter notebooks +- Can return multiple content types including text output and images ### Implementation Notes - Most tools follow camelCase naming except `close_tab` (uses snake_case) -- The `openDiff` tool is unique - it's **blocking** and waits for user interaction +- The `openDiff` tool is **blocking** and waits for user interaction - Tools return MCP-formatted responses with content arrays -- There's also `executeCode` for Jupyter notebooks in the VS Code extension +- All schemas use Zod validation in the VS Code extension +- Selection-related tools work with the current editor state ## Building Your Own Integration diff --git a/README.md b/README.md index 968a8fe..358ebe9 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,11 @@ ![Neovim version](https://img.shields.io/badge/Neovim-0.8%2B-green) ![Status](https://img.shields.io/badge/Status-beta-blue) +> ⚠️ **Important**: IDE integrations are currently broken in Claude Code releases newer than v1.0.27. Please use [Claude Code v1.0.27](https://www.npmjs.com/package/@anthropic-ai/claude-code/v/1.0.27) or older until these issues are resolved: +> +> - [Claude Code not detecting IDE integrations #2299](https://github.com/anthropics/claude-code/issues/2299) +> - [IDE integration broken after update #2295](https://github.com/anthropics/claude-code/issues/2295) + **The first Neovim IDE integration for Claude Code** — bringing Anthropic's AI coding assistant to your favorite editor with a pure Lua implementation. > 🎯 **TL;DR:** When Anthropic released Claude Code with VS Code and JetBrains support, I reverse-engineered their extension and built this Neovim plugin. This plugin implements the same WebSocket-based MCP protocol, giving Neovim users the same AI-powered coding experience. @@ -20,33 +25,12 @@ When Anthropic released Claude Code, they only supported VS Code and JetBrains. - ⚡ **First to Market** — Beat Anthropic to releasing Neovim support - 🛠️ **Built with AI** — Used Claude to reverse-engineer Claude's own protocol -## Quick Demo - -```vim -" Launch Claude Code in a split -:ClaudeCode - -" Claude now sees your current file and selections in real-time! - -" Send visual selection as context -:'<,'>ClaudeCodeSend - -" Claude can open files, show diffs, and more -``` - -## Requirements - -- Neovim >= 0.8.0 -- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed -- Optional: [folke/snacks.nvim](https://github.com/folke/snacks.nvim) for enhanced terminal support - ## Installation -Using [lazy.nvim](https://github.com/folke/lazy.nvim): - ```lua { "coder/claudecode.nvim", + dependencies = { "folke/snacks.nvim" }, config = true, keys = { { "a", nil, desc = "AI/Claude Code" }, @@ -54,6 +38,7 @@ Using [lazy.nvim](https://github.com/folke/lazy.nvim): { "af", "ClaudeCodeFocus", desc = "Focus Claude" }, { "ar", "ClaudeCode --resume", desc = "Resume Claude" }, { "aC", "ClaudeCode --continue", desc = "Continue Claude" }, + { "ab", "ClaudeCodeAdd %", desc = "Add current buffer" }, { "as", "ClaudeCodeSend", mode = "v", desc = "Send to Claude" }, { "as", @@ -68,162 +53,71 @@ Using [lazy.nvim](https://github.com/folke/lazy.nvim): } ``` -That's it! For more configuration options, see [Advanced Setup](#advanced-setup). +That's it! The plugin will auto-configure everything else. + +## Requirements + +- Neovim >= 0.8.0 +- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed +- [folke/snacks.nvim](https://github.com/folke/snacks.nvim) for enhanced terminal support + +## Quick Demo + +```vim +" Launch Claude Code in a split +:ClaudeCode + +" Claude now sees your current file and selections in real-time! + +" Send visual selection as context +:'<,'>ClaudeCodeSend + +" Claude can open files, show diffs, and more +``` ## Usage 1. **Launch Claude**: Run `:ClaudeCode` to open Claude in a split terminal 2. **Send context**: - Select text in visual mode and use `as` to send it to Claude - - In `nvim-tree` or `neo-tree`, press `as` on a file to add it to Claude's context + - In `nvim-tree`/`neo-tree`/`oil.nvim`, press `as` on a file to add it to Claude's context 3. **Let Claude work**: Claude can now: - See your current file and selections in real-time - Open files in your editor - Show diffs with proposed changes - Access diagnostics and workspace info -## Commands - -- `:ClaudeCode [arguments]` - Toggle the Claude Code terminal window (simple show/hide behavior) -- `:ClaudeCodeFocus [arguments]` - Smart focus/toggle Claude terminal (switches to terminal if not focused, hides if focused) -- `:ClaudeCode --resume` - Resume a previous Claude conversation -- `:ClaudeCode --continue` - Continue Claude conversation -- `:ClaudeCodeSend` - Send current visual selection to Claude, or add files from tree explorer -- `:ClaudeCodeTreeAdd` - Add selected file(s) from tree explorer to Claude context (also available via ClaudeCodeSend) -- `:ClaudeCodeAdd [start-line] [end-line]` - Add a specific file or directory to Claude context by path with optional line range -- `:ClaudeCodeDiffAccept` - Accept the current diff changes (equivalent to `aa`) -- `:ClaudeCodeDiffDeny` - Deny/reject the current diff changes (equivalent to `ad`) - -### Toggle Behavior - -- **`:ClaudeCode`** - Simple toggle: Always show/hide terminal regardless of current focus -- **`:ClaudeCodeFocus`** - Smart focus: Focus terminal if not active, hide if currently focused - -### Tree Integration - -The `as` keybinding has context-aware behavior: +## Key Commands -- **In normal buffers (visual mode)**: Sends selected text to Claude -- **In nvim-tree/neo-tree/oil.nvim buffers**: Adds the file under cursor (or selected files) to Claude's context - -This allows you to quickly add entire files to Claude's context for review, refactoring, or discussion. - -#### Features - -- **Single file**: Place cursor on any file and press `as` -- **Multiple files**: Select multiple files (using tree plugin's selection features or visual selection in oil.nvim) and press `as` -- **Smart detection**: Automatically detects whether you're in nvim-tree, neo-tree, or oil.nvim -- **Error handling**: Clear feedback if no files are selected or if tree plugins aren't available - -### Direct File Addition - -The `:ClaudeCodeAdd` command allows you to add files or directories directly by path, with optional line range specification: - -```vim -:ClaudeCodeAdd src/main.lua -:ClaudeCodeAdd ~/projects/myproject/ -:ClaudeCodeAdd ./README.md -:ClaudeCodeAdd src/main.lua 50 100 " Lines 50-100 only -:ClaudeCodeAdd config.lua 25 " Only line 25 -``` - -#### Features - -- **Path completion**: Tab completion for file and directory paths -- **Path expansion**: Supports `~` for home directory and relative paths -- **Line range support**: Optionally specify start and end lines for files (ignored for directories) -- **Validation**: Checks that files and directories exist before adding, validates line numbers -- **Flexible**: Works with both individual files and entire directories +- `:ClaudeCode` - Toggle the Claude Code terminal window +- `:ClaudeCodeFocus` - Smart focus/toggle Claude terminal +- `:ClaudeCodeSend` - Send current visual selection to Claude +- `:ClaudeCodeAdd [start-line] [end-line]` - Add specific file to Claude context with optional line range +- `:ClaudeCodeDiffAccept` - Accept diff changes +- `:ClaudeCodeDiffDeny` - Reject diff changes ## Working with Diffs -When Claude proposes changes to your files, the plugin opens a native Neovim diff view showing the original file alongside the proposed changes. You have several options to accept or reject these changes: - -### Accepting Changes - -- **`:w` (save)** - Accept the changes and apply them to your file -- **`aa`** - Accept the changes using the dedicated keymap (configured in LazyVim spec) - -You can edit the proposed changes in the right-hand diff buffer before accepting them. This allows you to modify Claude's suggestions or make additional tweaks before applying the final version to your file. - -Both methods signal Claude Code to apply the changes to your file, after which the plugin automatically reloads the affected buffers to show the updated content. +When Claude proposes changes, the plugin opens a native Neovim diff view: -### Rejecting Changes +- **Accept**: `:w` (save) or `aa` +- **Reject**: `:q` or `ad` -- **`:q` or `:close`** - Close the diff view to reject the changes -- **`ad`** - Reject changes using the dedicated keymap (configured in LazyVim spec) -- **`:bdelete` or `:bwipeout`** - Delete the diff buffer to reject changes - -When you reject changes, the diff view closes and the original file remains unchanged. - -### Accepting/Rejecting from Claude Code Terminal - -You can also navigate to the Claude Code terminal window and accept or reject diffs directly from within Claude's interface. This provides an alternative way to manage diffs without using the Neovim-specific keymaps. - -### Customizing Diff Keymaps - -The diff keymaps are configured in the LazyVim spec and can be customized by modifying the `keys` table: - -```lua -{ - "coder/claudecode.nvim", - config = true, - keys = { - -- ... other keymaps ... - - -- Customize diff keymaps to avoid conflicts (e.g., with debugger) - { "ya", "ClaudeCodeDiffAccept", desc = "Accept diff" }, - { "yn", "ClaudeCodeDiffDeny", desc = "Deny diff" }, - - -- Or disable them entirely by omitting them from the keys table - }, -} -``` - -The commands `ClaudeCodeDiffAccept` and `ClaudeCodeDiffDeny` work only in diff buffers created by the plugin and will show a warning if used elsewhere. - -### How It Works - -The plugin uses a signal-based approach where accepting or rejecting a diff sends a message to Claude Code rather than directly modifying files. This ensures consistency and allows Claude Code to handle the actual file operations while the plugin manages the user interface and buffer reloading. - -#### Examples - -```vim -" Add entire files -:ClaudeCodeAdd src/components/Header.tsx -:ClaudeCodeAdd ~/.config/nvim/init.lua - -" Add entire directories (line numbers ignored) -:ClaudeCodeAdd tests/ -:ClaudeCodeAdd ../other-project/ - -" Add specific line ranges -:ClaudeCodeAdd src/main.lua 50 100 " Lines 50 through 100 -:ClaudeCodeAdd config.lua 25 " Only line 25 -:ClaudeCodeAdd utils.py 1 50 " First 50 lines -:ClaudeCodeAdd README.md 10 20 " Just lines 10-20 - -" Path expansion works with line ranges -:ClaudeCodeAdd ~/project/src/app.js 100 200 -:ClaudeCodeAdd ./relative/path.lua 30 -``` +You can edit Claude's suggestions before accepting them. ## How It Works This plugin creates a WebSocket server that Claude Code CLI connects to, implementing the same protocol as the official VS Code extension. When you launch Claude, it automatically detects Neovim and gains full access to your editor. -### The Protocol - -The extensions use a WebSocket-based variant of the Model Context Protocol (MCP) that only Claude Code supports. The plugin: +The protocol uses a WebSocket-based variant of MCP (Model Context Protocol) that: 1. Creates a WebSocket server on a random port 2. Writes a lock file to `~/.claude/ide/[port].lock` with connection info 3. Sets environment variables that tell Claude where to connect 4. Implements MCP tools that Claude can call -For the full technical details and protocol documentation, see [PROTOCOL.md](./PROTOCOL.md). - 📖 **[Read the full reverse-engineering story →](./STORY.md)** +🔧 **[Complete protocol documentation →](./PROTOCOL.md)** ## Architecture @@ -237,44 +131,7 @@ Built with pure Lua and zero external dependencies: For deep technical details, see [ARCHITECTURE.md](./ARCHITECTURE.md). -## Contributing - -See [DEVELOPMENT.md](./DEVELOPMENT.md) for build instructions and development guidelines. Tests can be run with `make test`. - -## Configuration - -### Quick Setup - -For most users, the default configuration is sufficient: - -```lua -{ - "coder/claudecode.nvim", - dependencies = { - "folke/snacks.nvim", -- optional - }, - config = true, - keys = { - { "a", nil, desc = "AI/Claude Code" }, - { "ac", "ClaudeCode", desc = "Toggle Claude" }, - { "af", "ClaudeCodeFocus", desc = "Focus Claude" }, - { "ar", "ClaudeCode --resume", desc = "Resume Claude" }, - { "aC", "ClaudeCode --continue", desc = "Continue Claude" }, - { "as", "ClaudeCodeSend", mode = "v", desc = "Send to Claude" }, - { - "as", - "ClaudeCodeTreeAdd", - desc = "Add file", - ft = { "NvimTree", "neo-tree", "oil" }, - }, - -- Diff management - { "aa", "ClaudeCodeDiffAccept", desc = "Accept diff" }, - { "ad", "ClaudeCodeDiffDeny", desc = "Deny diff" }, - }, -} -``` - -### Advanced Configuration +## Advanced Configuration
Complete configuration options @@ -282,208 +139,51 @@ For most users, the default configuration is sufficient: ```lua { "coder/claudecode.nvim", - dependencies = { - "folke/snacks.nvim", -- Optional for enhanced terminal - }, - keys = { - { "a", nil, desc = "AI/Claude Code" }, - { "ac", "ClaudeCode", desc = "Toggle Claude" }, - { "af", "ClaudeCodeFocus", desc = "Focus Claude" }, - { "ar", "ClaudeCode --resume", desc = "Resume Claude" }, - { "aC", "ClaudeCode --continue", desc = "Continue Claude" }, - { "as", "ClaudeCodeSend", mode = "v", desc = "Send to Claude" }, - { - "as", - "ClaudeCodeTreeAdd", - desc = "Add file", - ft = { "NvimTree", "neo-tree", "oil" }, - }, - -- Diff management - { "aa", "ClaudeCodeDiffAccept", desc = "Accept diff" }, - { "ad", "ClaudeCodeDiffDeny", desc = "Deny diff" }, - }, + dependencies = { "folke/snacks.nvim" }, opts = { -- Server Configuration - port_range = { min = 10000, max = 65535 }, -- WebSocket server port range - auto_start = true, -- Auto-start server on Neovim startup - log_level = "info", -- "trace", "debug", "info", "warn", "error" - terminal_cmd = nil, -- Custom terminal command (default: "claude") + port_range = { min = 10000, max = 65535 }, + auto_start = true, + log_level = "info", -- "trace", "debug", "info", "warn", "error" + terminal_cmd = nil, -- Custom terminal command (default: "claude") -- Selection Tracking - track_selection = true, -- Enable real-time selection tracking - visual_demotion_delay_ms = 50, -- Delay before demoting visual selection (ms) - - -- Connection Management - connection_wait_delay = 200, -- Wait time after connection before sending queued @ mentions (ms) - connection_timeout = 10000, -- Max time to wait for Claude Code connection (ms) - queue_timeout = 5000, -- Max time to keep @ mentions in queue (ms) + track_selection = true, + visual_demotion_delay_ms = 50, -- Terminal Configuration terminal = { - split_side = "right", -- "left" or "right" - split_width_percentage = 0.30, -- Width as percentage (0.0 to 1.0) - provider = "auto", -- "auto", "snacks", or "native" - show_native_term_exit_tip = true, -- Show exit tip for native terminal - auto_close = true, -- Auto-close terminal after command completion + split_side = "right", -- "left" or "right" + split_width_percentage = 0.30, + provider = "auto", -- "auto", "snacks", or "native" + auto_close = true, }, -- Diff Integration diff_opts = { - auto_close_on_accept = true, -- Close diff view after accepting changes - show_diff_stats = true, -- Show diff statistics - vertical_split = true, -- Use vertical split for diffs - open_in_current_tab = true, -- Open diffs in current tab vs new tab - }, - }, -} -``` - -
- -### Configuration Options Explained - -#### Server Options - -- **`port_range`**: Port range for the WebSocket server that Claude connects to -- **`auto_start`**: Whether to automatically start the integration when Neovim starts -- **`terminal_cmd`**: Override the default "claude" command (useful for custom Claude installations) -- **`log_level`**: Controls verbosity of plugin logs - -#### Selection Tracking - -- **`track_selection`**: Enables real-time selection updates sent to Claude -- **`visual_demotion_delay_ms`**: Time to wait before switching from visual selection to cursor position tracking - -#### Connection Management - -- **`connection_wait_delay`**: Prevents overwhelming Claude with rapid @ mentions after connection -- **`connection_timeout`**: How long to wait for Claude to connect before giving up -- **`queue_timeout`**: How long to keep queued @ mentions before discarding them - -#### Terminal Configuration - -- **`split_side`**: Which side to open the terminal split (`"left"` or `"right"`) -- **`split_width_percentage`**: Terminal width as a fraction of screen width (0.1 = 10%, 0.5 = 50%) -- **`provider`**: Terminal implementation to use: - - `"auto"`: Try snacks.nvim, fallback to native - - `"snacks"`: Force snacks.nvim (requires folke/snacks.nvim) - - `"native"`: Use built-in Neovim terminal -- **`show_native_term_exit_tip`**: Show help text for exiting native terminal -- **`auto_close`**: Automatically close terminal when commands finish - -#### Diff Options - -- **`auto_close_on_accept`**: Close diff view after accepting changes with `:w` or `aa` -- **`show_diff_stats`**: Display diff statistics (lines added/removed) -- **`vertical_split`**: Use vertical split layout for diffs -- **`open_in_current_tab`**: Open diffs in current tab instead of creating new tabs - -### Example Configurations - -#### Minimal Configuration - -```lua -{ - "coder/claudecode.nvim", - keys = { - { "a", nil, desc = "AI/Claude Code" }, - { "ac", "ClaudeCode", desc = "Toggle Claude" }, - { "af", "ClaudeCodeFocus", desc = "Focus Claude" }, - { "ar", "ClaudeCode --resume", desc = "Resume Claude" }, - { "aC", "ClaudeCode --continue", desc = "Continue Claude" }, - { "as", "ClaudeCodeSend", mode = "v", desc = "Send to Claude" }, - { - "as", - "ClaudeCodeTreeAdd", - desc = "Add file", - ft = { "NvimTree", "neo-tree", "oil" }, + auto_close_on_accept = true, + vertical_split = true, + open_in_current_tab = true, }, - -- Diff management - { "aa", "ClaudeCodeDiffAccept", desc = "Accept diff" }, - { "ad", "ClaudeCodeDiffDeny", desc = "Deny diff" }, - }, - opts = { - log_level = "warn", -- Reduce log verbosity - auto_start = false, -- Manual startup only }, -} -``` - -#### Power User Configuration - -```lua -{ - "coder/claudecode.nvim", keys = { - { "a", nil, desc = "AI/Claude Code" }, - { "ac", "ClaudeCode", desc = "Toggle Claude" }, - { "af", "ClaudeCodeFocus", desc = "Focus Claude" }, - { "ar", "ClaudeCode --resume", desc = "Resume Claude" }, - { "aC", "ClaudeCode --continue", desc = "Continue Claude" }, - { "as", "ClaudeCodeSend", mode = "v", desc = "Send to Claude" }, - { - "as", - "ClaudeCodeTreeAdd", - desc = "Add file", - ft = { "NvimTree", "neo-tree", "oil" }, - }, - -- Diff management - { "aa", "ClaudeCodeDiffAccept", desc = "Accept diff" }, - { "ad", "ClaudeCodeDiffDeny", desc = "Deny diff" }, - }, - opts = { - log_level = "debug", - visual_demotion_delay_ms = 100, -- Slower selection demotion - connection_wait_delay = 500, -- Longer delay for @ mention batching - terminal = { - split_side = "left", - split_width_percentage = 0.4, -- Wider terminal - provider = "snacks", - auto_close = false, -- Keep terminal open to review output - }, - diff_opts = { - vertical_split = false, -- Horizontal diffs - open_in_current_tab = false, -- New tabs for diffs - }, + -- Your keymaps here }, } ``` -#### Custom Claude Installation - -```lua -{ - "coder/claudecode.nvim", - keys = { - { "a", nil, desc = "AI/Claude Code" }, - { "ac", "ClaudeCode", desc = "Toggle Claude" }, - { "af", "ClaudeCodeFocus", desc = "Focus Claude" }, - { "ar", "ClaudeCode --resume", desc = "Resume Claude" }, - { "aC", "ClaudeCode --continue", desc = "Continue Claude" }, - { "as", "ClaudeCodeSend", mode = "v", desc = "Send to Claude" }, - { - "as", - "ClaudeCodeTreeAdd", - desc = "Add file", - ft = { "NvimTree", "neo-tree", "oil" }, - }, - -- Diff management - { "aa", "ClaudeCodeDiffAccept", desc = "Accept diff" }, - { "ad", "ClaudeCodeDiffDeny", desc = "Deny diff" }, - }, - opts = { - terminal_cmd = "/opt/claude/bin/claude", -- Custom Claude path - port_range = { min = 20000, max = 25000 }, -- Different port range - }, -} -``` + ## Troubleshooting - **Claude not connecting?** Check `:ClaudeCodeStatus` and verify lock file exists in `~/.claude/ide/` -- **Need debug logs?** Set `log_level = "debug"` in setup +- **Need debug logs?** Set `log_level = "debug"` in opts - **Terminal issues?** Try `provider = "native"` if using snacks.nvim +## Contributing + +See [DEVELOPMENT.md](./DEVELOPMENT.md) for build instructions and development guidelines. Tests can be run with `make test`. + ## License [MIT](LICENSE) diff --git a/dev-config.lua b/dev-config.lua index 5e6dde6..ecb3489 100644 --- a/dev-config.lua +++ b/dev-config.lua @@ -17,6 +17,7 @@ return { { "aC", "ClaudeCode --continue", desc = "Continue Claude" }, -- Context sending + { "ab", "ClaudeCodeAdd %", desc = "Add current buffer" }, { "as", "ClaudeCodeSend", mode = "v", desc = "Send to Claude" }, { "as",