Skip to content

Commit a4b9a68

Browse files
committed
feat(websocket): implement complete RFC 6455 WebSocket server with zero dependencies
Change-Id: I5ca970785879454c215ddcfc5e65e59721b84590 Signed-off-by: Thomas Kosiewski <[email protected]>
1 parent c5a58f7 commit a4b9a68

23 files changed

+2203
-173
lines changed

ARCHITECTURE.md

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ The plugin establishes a bidirectional communication channel between Neovim and
1010

1111
### 1. WebSocket Server
1212

13-
The WebSocket server is the communication backbone of the plugin:
13+
The WebSocket server is the communication backbone of the plugin, implemented using pure Neovim built-ins:
1414

15-
- Implements JSON-RPC 2.0 message format
16-
- Listens on a dynamically selected port (10000-65535)
17-
- Handles client connections from Claude Code CLI
18-
- Dispatches incoming requests to appropriate handlers
15+
- **Pure Neovim Implementation**: Uses `vim.loop` (libuv) for TCP server operations
16+
- **RFC 6455 Compliant**: Full WebSocket protocol implementation
17+
- **JSON-RPC 2.0**: Standard message format for MCP communication
18+
- **Zero Dependencies**: No external libraries required
19+
- **Async Processing**: Non-blocking operations integrated with Neovim's event loop
20+
- **Multiple Clients**: Supports concurrent WebSocket connections
21+
- **Connection Management**: Ping/pong keepalive and graceful disconnection
1922

2023
```
2124
┌─────────────┐ ┌─────────────┐
@@ -25,6 +28,30 @@ The WebSocket server is the communication backbone of the plugin:
2528
└─────────────┘ └─────────────┘
2629
```
2730

31+
**WebSocket Server Architecture:**
32+
33+
```
34+
┌─────────────────┐
35+
│ TCP Server │ ◄─── vim.loop.new_tcp()
36+
│ (vim.loop) │
37+
└─────────┬───────┘
38+
39+
┌─────────▼───────┐
40+
│ HTTP Upgrade │ ◄─── WebSocket handshake
41+
│ Handler │
42+
└─────────┬───────┘
43+
44+
┌─────────▼───────┐
45+
│ WebSocket Frame │ ◄─── RFC 6455 frame processing
46+
│ Parser │
47+
└─────────┬───────┘
48+
49+
┌─────────▼───────┐
50+
│ JSON-RPC │ ◄─── MCP message routing
51+
│ Message Router │
52+
└─────────────────┘
53+
```
54+
2855
### 2. Lock File System
2956

3057
The lock file system enables Claude CLI to discover the Neovim integration:
@@ -149,21 +176,31 @@ lua/claudecode/
149176
├── init.lua # Main entry point and setup
150177
├── config.lua # Configuration management
151178
├── server/
152-
│ ├── init.lua # WebSocket server initialization
153-
│ ├── message.lua # Message formatting and parsing
154-
│ └── handler.lua # Request handlers
179+
│ ├── init.lua # WebSocket server main interface with JSON-RPC 2.0
180+
│ ├── tcp.lua # TCP server using vim.loop
181+
│ ├── utils.lua # Utility functions (base64, SHA-1, HTTP parsing)
182+
│ ├── frame.lua # WebSocket frame encoding/decoding (RFC 6455)
183+
│ ├── handshake.lua # HTTP upgrade and WebSocket handshake
184+
│ ├── client.lua # WebSocket client connection management
185+
│ └── mock.lua # Mock server for testing
155186
├── lockfile.lua # Lock file management
156187
├── tools/
157-
│ ├── init.lua # Tool registration
158-
│ ├── file.lua # File operation tools
159-
│ ├── editor.lua # Editor information tools
160-
│ └── selection.lua # Selection management tools
161-
├── selection.lua # Selection tracking
162-
├── terminal.lua # Terminal management (uses Snacks.nvim)
163-
├── environment.lua # Environment variable management
164-
└── util.lua # Utility functions
188+
│ └── init.lua # Tool registration and dispatch
189+
├── selection.lua # Selection tracking and notifications
190+
├── terminal.lua # Terminal management (Snacks.nvim or native)
191+
└── meta/
192+
└── vim.lua # Vim API type definitions
165193
```
166194

195+
**WebSocket Server Implementation Details:**
196+
197+
- **`server/tcp.lua`**: Creates TCP server using `vim.loop.new_tcp()`, handles port binding and client connections
198+
- **`server/handshake.lua`**: Processes HTTP upgrade requests, validates WebSocket headers, generates accept keys
199+
- **`server/frame.lua`**: Implements WebSocket frame parsing/encoding per RFC 6455 specification
200+
- **`server/client.lua`**: Manages individual WebSocket client connections and state
201+
- **`server/utils.lua`**: Provides base64 encoding, SHA-1 hashing, and XOR operations in pure Lua
202+
- **`server/init.lua`**: Main server interface that orchestrates all components and handles JSON-RPC messages
203+
167204
## Testing Architecture
168205

169206
The testing strategy involves multiple layers:

CHANGELOG.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Changelog
22

3-
All notable changes to the Claude Code Neovim Integration will be documented in this file.
3+
All notable changes to the Claude Code Neovim Integration will be documented in
4+
this file.
45

56
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
67
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
@@ -10,14 +11,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1011
### Added
1112

1213
- Initial project structure and core modules
13-
- Basic WebSocket server implementation (placeholder)
14+
- **Complete WebSocket server implementation using pure Neovim built-ins**
15+
- RFC 6455 compliant WebSocket protocol implementation
16+
- JSON-RPC 2.0 message handling for MCP protocol
17+
- Zero external dependencies (uses vim.loop, vim.json, vim.schedule)
18+
- Support for multiple concurrent client connections
19+
- Ping/pong keepalive and graceful connection management
20+
- Full HTTP upgrade handshake with proper WebSocket accept key generation
21+
- WebSocket frame encoding/decoding with masking support
1422
- Lock file management for Claude CLI discovery
1523
- Selection tracking for editor context
1624
- MCP tool implementations
1725
- Basic commands (:ClaudeCodeStart, :ClaudeCodeStop, :ClaudeCodeStatus, :ClaudeCodeSend)
1826
- Automatic shutdown and cleanup on Neovim exit
19-
- Testing framework with Busted
27+
- Testing framework with Busted (55 tests passing)
2028
- Development environment with Nix flakes
29+
- Comprehensive luacheck linting with zero warnings
30+
31+
### Changed
2132

2233
## [0.1.0-alpha] - TBD
2334

CLAUDE.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ The plugin follows a modular architecture with these main components:
2525
1. **WebSocket Server** (`lua/claudecode/server/init.lua`)
2626

2727
- Handles communication with Claude Code CLI using JSON-RPC 2.0 protocol
28-
- Currently uses placeholder implementations
28+
- Pure Lua implementation with RFC 6455 WebSocket compliance
29+
- Zero external dependencies
2930

3031
2. **Lock File System** (`lua/claudecode/lockfile.lua`)
3132

@@ -47,12 +48,14 @@ The plugin follows a modular architecture with these main components:
4748

4849
## Development Status
4950

50-
The plugin is in alpha stage with:
51+
The plugin is in beta stage with:
5152

5253
- Core structure and configuration system implemented
53-
- Basic lock file management implemented
54-
- Selection tracking implemented
55-
- WebSocket server and MCP tool implementation still using placeholders
54+
- Complete WebSocket server with RFC 6455 compliance
55+
- Enhanced selection tracking with multi-mode support
56+
- Lock file management implemented
57+
- MCP tool framework implemented
58+
- Comprehensive test suite (55 tests passing)
5659

5760
## Testing Approach
5861

@@ -70,10 +73,10 @@ The project uses the Busted testing framework:
7073

7174
Current priorities for development are:
7275

73-
1. Implementing a real WebSocket server with lua-websockets or similar
74-
2. Implementing MCP tools for file operations and editor features
75-
3. Enhancing selection tracking
76-
4. Adding comprehensive integration tests
76+
1. Enhancing MCP tools with additional file operations and editor features
77+
2. Adding Neovim-specific tools (LSP integration, diagnostics, Telescope)
78+
3. Performance optimization for large codebases
79+
4. Integration testing with real Claude Code CLI
7780

7881
## Development Principles
7982

@@ -89,7 +92,7 @@ Current priorities for development are:
8992
## Dependencies & Requirements
9093

9194
- Neovim >= 0.8.0
92-
- Lua >= 5.1
95+
- **Zero external dependencies** - Pure Lua implementation
9396
- Development tools:
9497
- LuaCheck for linting
9598
- StyLua for formatting

DEVELOPMENT.md

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,55 +27,59 @@ claudecode.nvim/
2727

2828
## Core Components Implementation Status
2929

30-
| Component | Status | Priority | Notes |
31-
| ---------------------- | -------------- | -------- | ---------------------------------- |
32-
| Basic plugin structure | ✅ Done | - | Initial setup complete |
33-
| Configuration system | ✅ Done | - | Support for user configuration |
34-
| WebSocket server | 🚧 Placeholder | High | Need real implementation |
35-
| Lock file management | ✅ Done | - | Basic implementation complete |
36-
| Selection tracking | ✅ Done | - | Basic implementation complete |
37-
| MCP tools | 🚧 Placeholder | High | Need real implementation |
38-
| Tests | 🚧 Started | High | Framework set up, examples created |
39-
| CI pipeline | ✅ Done | - | GitHub Actions configured |
40-
| Documentation | ✅ Done | - | Initial documentation complete |
30+
| Component | Status | Priority | Notes |
31+
| ---------------------- | ---------- | -------- | ---------------------------------------- |
32+
| Basic plugin structure | ✅ Done | - | Initial setup complete |
33+
| Configuration system | ✅ Done | - | Support for user configuration |
34+
| WebSocket server | ✅ Done | - | Pure Lua RFC 6455 compliant |
35+
| Lock file management | ✅ Done | - | Basic implementation complete |
36+
| Selection tracking | ✅ Done | - | Enhanced with multi-mode support |
37+
| MCP tools | 🚧 Started | Medium | Basic framework, need more tools |
38+
| Tests | ✅ Done | - | 55 tests passing, comprehensive coverage |
39+
| CI pipeline | ✅ Done | - | GitHub Actions configured |
40+
| Documentation | ✅ Done | - | Complete documentation |
4141

4242
## Development Priorities
4343

44-
1. **WebSocket Server Implementation**
44+
1. **MCP Tool Enhancement**
4545

46-
- Implement real WebSocket server using lua-websockets
47-
- Add JSON-RPC 2.0 message handling
48-
- Add client connection management
49-
- Implement proper error handling
46+
- Implement additional tools from the findings document
47+
- Add Neovim-specific tools (LSP, diagnostics, Telescope integration)
48+
- Enhance existing tool implementations
5049

51-
2. **MCP Tool Implementation**
50+
2. **Performance Optimization**
5251

53-
- Implement all required tools from the findings document
54-
- Map VS Code concepts to Neovim equivalents
55-
- Test each tool thoroughly
52+
- Monitor WebSocket server performance under load
53+
- Optimize selection tracking for large files
54+
- Fine-tune debouncing and event handling
5655

57-
3. **Selection Tracking Enhancement**
56+
3. **User Experience**
5857

59-
- Improve selection change detection
60-
- Ensure compatibility with various Neovim modes
61-
- Optimize performance with proper debouncing
58+
- Add more user commands and keybindings
59+
- Improve error messages and user feedback
60+
- Create example configurations for popular setups
6261

6362
4. **Integration Testing**
64-
- Develop comprehensive integration tests
65-
- Create mock Claude client for testing
66-
- Test edge cases and error handling
63+
- Test with real Claude Code CLI
64+
- Validate compatibility across Neovim versions
65+
- Create end-to-end test scenarios
6766

6867
## Testing
6968

7069
Run tests using:
7170

7271
```bash
7372
# Run all tests
74-
cd claudecode.nvim
75-
nvim --headless -u tests/minimal_init.lua -c "lua require('tests').run()"
73+
make test
7674

7775
# Run specific test file
7876
nvim --headless -u tests/minimal_init.lua -c "lua require('tests.unit.config_spec')"
77+
78+
# Run linting
79+
make check
80+
81+
# Format code
82+
make format
7983
```
8084

8185
## Implementation Guidelines
@@ -95,7 +99,7 @@ nvim --headless -u tests/minimal_init.lua -c "lua require('tests.unit.config_spe
9599
3. **Compatibility**
96100

97101
- Support Neovim >= 0.8.0
98-
- Minimize dependencies
102+
- Zero external dependencies (pure Lua implementation)
99103
- Follow Neovim plugin best practices
100104

101105
4. **Testing**
@@ -115,12 +119,13 @@ nvim --headless -u tests/minimal_init.lua -c "lua require('tests.unit.config_spe
115119

116120
### WebSocket Server
117121

118-
The WebSocket server should use either:
122+
The WebSocket server is implemented in pure Lua with zero external dependencies:
119123

120-
- [lua-resty-websocket](https://github.com/openresty/lua-resty-websocket) library
121-
- last resort, as unmaintained: [lua-websockets](https://github.com/lipp/lua-websockets)
122-
library
123-
- Call out to a Node.js or Rust/Go server (if Lua implementation is problematic)
124+
- **Pure Neovim Implementation**: Uses `vim.loop` (libuv) for TCP operations
125+
- **RFC 6455 Compliant**: Full WebSocket protocol implementation
126+
- **JSON-RPC 2.0**: MCP message handling with proper framing
127+
- **Security**: Pure Lua SHA-1 implementation for WebSocket handshake
128+
- **Performance**: Optimized with lookup tables and efficient algorithms
124129

125130
### Custom Tools
126131

@@ -133,7 +138,7 @@ Custom tools beyond the basic VS Code implementation could include:
133138

134139
## Next Steps
135140

136-
1. Implement the WebSocket server with real functionality
137-
2. Complete the MCP tool implementations
138-
3. Add more comprehensive tests
139-
4. Create example configurations for popular Neovim setups
141+
1. Enhance MCP tool implementations with Neovim-specific features
142+
2. Add integration tests with real Claude Code CLI
143+
3. Optimize performance for large codebases
144+
4. Create example configurations for popular Neovim setups (LazyVim, NvChad, etc.)

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ A Neovim plugin that integrates with Claude Code CLI to provide a seamless AI co
88

99
## Features
1010

11-
- 🔄 Bidirectional communication with Claude Code CLI
11+
- 🔄 **Pure Neovim WebSocket Server** - Zero external dependencies, uses only Neovim built-ins
12+
- 🌐 **RFC 6455 Compliant** - Full WebSocket protocol implementation with JSON-RPC 2.0
1213
- 🔍 Selection tracking to provide context to Claude
1314
- 🛠️ Integration with Neovim's buffer and window management
1415
- 📝 Support for file operations and diagnostics
@@ -19,9 +20,10 @@ A Neovim plugin that integrates with Claude Code CLI to provide a seamless AI co
1920

2021
- Neovim >= 0.8.0
2122
- Claude Code CLI installed and in your PATH
22-
- Lua >= 5.1
2323
- **Optional for terminal integration:** [folke/snacks.nvim](https://github.com/folke/snacks.nvim) - Terminal management plugin (can use native Neovim terminal as an alternative).
2424

25+
**Zero External Dependencies**: The WebSocket server is implemented using pure Neovim built-ins (`vim.loop`, `vim.json`, `vim.schedule`) with no external Lua libraries required.
26+
2527
Note: The terminal feature can use `Snacks.nvim` or the native Neovim terminal. If `Snacks.nvim` is configured as the provider but is not available, it will fall back to the native terminal.
2628

2729
## Installation

flake.nix

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@
4242
luajitPackages.busted
4343
luajitPackages.luacov
4444

45-
luajitPackages.luasocket
46-
luajitPackages.lua-cjson
47-
4845
ast-grep
4946
neovim
5047
luarocks

lua/claudecode/init.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ function M.setup(opts)
8383
end
8484

8585
M.state.config = vim.tbl_deep_extend("force", vim.deepcopy(default_config), opts)
86+
vim.g.claudecode_user_config = vim.deepcopy(M.state.config) -- Make config globally accessible
8687

8788
if terminal_opts then
8889
local terminal_setup_ok, terminal_module = pcall(require, "claudecode.terminal")

lua/claudecode/meta/vim.lua

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,37 @@
2525
---@field once boolean|nil
2626
---@field on_close_timeout number|nil
2727

28+
---@class vim_options_table: table<string, any>
29+
30+
---@class vim_buffer_options_table: table<string, any>
31+
32+
---@class vim_bo_proxy: vim_buffer_options_table
33+
---@operator index (key: number): vim_buffer_options_table # Allows vim.bo[bufnr]
34+
35+
---@class vim_diagnostic_info
36+
---@field bufnr number
37+
---@field col number
38+
---@field end_col number|nil
39+
---@field end_lnum number|nil
40+
---@field lnum number
41+
---@field message string
42+
---@field severity number
43+
---@field source string|nil
44+
---@field user_data any|nil
45+
46+
---@class vim_diagnostic_module
47+
---@field get fun(bufnr?: number, ns_id?: number): vim_diagnostic_info[]
48+
-- Add other vim.diagnostic functions as needed, e.g., get_namespace, set, etc.
49+
2850
---@class vim_global_api
2951
---@field notify fun(msg: string | string[], level?: number, opts?: vim_notify_opts):nil
3052
---@field log vim_log
3153
---@field _last_echo table[]? # table of tables, e.g. { {"message", "HighlightGroup"} }
3254
---@field _last_error string?
55+
---@field o vim_options_table # For vim.o.option_name
56+
---@field bo vim_bo_proxy # For vim.bo.option_name and vim.bo[bufnr].option_name
57+
---@field diagnostic vim_diagnostic_module # For vim.diagnostic.*
58+
---@field empty_dict fun(): table # For vim.empty_dict()
3359
-- Add other vim object definitions here if they cause linting issues
3460
-- e.g. vim.fn, vim.api, vim.loop, vim.deepcopy, etc.
3561

0 commit comments

Comments
 (0)