Common Lisp language support for the Zed editor with integrated LSP server and Jupyter kernel support.
Features
- LSP Features: Syntax highlighting, autocomplete, hover documentation, goto-definition
- Smart Completion: Type-aware parameter snippets, package-qualified completions
- Multi-Package Support: Package labels, user symbols prioritized
- Interactive REPL: Built-in REPL with
Ctrl+Shift+Enter, shared state across files - Rich Output: Display markdown, tables, images, and JSON inline
- Jupyter Compatible: Optional Jupyter Lab/Notebook support
- Cross-Platform: Works on macOS and Linux (not tested)
Prerequisites
Required for all features:
-
Common Lisp Implementation (one of):
-
SBCL (recommended - full feature support):
- macOS:
brew install sbcl - Linux:
apt install sbcl/dnf install sbcl/pacman -S sbcl
- macOS:
-
ECL (alternative - ~90% feature parity):
- macOS:
brew install ecl - Linux:
apt install ecl/dnf install ecl/pacman -S ecl
- macOS:
Configure your preferred implementation via
~/.zed-cl/config.json(see Configuration section below). -
Note: Quicklisp and required dependencies will be installed automatically during the build process (make build or make setup-quicklisp).
Development Installation
git clone https://github.com/etyurkin/zed-cl
cd zed-cl
make buildIn Zed:
- Open command palette (
Cmd+Shift+P) - Run "zed: install dev extension"
- Select the cloned directory
Configuration
All configuration is stored in ~/.zed-cl/config.json using profiles:
{
"active_profile": "sbcl",
"profiles": {
"sbcl": {
"lisp_impl": "sbcl",
"system_index": "system-index.db",
"completion_package_whitelist": [
"CORE-KEYWORDS",
"COMMON-LISP",
"COMMON-LISP-USER"
]
}
}
}Profile Settings
Each profile can configure:
lisp_impl- Common Lisp implementation ("sbcl"or"ecl")system_index- System index database filename (in~/.zed-cl/)completion_package_whitelist- Packages to show in completions
Multiple Profiles
Create different profiles for different workflows:
{
"active_profile": "sbcl-full",
"profiles": {
"sbcl-full": {
"lisp_impl": "sbcl",
"system_index": "sbcl-complete.db",
"completion_package_whitelist": ["CORE-KEYWORDS", "COMMON-LISP", "COMMON-LISP-USER"]
},
"ecl-dev": {
"lisp_impl": "ecl",
"system_index": "ecl-packages.db",
"completion_package_whitelist": ["COMMON-LISP", "COMMON-LISP-USER"]
},
"minimal": {
"lisp_impl": "sbcl",
"system_index": "system-index.db",
"completion_package_whitelist": ["COMMON-LISP"]
}
}
}Switch profiles by changing active_profile and restarting Zed.
Completion Package Whitelist
Control which packages appear in completions. By default (when not set), shows all user-defined packages plus COMMON-LISP and KEYWORD.
Special values:
"CORE-KEYWORDS"- Only core keywords (excludes system keywords)"ALL-KEYWORDS"- All keywords including system ones
Using the Extension
LSP Features
Open any .lisp file and get:
- Autocomplete for Common Lisp built-ins and your code
- Hover documentation
- Goto-definition
- Package-aware completions
Interactive REPL
Inline evaluation:
- Open a
.lispfile - Select code or position cursor in a form
- Press
Ctrl+Shift+Enterto evaluate - See results inline
Terminal REPL (for development):
- Open command palette (
Cmd+Shift+P) - Type "Tasks: Spawn"
- Select "Common Lisp REPL"
- Get an interactive REPL in a terminal tab
All evaluations share a single REPL environment - definitions are automatically available in autocomplete.
Direct Terminal Connection (Advanced):
For debugging or advanced use, connect directly to the master REPL socket:
./scripts/connect-repl.sh
This connects via Unix domain socket to the shared REPL using the configured Lisp implementation.
Building a System Index (Optional)
Goto-definition works out-of-the-box for your workspace code. To enable goto-definition for external libraries (Quicklisp packages, SBCL built-ins, etc.), build a system index.
Quick Start
The extension bundles an indexer tool at ~/.zed/extensions/installed/zed-cl/<version>/bin/zed-cl-index.
For SBCL users - index SBCL sources:
# Using Makefile (indexes SBCL built-ins) make build-system-index # Or manually ~/.zed/extensions/installed/zed-cl/<version>/bin/zed-cl-index \ --source-dir /path/to/sbcl/src/code \ --output ~/.zed-cl/system-index.db \ --default-package COMMON-LISP
For all users - index Quicklisp packages:
# Example: Index Alexandria zed-cl-index \ --source-dir ~/quicklisp/dists/quicklisp/software/alexandria-<version> \ --output ~/.zed-cl/system-index.db \ --default-package ALEXANDRIA
Finding SBCL Source
macOS (Homebrew):
$(brew --prefix sbcl)/share/sbcl/src # Usually: /opt/homebrew/share/sbcl/src or /usr/local/share/sbcl/src
Linux:
/usr/share/sbcl/src # Debian/Ubuntu /usr/share/sbcl-source/src # Some distributions
Indexer Commands
Build an index:
zed-cl-index \ --source-dir <PATH> # Directory containing .lisp files (searches recursively) --output <DB_FILE> # Output database file (appends if exists) --default-package <PACKAGE> # Default package for symbols without (in-package ...)
Query an index:
zed-cl-index \ --query \ --database <DB_FILE> # Database to query --symbol <SYMBOL> # Symbol name (e.g., MAPCAR, FORMAT) [required] --package <PACKAGE> # Package name (e.g., SB-IMPL) [optional - searches all packages if omitted]
Examples
Index SBCL standard library:
# Core runtime (list functions, sequences, etc.) zed-cl-index \ --source-dir /opt/homebrew/share/sbcl/src/code \ --output ~/.zed-cl/system-index.db \ --default-package COMMON-LISP # CLOS/MOP (classes, methods, generic functions) zed-cl-index \ --source-dir /opt/homebrew/share/sbcl/src/pcl \ --output ~/.zed-cl/system-index.db \ --default-package COMMON-LISP # Interpreter zed-cl-index \ --source-dir /opt/homebrew/share/sbcl/src/interpreter \ --output ~/.zed-cl/system-index.db \ --default-package COMMON-LISP
Index Quicklisp libraries:
# Alexandria zed-cl-index \ --source-dir ~/quicklisp/dists/quicklisp/software/alexandria-20241012-git \ --output ~/.zed-cl/system-index.db \ --default-package ALEXANDRIA # Iterate zed-cl-index \ --source-dir ~/quicklisp/dists/quicklisp/software/iterate-1.5.3 \ --output ~/.zed-cl/system-index.db \ --default-package ITERATE
Query the index:
# Find MAPCAR in a specific package zed-cl-index --query \ --database ~/.zed-cl/system-index.db \ --package SB-IMPL \ --symbol MAPCAR # Output: # Looking up: SB-IMPL::MAPCAR # # Found 1 definition(s): # # [1] function in SB-IMPL # File: /opt/homebrew/share/sbcl/src/code/list.lisp # Position: line 1388, char 19 # Find MAPCAR in all packages (omit --package) zed-cl-index --query \ --database ~/.zed-cl/system-index.db \ --symbol MAPCAR # Output: # Looking up: MAPCAR (in all packages) # # Found 1 definition(s) across packages: # # [1] function in SB-IMPL # File: /opt/homebrew/share/sbcl/src/code/list.lisp # Position: line 1388, char 19
Multiple System Indexes (Advanced)
Create different indexes for different projects:
# Minimal: Just SBCL core zed-cl-index \ --source-dir /path/to/sbcl/src/code \ --output ~/.zed-cl/system-sbcl-only.db \ --default-package COMMON-LISP # Full: SBCL + all your Quicklisp libraries zed-cl-index \ --source-dir /path/to/sbcl/src/code \ --output ~/.zed-cl/system-full.db \ --default-package COMMON-LISP # ... add more libraries
Switch between indexes by changing the system_index field in your active profile in ~/.zed-cl/config.json and restarting the extension.
How It Works
- User code: Automatically indexed when you open/save
.lispfiles →~/.zed-cl/user-index.db - System libraries: Manually indexed using
zed-cl-index→~/.zed-cl/system-index.db(or custom name) - Goto-definition search order:
- User index (your workspace code)
- System index (SBCL + libraries you indexed)
Development Commands
# Build make build # Build Rust binaries and extension make dev # Development mode make check # Type check only make test # Run tests # Jupyter make install-jupyter # Register kernel for Jupyter make verify # Verify SBCL installation # Maintenance make clean # Clean build artifacts make help # Show all commands
Process Management
List running processes:
# Count each process type ps aux | grep -c '[z]ed-cl-kernel' # Count kernels ps aux | grep -c '[z]ed-cl-lsp' # Count LSP servers ps aux | grep -c 'master-repl' # Count master REPLs # Show detailed process list ps aux | grep -E 'zed-cl-kernel|zed-cl-lsp|master-repl' | grep -v grep
Kill processes:
# Kill all zed-cl processes pkill -f 'zed-cl-kernel' && pkill -f 'zed-cl-lsp' && pkill -f 'master-repl' # Kill individual components pkill -f 'zed-cl-kernel' # Kill only kernels pkill -f 'zed-cl-lsp' # Kill only LSP pkill -f 'master-repl' # Kill only master REPL # Force kill if needed pkill -9 -f 'zed-cl-kernel' && pkill -9 -f 'zed-cl-lsp' && pkill -9 -f 'master-repl'
Log Locations
LSP Server:
/tmp/cl-zed-lsp.log- LSP debug logs/tmp/master-repl.log- Master REPL logs
Zed Application:
~/Library/Logs/Zed/Zed.log(macOS)~/.local/share/zed/logs/Zed.log(Linux)
Database Indexes:
~/.zed-cl/system-index.db- System libraries (SBCL + manually indexed packages)~/.zed-cl/user-index.db- User workspace code (auto-indexed)
Architecture
┌───────────────────────┐
│ Master REPL Process │
│ (Unix domain sockets) │
└──────────┬────────────┘
│
┌─────────┼──────────┐
│ │ │
┌───▼───┐ ┌──▼───┐ ┌───▼───┐
│Console│ │ Zed │ │ Zed │
│ REPL │ │ REPL │ │ LSP │
└───────┘ └──────┘ └───────┘
All components connect to a single master REPL via Unix domain sockets for true state sharing. Code evaluated in any component is immediately available in all others.
License
MIT