Skip to content

feat: add nvim-tree and neotree integration #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,9 @@ jobs:

- name: Generate coverage report
run: |
# Check if stats file exists (created by busted --coverage)
if [ -f "luacov.stats.out" ]; then
# Generate the regular luacov report
nix develop .#ci -c luacov

# Create simple lcov.info from luacov.report.out
echo "Creating lcov.info from luacov.report.out"
{
echo "TN:"
Expand All @@ -81,24 +78,20 @@ jobs:
done
} > lcov.info

# Create markdown coverage summary for GitHub Actions
{
echo "## 📊 Test Coverage Report"
echo ""

# Extract overall coverage percentage
if [ -f "luacov.report.out" ]; then
overall_coverage=$(grep -E "Total.*%" luacov.report.out | grep -oE "[0-9]+\.[0-9]+%" | head -1)
if [ -n "$overall_coverage" ]; then
echo "**Overall Coverage: $overall_coverage**"
echo ""
fi

# Create table header
echo "| File | Coverage |"
echo "|------|----------|"

# Extract file-by-file coverage
grep -E "^[^ ].*:" luacov.report.out | while read -r line; do
file=$(echo "$line" | cut -d':' -f1)
percent=$(echo "$line" | grep -oE "[0-9]+\.[0-9]+%" | head -1)
Expand Down
16 changes: 4 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
.PHONY: check format test clean

# Default target
all: check format
all: format check test

# Check for syntax errors
check:
@echo "Checking Lua files for syntax errors..."
@find lua -name "*.lua" -type f -exec lua -e "assert(loadfile('{}'))" \;
nix develop .#ci -c find lua -name "*.lua" -type f -exec lua -e "assert(loadfile('{}'))" \;
@echo "Running luacheck..."
@luacheck lua/ tests/ --no-unused-args --no-max-line-length
nix develop .#ci -c luacheck lua/ tests/ --no-unused-args --no-max-line-length

# Format all files
format:
@echo "Formatting files..."
@if command -v nix >/dev/null 2>&1; then \
nix fmt; \
elif command -v stylua >/dev/null 2>&1; then \
stylua lua/; \
else \
echo "Neither nix nor stylua found. Please install one of them."; \
exit 1; \
fi
nix fmt

# Run tests
test:
Expand Down
83 changes: 82 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,15 @@ Using [lazy.nvim](https://github.com/folke/lazy.nvim):
"coder/claudecode.nvim",
config = true,
keys = {
{ "<leader>a", nil, desc = "AI/Claude Code" },
{ "<leader>ac", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude" },
{ "<leader>as", "<cmd>ClaudeCodeSend<cr>", mode = "v", desc = "Send to Claude" },
{
"<leader>as",
"<cmd>ClaudeCodeTreeAdd<cr>",
desc = "Add file",
ft = { "NvimTree", "neo-tree" },
},
},
}
```
Expand All @@ -60,13 +67,80 @@ That's it! For more configuration options, see [Advanced Setup](#advanced-setup)
## Usage

1. **Launch Claude**: Run `:ClaudeCode` to open Claude in a split terminal
2. **Send context**: Select text and run `:'<,'>ClaudeCodeSend` to send it to Claude
2. **Send context**:
- Select text in visual mode and use `<leader>as` to send it to Claude
- In `nvim-tree` or `neo-tree`, press `<leader>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` - Toggle the Claude Code terminal window
- `: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 <file-path> [start-line] [end-line]` - Add a specific file or directory to Claude context by path with optional line range

### Tree Integration

The `<leader>as` keybinding has context-aware behavior:

- **In normal buffers (visual mode)**: Sends selected text to Claude
- **In nvim-tree/neo-tree 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 `<leader>as`
- **Multiple files**: Select multiple files (using tree plugin's selection features) and press `<leader>as`
- **Smart detection**: Automatically detects whether you're in nvim-tree or neo-tree
- **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 " From line 25 to end of file
```

#### 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

#### 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 " From line 25 to end of file
: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
```

## 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.
Expand Down Expand Up @@ -132,8 +206,15 @@ See [DEVELOPMENT.md](./DEVELOPMENT.md) for build instructions and development gu
},
config = true,
keys = {
{ "<leader>a", nil, desc = "AI/Claude Code" },
{ "<leader>ac", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude" },
{ "<leader>as", "<cmd>ClaudeCodeSend<cr>", mode = "v", desc = "Send to Claude" },
{
"<leader>as",
"<cmd>ClaudeCodeTreeAdd<cr>",
desc = "Add file",
ft = { "NvimTree", "neo-tree" },
},
{ "<leader>ao", "<cmd>ClaudeCodeOpen<cr>", desc = "Open Claude" },
{ "<leader>ax", "<cmd>ClaudeCodeClose<cr>", desc = "Close Claude" },
},
Expand Down
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
luajitPackages.luacov
neovim
treefmt.config.build.wrapper
findutils
];

# Development packages (additional tools for development)
Expand All @@ -49,7 +50,7 @@
gnumake
websocat
jq
claude-code
# claude-code
];
in
{
Expand Down
4 changes: 0 additions & 4 deletions lua/claudecode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ M.defaults = {
}

--- Validates the provided configuration table.
-- Ensures that all configuration options are of the correct type and within valid ranges.
-- @param config table The configuration table to validate.
-- @return boolean true if the configuration is valid.
-- @error string if any configuration option is invalid.
Expand Down Expand Up @@ -54,7 +53,6 @@ function M.validate(config)
"visual_demotion_delay_ms must be a non-negative number"
)

-- Validate diff_opts
assert(type(config.diff_opts) == "table", "diff_opts must be a table")
assert(type(config.diff_opts.auto_close_on_accept) == "boolean", "diff_opts.auto_close_on_accept must be a boolean")
assert(type(config.diff_opts.show_diff_stats) == "boolean", "diff_opts.show_diff_stats must be a boolean")
Expand All @@ -65,8 +63,6 @@ function M.validate(config)
end

--- Applies user configuration on top of default settings and validates the result.
-- Merges the user-provided configuration with the default configuration,
-- then validates the merged configuration.
-- @param user_config table|nil The user-provided configuration table.
-- @return table The final, validated configuration table.
function M.apply(user_config)
Expand Down
Loading