Skip to content

Commit 731abf8

Browse files
committed
merge: Integrate PR coder#117 with add-unsafe-command branch features
- Merged external terminal provider support from PR coder#117 - Preserved add-unsafe-command branch features (monitoring, notifications, anti-flicker) - Combined terminal integration improvements from both branches - Maintained backward compatibility with existing configurations - Added mini.files integration support - Enhanced documentation with new terminal providers and integration fixtures - Resolved conflicts by keeping the best features from both branches
2 parents 33dcf72 + fbcc5d8 commit 731abf8

File tree

96 files changed

+5809
-1288
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+5809
-1288
lines changed

.claude/hooks/format.sh

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Claude Code Hook: Format Files
4+
# Triggers after Claude edits/writes files and runs nix fmt
5+
#
6+
# Environment variables provided by Claude Code:
7+
# - CLAUDE_PROJECT_DIR: Path to the project directory
8+
# - CLAUDE_TOOL_NAME: Name of the tool that was executed
9+
# - CLAUDE_TOOL_ARGS: JSON string containing tool arguments
10+
11+
set -euo pipefail
12+
13+
# Colors for output
14+
RED='\033[0;31m'
15+
GREEN='\033[0;32m'
16+
YELLOW='\033[1;33m'
17+
NC='\033[0m' # No Color
18+
19+
# Log function
20+
log() {
21+
echo -e "[$(date '+%H:%M:%S')] $1" >&2
22+
}
23+
24+
# Parse tool arguments to get the file path
25+
get_file_path() {
26+
# Read hook input from stdin
27+
local hook_input
28+
if [ -t 0 ]; then
29+
# No stdin input available
30+
log "DEBUG: No stdin input available"
31+
return
32+
fi
33+
34+
hook_input=$(cat)
35+
log "DEBUG: Hook input = $hook_input"
36+
37+
# Try to extract file_path from tool_input
38+
local file_path
39+
file_path=$(echo "$hook_input" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
40+
41+
if [ -n "$file_path" ]; then
42+
echo "$file_path"
43+
return
44+
fi
45+
46+
# Try extracting any file path from the input
47+
local any_file_path
48+
any_file_path=$(echo "$hook_input" | grep -o '"[^"]*\.[^"]*"' | sed 's/"//g' | head -1)
49+
50+
if [ -n "$any_file_path" ]; then
51+
echo "$any_file_path"
52+
return
53+
fi
54+
55+
log "DEBUG: Could not extract file path from hook input"
56+
}
57+
58+
# Main logic
59+
main() {
60+
log "${YELLOW}Claude Code Hook: File Formatter${NC}"
61+
62+
# Get the file path from tool arguments
63+
FILE_PATH=$(get_file_path)
64+
65+
if [ -z "$FILE_PATH" ]; then
66+
log "${RED}Error: Could not determine file path from tool arguments${NC}"
67+
exit 1
68+
fi
69+
70+
log "Tool: ${CLAUDE_TOOL_NAME:-unknown}, File: $FILE_PATH"
71+
72+
# Check if file exists
73+
if [ ! -f "$FILE_PATH" ]; then
74+
log "${RED}Error: File does not exist: $FILE_PATH${NC}"
75+
exit 1
76+
fi
77+
78+
log "${YELLOW}Formatting file with nix fmt...${NC}"
79+
80+
# Change to project directory
81+
cd "${CLAUDE_PROJECT_DIR}"
82+
83+
# Run nix fmt on the file
84+
if nix fmt "$FILE_PATH" 2>/dev/null; then
85+
log "${GREEN}✓ Successfully formatted: $FILE_PATH${NC}"
86+
exit 0
87+
else
88+
EXIT_CODE=$?
89+
log "${RED}✗ nix fmt failed with exit code $EXIT_CODE${NC}"
90+
log "${RED}This indicates the file has formatting issues that need manual attention${NC}"
91+
92+
# Don't fail the hook - just warn about formatting issues
93+
# This allows Claude's operation to continue while alerting about format problems
94+
log "${YELLOW}Continuing with Claude's operation, but please fix formatting issues${NC}"
95+
exit 0
96+
fi
97+
}
98+
99+
# Run main function
100+
main "$@"

.claude/settings.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"hooks": {
3+
"PostToolUse": [
4+
{
5+
"matcher": "Write|Edit",
6+
"hooks": [
7+
{
8+
"type": "command",
9+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/format.sh"
10+
}
11+
]
12+
}
13+
]
14+
}
15+
}

.devcontainer/Dockerfile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
FROM mcr.microsoft.com/devcontainers/base:ubuntu
2+
3+
# Install Nix
4+
RUN apt-get update && apt-get install -y \
5+
curl \
6+
xz-utils \
7+
sudo \
8+
&& rm -rf /var/lib/apt/lists/*
9+
10+
# Create vscode user if it doesn't exist
11+
RUN if ! id -u vscode > /dev/null 2>&1; then \
12+
useradd -m -s /bin/bash vscode && \
13+
echo "vscode ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers; \
14+
fi
15+
16+
# Switch to vscode user for Nix installation
17+
USER vscode
18+
WORKDIR /home/vscode
19+
20+
# Install Nix in single-user mode
21+
RUN curl -L https://nixos.org/nix/install | sh -s -- --no-daemon
22+
23+
# Add Nix to PATH and configure for the shell
24+
RUN echo '. /home/vscode/.nix-profile/etc/profile.d/nix.sh' >> /home/vscode/.bashrc && \
25+
mkdir -p /home/vscode/.config/nix && \
26+
echo 'experimental-features = nix-command flakes' >> /home/vscode/.config/nix/nix.conf
27+
28+
# Keep container running
29+
CMD ["sleep", "infinity"]

.devcontainer/devcontainer.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "claudecode.nvim Development",
3+
"build": {
4+
"dockerfile": "Dockerfile"
5+
},
6+
"features": {
7+
"ghcr.io/devcontainers/features/git:1": {}
8+
},
9+
"customizations": {
10+
"vscode": {
11+
"settings": {
12+
"terminal.integrated.defaultProfile.linux": "bash"
13+
},
14+
"extensions": ["jnoortheen.nix-ide"]
15+
}
16+
},
17+
"postCreateCommand": "bash .devcontainer/post-create.sh",
18+
"remoteUser": "vscode"
19+
}

.devcontainer/post-create.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
3+
# Source Nix environment
4+
. /home/vscode/.nix-profile/etc/profile.d/nix.sh
5+
6+
# Verify Nix is available
7+
if ! command -v nix &>/dev/null; then
8+
echo "Error: Nix is not installed properly"
9+
exit 1
10+
fi
11+
12+
echo "✅ Nix is installed and available"
13+
echo ""
14+
echo "📦 claudecode.nvim Development Container Ready!"
15+
echo ""
16+
echo "To enter the development shell with all dependencies, run:"
17+
echo " nix develop"
18+
echo ""
19+
echo "This will provide:"
20+
echo " - Neovim"
21+
echo " - Lua and LuaJIT"
22+
echo " - busted (test framework)"
23+
echo " - luacheck (linter)"
24+
echo " - stylua (formatter)"
25+
echo " - All other development tools"
26+
echo ""
27+
echo "You can also run development commands directly:"
28+
echo " - make # Run full validation (format, lint, test)"
29+
echo " - make test # Run tests"
30+
echo " - make check # Run linter"
31+
echo " - make format # Format code"

.envrc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#!/usr/bin/env bash
22

3-
if ! has nix_direnv_version || ! nix_direnv_version 3.0.6; then
4-
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.6/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM="
3+
if ! has nix_direnv_version || ! nix_direnv_version 3.0.7; then
4+
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.7/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM="
55
fi
66

77
nix_direnv_manual_reload
88

99
use flake .
10+
11+
# Add fixtures/bin to PATH for nvim config aliases
12+
PATH_add fixtures/bin

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ luacov.stats.out
6161
# direnv
6262
.direnv
6363

64-
.claude
64+
.claude/*
65+
!.claude/settings.json
66+
!.claude/hooks/

.luarc.json

Lines changed: 0 additions & 19 deletions
This file was deleted.

CLAUDE.md

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,24 @@ Is it about viewing CODE with syntax? use 'bat'
5757
- `nix develop` - Enter development shell with all dependencies
5858
- `nix fmt` - Format all files using nix formatter
5959

60+
### Integration Testing with Fixtures
61+
62+
The `fixtures/` directory contains test Neovim configurations for verifying plugin integrations:
63+
64+
- `vv <config>` - Start Neovim with a specific fixture configuration
65+
- `vve <config>` - Start Neovim with a fixture config in edit mode
66+
- `list-configs` - Show available fixture configurations
67+
- Source `fixtures/nvim-aliases.sh` to enable these commands
68+
69+
**Available Fixtures**:
70+
71+
- `netrw` - Tests with Neovim's built-in file explorer
72+
- `nvim-tree` - Tests with nvim-tree.lua file explorer
73+
- `oil` - Tests with oil.nvim file explorer
74+
- `mini-files` - Tests with mini.files file explorer
75+
76+
**Usage**: `source fixtures/nvim-aliases.sh && vv oil` starts Neovim with oil.nvim configuration
77+
6078
## Architecture Overview
6179

6280
### Core Components
@@ -66,7 +84,7 @@ Is it about viewing CODE with syntax? use 'bat'
6684
3. **Lock File System** (`lua/claudecode/lockfile.lua`) - Creates discovery files for Claude CLI at `~/.claude/ide/`
6785
4. **Selection Tracking** (`lua/claudecode/selection.lua`) - Monitors text selections and sends updates to Claude
6886
5. **Diff Integration** (`lua/claudecode/diff.lua`) - Native Neovim diff support for Claude's file comparisons
69-
6. **Terminal Integration** (`lua/claudecode/terminal.lua`) - Manages Claude CLI terminal sessions
87+
6. **Terminal Integration** (`lua/claudecode/terminal.lua`) - Manages Claude CLI terminal sessions with support for internal Neovim terminals and external terminal applications
7088
7. **Session Management** (`lua/claudecode/session_manager.lua`) - Parses and manages Claude CLI session files for resume functionality
7189

7290
### WebSocket Server Implementation
@@ -138,6 +156,28 @@ The WebSocket server implements secure authentication using:
138156
<leader>ax " Default key mapping for session selection
139157
```
140158

159+
### Terminal Integration Options
160+
161+
**Internal Terminals** (within Neovim):
162+
163+
- **Snacks.nvim**: `terminal/snacks.lua` - Advanced terminal with floating windows
164+
- **Native**: `terminal/native.lua` - Built-in Neovim terminal as fallback
165+
166+
**External Terminals** (separate applications):
167+
168+
- **External Provider**: `terminal/external.lua` - Launches Claude in external terminal apps
169+
170+
**Configuration Example**:
171+
172+
```lua
173+
opts = {
174+
terminal = {
175+
provider = "external", -- "auto", "snacks", "native", or "external"
176+
external_terminal_cmd = "alacritty -e %s" -- Required for external provider
177+
}
178+
}
179+
```
180+
141181
### Key File Locations
142182

143183
- `lua/claudecode/init.lua` - Main entry point and setup
@@ -286,7 +326,36 @@ Enable detailed authentication logging by setting:
286326

287327
```lua
288328
require("claudecode").setup({
289-
log_level = "debug" -- Shows auth token generation, validation, and failures
329+
log_level = "debug", -- Shows auth token generation, validation, and failures
330+
diff_opts = {
331+
keep_terminal_focus = true, -- If true, moves focus back to terminal after diff opens
332+
},
333+
})
334+
```
335+
336+
### Configuration Options
337+
338+
#### Diff Options
339+
340+
The `diff_opts` configuration allows you to customize diff behavior:
341+
342+
- `keep_terminal_focus` (boolean, default: `false`) - When enabled, keeps focus in the Claude Code terminal when a diff opens instead of moving focus to the diff buffer. This allows you to continue using terminal keybindings like `<CR>` for accepting/rejecting diffs without accidentally triggering other mappings.
343+
- `open_in_new_tab` (boolean, default: `false`) - Open diffs in a new tab instead of the current tab.
344+
- `hide_terminal_in_new_tab` (boolean, default: `false`) - When opening diffs in a new tab, do not show the Claude terminal split in that new tab. The terminal remains in the original tab, giving maximum screen estate for reviewing the diff.
345+
346+
**Example use case**: If you frequently use `<CR>` or arrow keys in the Claude Code terminal to accept/reject diffs, enable this option to prevent focus from moving to the diff buffer where `<CR>` might trigger unintended actions.
347+
348+
```lua
349+
require("claudecode").setup({
350+
diff_opts = {
351+
keep_terminal_focus = true, -- If true, moves focus back to terminal after diff opens
352+
open_in_new_tab = true, -- Open diff in a separate tab
353+
hide_terminal_in_new_tab = true, -- In the new tab, do not show Claude terminal
354+
auto_close_on_accept = true,
355+
show_diff_stats = true,
356+
vertical_split = true,
357+
open_in_current_tab = true,
358+
},
290359
})
291360
```
292361

@@ -351,7 +420,7 @@ Key configuration options available in `require("claudecode").setup({})`:
351420
### Integration Support
352421

353422
- Terminal integration supports both snacks.nvim and native Neovim terminal
354-
- Compatible with popular file explorers (nvim-tree, oil.nvim, neo-tree)
423+
- Compatible with popular file explorers (nvim-tree, oil.nvim, neo-tree, mini.files)
355424
- Visual selection tracking across different selection modes
356425

357426
### Common Troubleshooting
@@ -425,6 +494,23 @@ rg "0\.1\.0" . # Should only show CHANGELOG.md historical entries
425494
4. **Document Changes**: Update relevant documentation (this file, PROTOCOL.md, etc.)
426495
5. **Commit**: Only commit after successful `make` execution
427496

497+
### Integration Development Guidelines
498+
499+
**Adding New Integrations** (file explorers, terminals, etc.):
500+
501+
1. **Implement Integration**: Add support in relevant modules (e.g., `lua/claudecode/tools/`)
502+
2. **Create Fixture Configuration**: **REQUIRED** - Add a complete Neovim config in `fixtures/[integration-name]/`
503+
3. **Test Integration**: Use fixture to verify functionality with `vv [integration-name]`
504+
4. **Update Documentation**: Add integration to fixtures list and relevant tool documentation
505+
5. **Run Full Test Suite**: Ensure `make` passes with new integration
506+
507+
**Fixture Requirements**:
508+
509+
- Complete Neovim configuration with plugin dependencies
510+
- Include `dev-claudecode.lua` with development keybindings
511+
- Test all relevant claudecode.nvim features with the integration
512+
- Document any integration-specific behaviors or limitations
513+
428514
### MCP Tool Development Guidelines
429515

430516
**Adding New Tools**:

0 commit comments

Comments
 (0)