leta - LSP Enabled Tools for Agents
leta is a command-line LSP client for semantic code navigation. It provides fast symbol search, reference finding, call hierarchy analysis, and refactoring operations by leveraging language server protocols across multiple programming languages.
$ leta grep "Handler$" -k class
src/handlers/auth.py:15 [Class] AuthHandler
src/handlers/user.py:22 [Class] UserHandler
src/handlers/admin.py:8 [Class] AdminHandler
$ leta show UserHandler
src/handlers/user.py:22-67
class UserHandler:
def __init__(self, db: Database):
self.db = db
def get_user(self, user_id: int) -> User:
return self.db.query(User).get(user_id)
...
Table of contents
- Installation
- Quick start
- AI agent skill
- Commands
- Symbol formats
- Daemon management
- Workspace management
- Configuration
- Supported languages
- Development
- License
Installation
Using Homebrew (macOS)
brew install andreasjansson/tap/leta
Using Cargo
From source
git clone https://github.com/andreasjansson/leta
cd leta
cargo install --path crates/leta
cargo install --path crates/leta-daemonLanguage servers
Ensure you have language servers installed for your target languages:
# Python pip install basedpyright # TypeScript/JavaScript npm install -g typescript-language-server typescript # Go go install golang.org/x/tools/gopls@latest # Rust rustup component add rust-analyzer # Ruby gem install ruby-lsp # C/C++ brew install llvm # macOS apt install clangd # Ubuntu
Quick start
Initialize a workspace before using leta:
cd /path/to/your/project
leta workspace addGet a full architectural overview:
leta graph # Full call graph as trees from entry pointsSearch for symbols:
leta grep "User" # Find symbols matching "User" leta grep "^Test" -k function # Find test functions
Show symbol definitions:
leta show UserRepository # Show full class body leta show UserRepository.add_user # Show method body
Find references:
leta refs validate_email # Find all uses of validate_email leta refs UserRepository -n 2 # With 2 lines of context
AI agent skill
leta includes a skill file that teaches AI coding agents (like Claude Code or
OpenCode) how to use leta effectively. The skill instructs agents to prefer
leta show over reading files, leta refs over grepping for usages, etc.
OpenCode
Copy the skill to your OpenCode skills directory:
cp -r skills/leta ~/.config/opencode/skills/Then load the skill with /skill leta or configure it to load automatically.
Claude Code
Copy the skill to your Claude Code skills directory:
# Personal (available across all your projects): cp -r skills/leta ~/.claude/skills/ # Project-specific (commit to version control): cp -r skills/leta .claude/skills/
Commands
grep
Search for symbols by regex pattern. Unlike text search tools, leta grep
searches symbol names semantically—it finds function definitions, class
declarations, method names, etc.
leta grep <PATTERN> [PATH] [OPTIONS] Options: -k, --kind <KIND> Filter by symbol kind (comma-separated: class, function, method, etc.) -x, --exclude <EXCLUDE> Exclude files matching regex (repeatable) -C, --case-sensitive Case-sensitive matching -N, --head <N> Maximum results (0 = unlimited) [default: 500]
The optional PATH argument filters files by matching a regex against the relative file path. This is simpler and more powerful than glob patterns.
Examples:
# Find all classes ending with "Handler" leta grep "Handler$" -k class # Find functions in Python files only leta grep "validate" '\.py$' -k function # Find symbols in a specific directory leta grep "User" "models/" # Find symbols in test files leta grep "test" "test/" # Exclude test files leta grep "User" -x test -x mock
When to use leta grep vs ripgrep:
- Use
leta grepfor: finding symbol definitions, filtering by kind, getting semantic matches - Use ripgrep for: searching file contents, string literals, comments, multi-word phrases
files
Show source file tree with line counts.
leta files [PATH] [OPTIONS] Options: -x, --exclude <EXCLUDE> Exclude files matching regex (repeatable) -i, --include <INCLUDE> Include default-excluded dirs (repeatable) -f, --filter <FILTER> Only include files matching regex -N, --head <N> Maximum files (0 = unlimited) [default: 500]
Example output:
src
├── handlers
│ ├── auth.py (2.3KB, 89 lines, 1 class, 5 methods)
│ └── user.py (3.1KB, 112 lines, 2 classes, 8 methods)
├── models
│ └── user.py (1.8KB, 67 lines, 1 class, 4 methods)
└── main.py (845B, 32 lines, 2 functions)
4 files, 8.0KB, 300 lines
show
Print the full definition of a symbol.
leta show <SYMBOL> [OPTIONS] Options: -n, --context <N> Lines of context around definition [default: 0] -N, --head <N> Maximum lines (0 = unlimited) [default: 500]
Examples:
leta show UserRepository # Show full class leta show UserRepository.add_user # Show method leta show "*.py:User" # Filter by file leta show COUNTRY_CODES # Multi-line constants work too
refs
Find all references to a symbol.
leta refs <SYMBOL> [OPTIONS] Options: -n, --context <N> Lines of context around each reference [default: 0] -N, --head <N> Maximum results (0 = unlimited) [default: 500]
Examples:
leta refs UserRepository
leta refs validate_email -n 2
leta refs "models.py:User"calls
Show call hierarchy for a symbol.
leta calls [OPTIONS] Options: --from <SYMBOL> Show what SYMBOL calls (outgoing) --to <SYMBOL> Show what calls SYMBOL (incoming) --max-depth <N> Maximum recursion depth [default: 3] --include-non-workspace Include stdlib/dependency calls -N, --head <N> Maximum results (0 = unlimited) [default: 500]
At least one of --from or --to is required. Use both to find a path.
Examples:
# What does main() call? leta calls --from main # What calls validate_email()? leta calls --to validate_email # Find call path from main to save leta calls --from main --to save --max-depth 5
graph
Show the full workspace call graph as trees rooted at entry points. This is the most token-efficient way to understand the architecture of a codebase. Test files are excluded by default.
leta graph [OPTIONS]
Options:
--include-non-workspace Include stdlib/dependency calls
--include-tests Include test files (excluded by default)
-x, --exclude-path Exclude paths matching regex (repeatable)
-i, --include-path Only include paths matching regex (repeatable)
--include-orphans Include symbols with no callers or calleesThe output shows trees from entry points (functions nothing else calls),
largest subgraph first. Nodes already shown get a ↑ marker; recursive
calls get ↻. Multi-language workspaces are grouped by language.
Examples:
# Full call graph leta graph # Only Go files leta graph -i '\.go$' # Include stdlib calls leta graph --include-non-workspace # Exclude generated code leta graph -x generated -x proto
implementations
Find implementations of an interface or abstract method.
leta implementations <SYMBOL> [OPTIONS] Options: -n, --context <N> Lines of context [default: 0] -N, --head <N> Maximum results (0 = unlimited) [default: 500]
Examples:
leta implementations Storage leta implementations Storage.save
supertypes / subtypes
Navigate type hierarchies.
leta supertypes <SYMBOL> [OPTIONS] # Find parent types leta subtypes <SYMBOL> [OPTIONS] # Find child types Options: -n, --context <N> Lines of context [default: 0] -N, --head <N> Maximum results (0 = unlimited) [default: 500]
declaration
Find the declaration of a symbol (useful for languages that separate declaration from definition).
leta declaration <SYMBOL> [OPTIONS] Options: -n, --context <N> Lines of context [default: 0] -N, --head <N> Maximum results (0 = unlimited) [default: 500]
rename
Rename a symbol across the entire workspace.
leta rename <SYMBOL> <NEW_NAME>
Examples:
leta rename old_function new_function
leta rename UserRepository.add_user insert_user
leta rename "user.py:User" Personmv
Move/rename a file and update all imports.
leta mv <OLD_PATH> <NEW_PATH>
Supported by: TypeScript, Rust, Python (via basedpyright).
Examples:
leta mv src/user.ts src/models/user.ts leta mv lib/utils.rs lib/helpers.rs
Symbol formats
Most commands accept symbols in these formats:
| Format | Description |
|---|---|
SymbolName |
Find symbol by name |
Parent.Symbol |
Qualified name (Class.method, module.function) |
path:Symbol |
Filter by file path pattern |
path:Parent.Symbol |
Combine path filter with qualified name |
path:line:Symbol |
Exact file + line number (for edge cases) |
Examples:
leta show UserRepository # By name leta show UserRepository.add_user # Qualified leta show "*.py:User" # Path filter leta show "models/user.py:User" # Specific file
Daemon management
leta runs a background daemon that manages LSP server connections. The daemon starts automatically on first command and persists to make subsequent commands fast.
leta daemon start # Start daemon leta daemon stop # Stop daemon leta daemon restart # Restart daemon leta daemon info # Show daemon status and active workspaces
Workspace management
Workspaces must be explicitly added before using leta:
leta workspace add # Add current directory leta workspace add /path # Add specific path leta workspace remove # Remove current workspace leta workspace restart # Restart language servers leta workspace info # Show workspace info for current directory
Configuration
Configuration is stored in ~/.config/leta/config.toml:
[daemon] log_level = "info" request_timeout = 30 hover_cache_size = 268435456 # 256MB symbol_cache_size = 268435456 # 256MB [workspaces] roots = ["/home/user/projects/myapp"] excluded_languages = ["json", "yaml", "html"] [formatting] tab_size = 4 insert_spaces = true [servers.python] preferred = "basedpyright"
View configuration:
Logs are stored in ~/.cache/leta/log/.
Supported languages
| Language | Server | Install |
|---|---|---|
| Python | basedpyright | pip install basedpyright |
| TypeScript/JavaScript | typescript-language-server | npm install -g typescript-language-server typescript |
| Go | gopls | go install golang.org/x/tools/gopls@latest |
| Rust | rust-analyzer | rustup component add rust-analyzer |
| Java | jdtls | brew install jdtls |
| Ruby | ruby-lsp | gem install ruby-lsp |
| C/C++ | clangd | brew install llvm |
| PHP | intelephense | npm install -g intelephense |
| Lua | lua-language-server | brew install lua-language-server |
| OCaml | ocamllsp | opam install ocaml-lsp-server |
| Zig | zls | brew install zls |
Development
# Run unit tests ./script/unit-test # Run corpus tests ./script/corpus-test # Run linter ./script/lint # Format code ./script/format
License
MIT