Skip to content

rewasa/hermes-code-intel-plugin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧠 hermes-code-intel-plugin

AST-aware code intelligence for Hermes Agent β€” tree-sitter + ast-grep + LSP

Add semantic code understanding to Hermes without forking the core repo. This plugin gives the agent 5 tools that understand your code's structure, not just its text β€” making it dramatically more token-efficient and accurate when navigating, searching, and refactoring codebases.

✨ Why?

Hermes ships with search_files (regex grep) and read_file (raw text). Those work, but they're blind to syntax β€” they match comments, strings, and formatting equally. This plugin adds:

  • Symbol extraction β€” get all functions, classes, methods with signatures and line numbers (without reading the whole file)
  • Structural search β€” find imports, decorators, function calls, try/catch blocks by AST node type, not regex
  • Safe refactoring β€” rename patterns, wrap functions, add parameters across files. Dry-run by default β€” preview changes before applying
  • Go-to-definition β€” LSP-powered jump to where a symbol is defined (falls back to AST if no LSP server)
  • Find all references β€” LSP-powered cross-file usage search (falls back to AST)

The result: 10–50x fewer tokens for code navigation tasks and far fewer false-positive matches.

πŸ›  Tools

Tool What it does Replaces
code_symbols Extract functions, classes, methods, interfaces, enums, structs from any file. Returns signatures + line numbers. Reading entire files just to see "what's in here?"
code_search Tree-sitter query-based structural search. Find function calls, imports, decorators, return statements, assignments by their semantic meaning. search_files / grep for code patterns
code_refactor ast-grep structural search-and-replace. Matches by AST structure, not raw text. Supports meta-variables ($NAME, $$BODY). patch / sed for structural changes
code_definition LSP go-to-definition. Falls back to tree-sitter AST analysis if no language server. Manual grep for symbol definitions
code_references LSP find-all-references. Falls back to tree-sitter AST analysis if no language server. Manual grep for symbol usages

Steering Hints

The plugin automatically injects hints into the built-in tool descriptions, so the agent naturally prefers the AST tools:

  • read_file β†’ "prefer code_symbols to understand what a file contains"
  • search_files β†’ "prefer code_search for structural code patterns"
  • patch β†’ "prefer code_refactor for AST-aware structural replacement"

No prompt changes needed β€” it just works.

Ensuring code_intel is Available (Config)

Make sure the plugin is enabled and the toolset is registered in your Hermes config:

# ~/.hermes/config.yaml
plugins:
  enabled:
    - code_intel

# code_intel is auto-injected into core toolsets on plugin load.
# Verify it's present for your platform:
platform_toolsets:
  cli:
    - ...existing...
    - code_intel
  discord:
    - ...existing...
    - code_intel

# Subagents inherit toolsets β€” ensure code_intel is in the delegation defaults:
delegation:
  default_toolsets:
    - terminal
    - file
    - code_intel

πŸ“¦ Installation

Quick install (from GitHub)

hermes plugins install rewasa/hermes-code-intel-plugin
hermes plugins enable code_intel

Manual install

# Clone into your plugins directory
git clone https://github.com/rewasa/hermes-code-intel-plugin.git ~/.hermes/plugins/code_intel

# Enable in your config
hermes plugins enable code_intel

Or add to ~/.hermes/config.yaml:

plugins:
  enabled:
    - code_intel

Dependencies

The plugin uses tree-sitter and ast-grep under the hood. Install them in your Hermes venv:

cd ~/.hermes/hermes-agent
source venv/bin/activate
pip install tree-sitter tree-sitter-languages ast-grep-py

LSP tools (code_definition, code_references) work without additional setup β€” they fall back to AST analysis when no language server is available. For full LSP support, install your preferred language server:

# Python (default β€” tried first)
pip install pyright

# TypeScript / JavaScript
npm install -g typescript-language-server typescript

# Rust
rustup component add rust-analyzer

# Go
go install golang.org/x/tools/gopls@latest

The plugin auto-discovers servers via PATH, monorepo node_modules/.bin, and npx fallback. No additional configuration needed.

Monorepo Support

The plugin automatically detects monorepo roots by scanning for pnpm-workspace.yaml, nx.json, or lerna.json. When found:

  • Workspace folders are parsed (e.g. apps/*, packages/*, modules/*) and sent to the LSP server during initialization
  • This enables cross-workspace type resolution β€” e.g. resolving @agentselly/logger imports across package boundaries
  • Works out of the box with pnpm, Nx, and Lerna monorepos β€” no config needed

The workspace folder list is cached per project root and cleared on shutdown.

TypeScript LSP Specifics

The TypeScript LSP integration has several smart behaviors for monorepo setups:

  1. tsconfig root detection β€” Instead of using the monorepo root as rootUri (which confuses TSServer with 60+ workspace folders), the plugin finds the nearest tsconfig.json directory. This gives accurate cross-file resolution within a single app while keeping monorepo folders as workspaceFolders.

  2. typeDefinition fallback β€” When go-to-definition on an import identifier returns the import binding itself (a TSServer quirk), the plugin automatically tries textDocument/typeDefinition to jump to the actual class/interface definition.

  3. Initialization retry β€” TS language server sometimes returns empty results on the first request (still indexing). The plugin retries once after 500ms for TS/JS files.

🌐 Supported Languages

Language Extensions Tree-sitter ast-grep LSP
Python .py, .pyi βœ… βœ… βœ… (pyright)
JavaScript .js, .jsx βœ… βœ… βœ…
TypeScript .ts βœ… βœ… βœ… (tsls)
TSX .tsx βœ… βœ… βœ… (tsls)
Rust .rs βœ… βœ… βœ… (rust-analyzer)
Go .go βœ… βœ… βœ… (gopls)
Java .java βœ… βœ… βœ… (jdtls)
C .c, .h βœ… β€” βœ… (clangd)
C++ .cpp βœ… β€” βœ… (clangd)

πŸ’¬ Slash Command

Once enabled, you get a /code-intel command in CLI and gateway sessions:

/code-intel status   β†’ Show AST symbol cache status
/code-intel clear    β†’ Clear the AST symbol cache (free memory)
/code-intel help     β†’ Show usage

πŸ”§ How It Works

Architecture

code_intel.py          ← tree-sitter tools (code_symbols, code_search, code_refactor)
lsp_bridge.py          ← LSP tools (code_definition, code_references)
__init__.py            ← plugin registration, steering hints, hooks

LSP Bridge Pooling

LSP bridges are keyed by (language_id, workspace_root) and pooled with LRU eviction:

  • Max 8 concurrent bridges β€” supports multi-language monorepos (Python + TypeScript + Go, etc.)
  • Lazy creation β€” bridges start on first use, not on plugin load
  • Auto-eviction β€” oldest idle bridge is shut down when the pool is full
  • Server fallback chain β€” e.g. pyright-langserver β†’ pylsp for Python; first available server wins
  • All bridges are cleaned up on session end via the on_session_end hook

Monorepo Workspace Discovery

For monorepo projects, the plugin detects root markers (pnpm-workspace.yaml, nx.json, lerna.json) separately from generic markers (.git, package.json). This prevents false stops at nested apps/*/package.json files. Discovered workspace folders are parsed and sent to the LSP server during initialization for full cross-workspace intelligence.

Symbol Caching

Parsed AST results are cached in memory (OrderedDict, max 2000 entries, LRU eviction). The cache is automatically cleared at session end via the on_session_end hook β€” no memory leaks during long-running gateway sessions.

Toolset Injection

On startup, the plugin dynamically injects into:

  • toolsets._HERMES_CORE_TOOLS (available on all platforms)
  • toolsets.TOOLSETS["hermes-acp"] (ACP / VS Code / JetBrains)
  • toolsets.TOOLSETS["hermes-api-server"] (API server mode)

πŸ§ͺ Development

cd ~/.hermes/plugins/code_intel

# Run tests (uses Hermes venv for tree-sitter dependencies)
PYTHONPATH=~/.hermes/plugins ~/.hermes/hermes-agent/venv/bin/python3 \
  -m pytest tests/test_code_intel.py -v

# Run a single test
PYTHONPATH=~/.hermes/plugins ~/.hermes/hermes-agent/venv/bin/python3 \
  -m pytest tests/test_code_intel.py::test_extract_symbols_python -v

πŸ“‹ Example: What the agent sees

Symbol Extraction (code_symbols)

Before (reading a 500-line file to find a function):

β†’ read_file("src/service.py")  β†’  500 lines, ~8000 tokens

After (using code_symbols):

β†’ code_symbols("src/service.py")
← {"symbols": [
    {"name": "processOrder", "kind": "function", "line": 42,
     "signature": "def processOrder(order_id: str, priority: int = 0) -> dict"},
    {"name": "OrderService", "kind": "class", "line": 120,
     "signature": "class OrderService"},
    {"name": "validate", "kind": "method", "line": 145,
     "signature": "def validate(self, order: Order) -> bool"}
  ]}
  β†’ ~200 tokens (40x savings)

LSP Benchmarks (TypeScript, NestJS monorepo)

Benchmarks from a real pnpm monorepo (~60 workspace folders). Tests performed with typescript-language-server v5.1.3 on Apple Silicon.

Tool Scenario Time Output Tokens
code_definition Import binding β†’ typeDefinition fallback ~1.5s (first request) ~272
code_definition Cached request ~0.65s ~290
code_definition External module (NestFactory) ~0.65s ~288
code_references Small class (DealsController) ~0.67s ~1,362
code_references Medium class (PropertyStatsService) ~0.66s ~2,610

Key observations:

  • First request penalty (~1.5s) only for import identifiers that trigger the typeDefinition fallback
  • Cross-file references work correctly: 3 refs in 2 files, 6 refs in 3 files (verified against real NestJS monorepo)
  • Token efficiency: definition results ~270-290 tokens, references scale with usage count
  • No LSP startup delay: bridges are lazily created and pooled (max 8 concurrent)

🀝 Contributing

Contributions welcome! This is a community plugin β€” PRs for new languages, better LSP fallbacks, or caching improvements are appreciated.

  1. Fork the repo
  2. Create a feature branch
  3. Add tests for your changes
  4. Open a PR

πŸ“„ License

MIT β€” use it however you like.

πŸ™ Credits

  • Hermes Agent by Nous Research β€” the plugin system this builds on
  • tree-sitter β€” incremental parsing system
  • ast-grep β€” pattern-based code search and replacement
  • pyright β€” Python LSP server (fallback)
  • typescript-language-server β€” TypeScript/JavaScript LSP server
  • tsserver β€” TypeScript language service (used by typescript-language-server)

About

🧠 AST-aware code intelligence plugin for Hermes Agent β€” tree-sitter + ast-grep + LSP. Symbol extraction, structural search, safe refactoring, go-to-definition, find-all-references.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages