capytrace.nvim is a lightweight, privacy-first debugging session recorder for Neovim. It automatically captures your development workflow—file edits, cursor movements, terminal commands, and LSP diagnostics—into structured, timestamped session logs. Designed with a focus on signal-over-noise, capytrace intelligently filters redundant events and provides actionable insights into your debugging process.
- 🔒 Privacy First: All data stays local—zero external APIs or telemetry
- ⚡ High Performance: Smart event filtering eliminates 90% of cursor noise
- 💾 Multiple Formats: Export to Markdown, JSON, or SQLite for different use cases
- 🚀 Non-Blocking: Background Goroutines ensure your editor stays responsive
- 📦 Zero Dependencies: Pure Go with no CGO—builds on any platform
- 🎯 Developer-Centric: Actionable statistics and intuitive session management
- Features
- Requirements
- Installation
- Quick Start
- Configuration
- Usage
- Output Examples
- Architecture
- Performance
- Development
- Contributing
- License
- Support
- Live Session Recorder: Automatically captures file edits, cursor movements, terminal commands, file opens, and LSP diagnostics
- Smart Event Filtering: Intelligent cursor debouncing (200ms) and idle detection (500ms) reduce noise while preserving meaningful context
- Structured Timeline: Events are timestamped and organized chronologically for easy review
- User Annotations: Add inline notes during debugging sessions—automatically timestamped and integrated into session logs
- Session Management: List, resume, or query any previous debugging session without losing context
- Markdown: Human-readable session reports with emojis and formatted timelines
- JSON: Machine-readable data suitable for programmatic analysis and integration
- SQLite: Queryable database for aggregating statistics across multiple sessions
- Context-Aware Logging: File edits and terminal commands immediately flush pending cursor events for accurate context
- Configurable Thresholds: Adjust debounce intervals and idle detection times to your workflow
- Session Resumption: Continue debugging from exactly where you left off
- Statistics Command: Analyze session metrics (duration, event counts, code vs. navigation time)
- Neovim: v0.9.0 or higher
- Go: v1.18 or higher (required to build from source)
- Make: For building (optional, see Building from Source)
Add the following to your lazy.nvim configuration:
{
"andev0x/capytrace.nvim",
build = "make build", -- Builds the Go binary automatically
config = function()
require("capytrace").setup({
output_format = "markdown", -- or "json" or "sqlite"
save_path = "~/capytrace_logs/",
filter_threshold = 500, -- Idle detection threshold (ms)
debounce_interval = 200, -- Cursor debounce interval (ms)
})
end,
}Plug 'andev0x/capytrace.nvim', { 'do': 'make build' }-
Clone the repository:
git clone https://github.com/andev0x/capytrace.nvim.git cd capytrace.nvim -
Build the Go binary:
make build
-
Add the plugin path to your Neovim configuration and call setup:
require("capytrace").setup()
:CapyTraceStart myprojectThis creates a new debugging session for your project. The plugin will now record all relevant events.
The plugin automatically records:
- File edits (TextChanged, TextChangedI)
- Cursor movements (intelligently filtered)
- File opens (BufEnter)
- Terminal commands (TermOpen)
- LSP diagnostics (DiagnosticChanged)
- User annotations (
:CapyTraceAnnotate)
:CapyTraceEndThe session is exported to your configured format (Markdown, JSON, or SQLite) and saved to save_path.
:CapyTraceList " List all recorded sessions
:CapyTraceStatus " Show current session statusAll settings are optional. Defaults are designed for typical use cases:
require("capytrace").setup({
-- Output format for exported sessions
output_format = "markdown", -- "markdown" | "json" | "sqlite"
-- Directory where sessions are saved
save_path = "~/capytrace_logs/",
-- Smart Filter: Idle threshold before committing cursor position (milliseconds)
filter_threshold = 500,
-- Smart Filter: Debounce interval for rapid cursor movements (milliseconds)
debounce_interval = 200,
-- Auto-save session when closing Neovim
auto_save_on_exit = true,
-- Maximum cursor movement events per session (for memory efficiency)
max_cursor_events = 100,
-- Event logging preferences
log_events = {
terminal_commands = true, -- Log TermOpen events
file_open = true, -- Log BufEnter events
lsp_diagnostics = true, -- Log LSP diagnostics
},
})The plugin uses an intelligent cursor filter to reduce noise:
- Debouncing (default 200ms): Rapid keyboard navigation (j/k) within 200ms is considered a single movement
- Idle Detection (default 500ms): Cursor position is only recorded after staying idle for 500ms
- Context Triggers: Immediate recording on file edits, terminal commands, or session end
This approach reduces cursor events by ~90% while preserving meaningful context.
" Start a new debugging session
:CapyTraceStart [project_name]
" End the current session and export
:CapyTraceEnd
" Add a note to the current session
:CapyTraceAnnotate This is a note
" Show status of current session
:CapyTraceStatus
" List all available sessions
:CapyTraceList
" Resume a previous session
:CapyTraceResume session_id# Start a session
./bin/capytrace start <session_id> <project_path> <save_path> <format>
# End a session
./bin/capytrace end <session_id> <save_path>
# Add annotation
./bin/capytrace annotate <session_id> <save_path> "note text"
# Record events
./bin/capytrace record-edit <session_id> <save_path> <filename> <line> <col> <line_count> <changed_tick>
./bin/capytrace record-cursor <session_id> <save_path> <filename> <line> <col>
./bin/capytrace record-terminal <session_id> <save_path> "command"
# Session management
./bin/capytrace list <save_path>
./bin/capytrace resume <session_id> <save_path>
./bin/capytrace stats <save_path> [session_id]# Debug Session: 1704067200_myproject
**Project:** /home/user/myproject
**Started:** 2026-01-01T10:00:00Z
**Ended:** 2026-01-01T11:30:00Z
**Duration:** 1h30m0s
---
## Timeline
### 10:00:00 - Session Started
🚀 Started debugging session in /home/user/myproject
### 10:05:23 - File Edit
📄 **File:** `src/auth.lua`
📍 **Position:** Line 45, Column 12
📊 **Total Lines:** 120
### 10:07:15 - Terminal Command
💻 ```bash
git log --oneline -10📝 Found potential issue in authentication logic
🏁 Debugging session ended
- Total Events: 25
- File Edits: 12
- Terminal Commands: 8
- Annotations: 3
- Cursor Movements: 2
### JSON Format
```json
{
"id": "1704067200_myproject",
"project_path": "/home/user/myproject",
"start_time": "2026-01-01T10:00:00Z",
"end_time": "2026-01-01T11:30:00Z",
"output_format": "json",
"active": false,
"events": [
{
"type": "session_start",
"timestamp": "2026-01-01T10:00:00Z",
"data": {
"note": "Started debugging session in /home/user/myproject"
}
},
{
"type": "file_edit",
"timestamp": "2026-01-01T10:05:23Z",
"data": {
"filename": "src/auth.lua",
"line": 45,
"column": 12,
"line_count": 120,
"changed_tick": 5
}
}
]
}
$ capytrace stats ~/capytrace_logs/
Session Statistics
==================
1704067200_myproject:
Status: Completed
Duration: 1h30m0s
Total Events: 25
File Edits: 12
Cursor Moves: 2
Terminal Commands: 8
Annotations: 3
┌─────────────────────────────────────────────────────────┐
│ Neovim Editor │
├─────────────────────────────────────────────────────────┤
│ Lua Frontend (lua/capytrace/) │
│ - Listens to editor events │
│ - Manages user commands │
│ - Communicates with Go backend │
├─────────────────────────────────────────────────────────┤
│ Go Backend (cmd/capytrace/main.go) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Recorder │ │ Filter │ │ Exporter │ │
│ │ (Session │ │ (Smart │ │ (Markdown, │ │
│ │ State) │ │ Filtering) │ │ JSON, │ │
│ │ │ │ │ │ SQLite) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Storage (Local Filesystem / SQLite) │
│ - Session JSON files │
│ - Exported reports (Markdown/JSON) │
│ - SQLite database (optional) │
└─────────────────────────────────────────────────────────┘
Lua Frontend (lua/capytrace/)
- Hooks into Neovim autocommands (TextChanged, BufEnter, CursorMoved, etc.)
- Invokes the Go binary with appropriate arguments
- Manages user-facing commands and configuration
- Ensures UI remains responsive during recording
Go Backend (cmd/capytrace/)
- Recorder: Manages session state, buffers events, persists to disk
- Filter: Implements the Smart Filter for cursor event debouncing
- Exporter: Converts sessions to Markdown, JSON, or SQLite formats
- Models: Shared data structures across all components
Storage
- JSON Files (default): Direct, human-readable session logs
- SQLite Database: Queryable storage for analytics and session merging
- Standard Directory:
~/.local/share/capytrace/(follows XDG spec)
- Non-blocking I/O: All file operations use Goroutines to prevent editor lag
- Thread-safe Sessions: RWMutex protects concurrent access to session state
- Buffered Channels: Events are queued and processed asynchronously
Capytrace's Smart Filter significantly reduces event noise:
| Event Type | Before Filter | After Filter | Reduction |
|---|---|---|---|
| Cursor Movements | ~1000 events/session | ~100 events | ~90% |
| File Edits | Unchanged | Unchanged | 0% |
| Terminal Commands | Unchanged | Unchanged | 0% |
| Annotations | Unchanged | Unchanged | 0% |
- macOS: ~9.8 MB (single binary, no dependencies)
- Linux: ~8.5 MB (single binary, no dependencies)
- Windows: ~9.2 MB (single binary, no dependencies)
- Idle: <5 MB
- Recording: 5-15 MB (depends on event frequency and session size)
- Session Size: ~1-2 MB per hour of typical development
capytrace.nvim/
├── cmd/capytrace/ # Entry point and CLI
├── internal/ # Core packages
│ ├── filter/ # Smart cursor filter
│ ├── recorder/ # Session management
│ ├── exporter/ # Export formats
│ └── models/ # Data structures
├── lua/capytrace/ # Lua frontend
├── plugin/ # Neovim plugin entry
├── assets/ # Static assets
├── Makefile # Build system
├── go.mod # Go dependencies
└── README.md # This file
# Clone repository
git clone https://github.com/andev0x/capytrace.nvim.git
cd capytrace.nvim
# Build binary
make build
# Run tests
make test
# Format code
make fmt
# Clean build artifacts
make clean- Go: Follow Effective Go conventions
- Documentation: All exported functions must have doc comments
- Testing: Unit tests for filter, recorder, and exporter packages
- Formatting: Use
go fmtbefore committing
| Package | Purpose | License |
|---|---|---|
modernc.org/sqlite |
Pure-Go SQLite driver | Apache 2.0 |
Minimal dependencies ensure fast builds and maximum portability.
We welcome contributions from the community! Whether it's bug fixes, feature requests, or documentation improvements, your help is valuable.
- Fork the repository on GitHub
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/capytrace.nvim.git
- Create a feature branch:
git checkout -b feature/your-feature-name
- Make your changes and ensure code quality:
make fmt # Format code make test # Run tests
- Commit with clear, concise messages:
git commit -m "feat: add new feature" -m "Detailed description of changes"
- Push to your fork:
git push origin feature/your-feature-name
- Open a Pull Request on GitHub with a clear description
Found a bug? Please open an issue with:
- A clear, descriptive title
- Steps to reproduce the issue
- Expected vs. actual behavior
- Your Neovim version (
nvim --version) - Your Go version (
go version)
Have an idea for improvement? Open an issue with:
- A clear use case and motivation
- Description of the proposed feature
- Any relevant examples or mockups
- Use
nvim -u NORC -c "edit test.nvim"to test without your config - Enable verbose logging:
let g:capytrace_debug = 1 - Check Go code quality:
go vet ./... - Profile performance:
go test -bench=. ./internal/...
This project is licensed under the MIT License. See the LICENSE file for full details.
You are free to:
- ✅ Use this software for any purpose
- ✅ Copy, modify, and distribute the software
- ✅ Include the software in proprietary applications
Under the condition that:
- ℹ️ You include a copy of the license and copyright notice
- 📖 Documentation: Check docs/ for detailed guides
- 🐛 Bug Reports: Open an issue on GitHub Issues
- 💬 Discussions: Join our community discussions
- 📧 Email: For security issues, email maintainers directly
Q: Does capytrace send data to external servers? A: No. All data stays on your machine. There's no telemetry or external API calls.
Q: What's the performance impact? A: Minimal. The Smart Filter and non-blocking I/O ensure your editor stays responsive. Typical overhead is <5% CPU.
Q: Can I export sessions to other formats? A: Currently supported: Markdown, JSON, SQLite. More formats can be added via the exporter interface.
Q: How much disk space do sessions use? A: Approximately 1-2 MB per hour of development, depending on event frequency.
Q: Can I share sessions with teammates? A: Yes! Export to JSON or SQLite format and share the files. Markdown exports are also shareable.
- ✅ Smart event filtering
- ✅ Multi-format export (Markdown, JSON, SQLite)
- ✅ Session management and resumption
- ✅ Statistics and analytics
- ✅ Professional architecture (cmd/internal pattern)
- 🔄 Web-based session viewer
- 🔄 Git integration (correlate with commits)
- 🔄 Multi-session merging and aggregation
- 🔄 Custom event hooks
- 🔄 Session tagging and search
- 🔄 Visual timeline renderer
- Built with ❤️ using Go and Lua
- Thanks to the Neovim community
- Inspired by flight data recorders and black-box logging concepts
See CHANGELOG.md for version history and release notes.
If capytrace.nvim has been helpful in your development workflow, consider supporting the project:
- 🌟 Star the repository on GitHub
- 💰 Sponsor via GitHub Sponsors
- ☕ Donate via Buy Me a Coffee
Your support helps maintain and improve the project for everyone!
Made with ❤️ by the capytrace community
GitHub · Issues · Discussions
