Skip to content

TokToken vs Serena: Which Tool Fixes Claude Code Navigation?

Problem

I was working on a large C codebase with Claude Code when I hit a wall. Claude kept losing context, inventing function names that didn’t exist, and asking me to show it files I had already provided. The context window inefficiency was wasting my time.

I saw a Reddit post from someone who pair-programmed ~22K lines of C with Claude Opus to solve this exact problem. They built a tool called TokToken. But then someone in the comments asked:

“Isn’t this what plug-ins like Serena are for?”

I realized I had two options: TokToken (tokenization-based) or Serena (LSP-based). I needed to understand which approach would actually solve my problem.

What I tried first

I started by understanding what both tools actually do:

┌─────────────────────────────────────────────────────────────────┐
│ Claude Code Context Problem │
├─────────────────────────────────────────────────────────────────┤
│ 22K lines of code → Cannot fit in context window → Problems: │
│ - Hallucinated references (invented function names) │
│ - Lost context (asking for files repeatedly) │
│ - Incomplete understanding (missed relationships) │
└─────────────────────────────────────────────────────────────────┘
┌───────────────┴───────────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ TokToken │ │ Serena │
│ (Tokenization) │ │ (LSP-based) │
└─────────────────┘ └─────────────────┘

Understanding TokToken’s approach

TokToken solves context window issues through intelligent token management. Here’s the core concept:

┌─────────────────────────────────────────────────────────────┐
│ TokToken Strategy │
├─────────────────────────────────────────────────────────────┤
│ 1. Count tokens per file │
│ 2. Score files by relevance to query │
│ 3. Select files that maximize relevance per token │
│ 4. Stay within token budget │
└─────────────────────────────────────────────────────────────┘
Example: 200K token budget
┌──────────────┬────────┬──────────┬─────────────────┐
│ File │ Tokens │ Relevance│ Score/Tokens │
├──────────────┼────────┼──────────┼─────────────────┤
│ main.c │ 5000 │ 0.9 │ 0.00018 │
│ utils.c │ 3000 │ 0.7 │ 0.00023 <- │
│ parser.c │ 8000 │ 0.6 │ 0.000075 │
│ network.c │ 12000 │ 0.4 │ 0.000033 │
└──────────────┴────────┴──────────┴─────────────────┘
Select utils.c first (best bang for buck)

The approach is conceptually simple:

toktoken_selector.py
class TokenManager:
def __init__(self, max_tokens: int = 200000):
self.max_tokens = max_tokens
def select_files(self, query: str, codebase: dict) -> list[str]:
"""Select optimal files within token budget."""
scored_files = []
for path, content in codebase.items():
score = self.calculate_relevance(query, content)
tokens = self.count_tokens(content)
scored_files.append((path, score, tokens))
# Greedy selection by relevance per token
selected = []
total_tokens = 0
for path, score, tokens in sorted(
scored_files,
key=lambda x: x[1]/x[2],
reverse=True
):
if total_tokens + tokens <= self.max_tokens:
selected.append(path)
total_tokens += tokens
return selected

What I like about TokToken:

  • Works with any language (no LSP dependency)
  • Simple to understand and debug
  • Low setup overhead
  • Transparent about what it’s doing

What concerns me:

  • No semantic understanding of code
  • Cannot resolve complex references
  • Pattern matching over true comprehension

Understanding Serena’s approach

Serena leverages the Language Server Protocol for deep semantic analysis:

┌─────────────────────────────────────────────────────────────┐
│ Serena Strategy │
├─────────────────────────────────────────────────────────────┤
│ 1. Connect to LSP server for the language │
│ 2. Use go-to-definition for accurate navigation │
│ 3. Find references across files │
│ 4. Leverage IDE-like intelligence │
└─────────────────────────────────────────────────────────────┘
Example: Finding a function definition
┌──────────────┐ LSP Request ┌──────────────┐
│ main.c:42 │ ─────────────────▶ │ LSP Server │
│ func_call() │ │ (clangd) │
└──────────────┘ ◀───────────────── └──────────────┘
Definition at
utils.c:15

The conceptual implementation:

serena_navigator.py
class SerenaLSPNavigator:
def __init__(self, language: str):
self.lsp_client = self.connect_lsp(language)
def find_definition(self, symbol: str, file_path: str, line: int):
"""Use LSP to find definition location."""
response = self.lsp_client.request(
"textDocument/definition",
{
"textDocument": {"uri": f"file://{file_path}"},
"position": {"line": line, "character": 0}
}
)
return response["uri"], response["range"]["start"]
def get_code_context(self, symbol: str):
"""Retrieve relevant code context semantically."""
definition = self.find_definition(symbol)
references = self.lsp_client.request(
"textDocument/references",
{...}
)
return self.compile_context(definition, references)

What I like about Serena:

  • Deep semantic understanding
  • Accurate reference resolution
  • Language-specific intelligence
  • Industry-standard protocol

What concerns me:

  • Requires LSP server installation for each language
  • Higher setup complexity
  • May not work with all languages
  • Dependency on external tooling

Side-by-side comparison

┌────────────────────┬─────────────────────┬─────────────────────┐
│ Feature │ TokToken │ Serena (LSP) │
├────────────────────┼─────────────────────┼─────────────────────┤
│ Setup Complexity │ Low │ Medium-High │
│ Language Support │ Universal │ Per-language server │
│ Semantic Analysis │ No │ Yes │
│ Reference Resolution│ Pattern-based │ LSP-powered │
│ Token Optimization │ Primary focus │ Indirect │
│ IDE Integration │ Standalone │ Inherits LSP │
│ Debuggability │ Transparent │ LSP-dependent │
│ Maintenance │ Self-maintained │ Community LSPs │
└────────────────────┴─────────────────────┴─────────────────────┘

MCP Configuration for both

I can configure both tools in my Claude Code settings:

claude_desktop_config.json
{
"mcpServers": {
"toktoken": {
"command": "node",
"args": ["path/to/toktoken-server/build/index.js"],
"env": {}
},
"serena": {
"command": "python",
"args": ["-m", "serena.server"],
"env": {
"SERENA_LSP_ENABLED": "true"
}
}
}
}

When I would use each

Use TokToken when:

  • Working with multiple languages in one project
  • Need quick setup without LSP dependencies
  • Want transparent token budgeting
  • Debugging context window issues directly

Use Serena when:

  • Working deeply in one language (Python, TypeScript, etc.)
  • Need accurate go-to-definition
  • Want IDE-like semantic navigation
  • LSP servers are already available for your stack

Use both together:

┌─────────────────────────────────────────────────────────────┐
│ Combined Workflow │
├─────────────────────────────────────────────────────────────┤
│ 1. Serena: Find relevant symbols via LSP navigation │
│ 2. TokToken: Budget tokens for selected files │
│ 3. Result: Semantic accuracy + Token efficiency │
└─────────────────────────────────────────────────────────────┘

Why context window inefficiency matters

Claude Code has a finite context window (200K tokens for Claude 3.5 Sonnet, 200K for Claude 3 Opus). When working with large codebases:

  1. Hallucination risk: Claude invents functions that seem plausible but don’t exist
  2. Repeated requests: Claude asks for files it already saw earlier in the conversation
  3. Lost relationships: Cross-file dependencies get dropped from context
  4. Incomplete analysis: Architectural decisions suffer from partial context

What is LSP (Language Server Protocol)

LSP is a protocol used between an editor and a language server that provides language features like auto complete, go to definition, find all references, etc. It’s what powers VS Code’s IntelliSense.

Editor (Claude Code) LSP Server (clangd/pyright/etc)
│ │
│ textDocument/definition
│ ──────────────────────▶│
│ │
│ ◀──────────────────────│
│ Definition location │

Why the Reddit discussion matters

The original poster built TokToken specifically because they faced this problem with 22K lines of C code. The fact that someone immediately suggested Serena as an alternative shows this is a common pain point with multiple valid solutions.

Summary

I compared TokToken and Serena for solving Claude Code’s context window inefficiency. TokToken optimizes token usage through smart file selection and works with any language. Serena leverages LSP for semantic code understanding but requires language-specific setup.

The tools aren’t mutually exclusive. I can use Serena for accurate code navigation and reference resolution, then use TokToken to manage my token budget across the selected files.

For my C project, I’ll start with TokToken for its simplicity and universal compatibility. If I need deeper semantic understanding, I’ll add Serena with clangd as the LSP server.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments