Merge remote-tracking branch 'origin/main' into disable-usage-reporting-env-var

Conflicts:
  CHANGELOG.md
This commit is contained in:
Dominik Jain authored and Dominik Jain committed 2026-04-12 15:13:28 +02:00
commit a96640aebf
17 files changed
+115 -154

No files matched your search

+12 -1
View File
@@ -5,11 +5,22 @@ Status of the `main` branch. Changes prior to the next official version change w
* General:
- Support environment variable `SERENA_USAGE_REPORTING` (set to `false` to disable usage reporting)
# 1.1.1
* General:
- Enable cert verification for HTTPS request to oraios-software.de #1320
* JetBrains:
- `JetBrainsRenameTool` can now also rename occurrences in comments and text.
* Language Servers:
- Fix Dart LSP returning only symbol name as body instead of full method body.
# 1.1.0
* General:
- Add `serena init` and `serena setup` commands
- **Major**: Add commands for hooks and documentation of recommended setup. Consider setting up the [recommended hooks](https://oraios.github.io/serena/02-usage/030_clients.html) !
- Add `serena init` and `serena setup` commands
- Rework installation instructions, switching to releases on pypi for distribution. Please update your mcp startup commands!
- Add minimal usage data collection on startup (only Serena version, language backend, OS, dashboard enabled status; no personally identifiable information)
- Fix: git commit id in Serena version strings was incorrect
+10 -3
View File
@@ -7,10 +7,17 @@
Serena is the IDE for your coding agent.
</h3>
<div align="center">
<a href="https://discord.com/invite/cVUNQmnV4r"><img src="https://img.shields.io/badge/discord-join-5865F2?style=flat-square&labelColor=0a0e14&logo=discord&logoColor=5865F2" alt="discord"></a>
<a href="https://github.com/oraios/serena/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-b0e8ff?style=flat-square&labelColor=0a0e14" alt="license"></a>
</div>
<br>
* Serena provides essential **semantic code retrieval, editing and refactoring tools** that are akin to an IDE's capabilities,
operating at the symbol level and exploiting relational structure.
* It integrates with any client/LLM via the model context protocol (**MCP**).
Serena's **agent-first tool design** involves robust high-level abstractions, distinguishing it from
approaches that rely on low-level concepts like line numbers or primitive search patterns.
@@ -19,7 +26,7 @@ more complex codebases.
> [!IMPORTANT]
> Do not install Serena via an MCP or plugin marketplace! They contain outdated and suboptimal installation commands.
> Instead, follow our [Quick Start](quick-start) instructions.
> Instead, follow our [Quick Start](#quick-start) instructions.
## How Serena Works
@@ -38,7 +45,7 @@ To connect the Serena MCP server to your client, you either
* provide the client with a launch command that allows it to start the MCP server, or
* start the Serena MCP server yourself in HTTP mode and provide the client with the URL.
See the [Quick Start](quick-start) section below for information on how to get started.
See the [Quick Start](#quick-start) section below for information on how to get started.
## Programming Language Support & Semantic Analysis Capabilities
+6 -17
View File
@@ -40,10 +40,15 @@ A key mechanism for this is to use the appropriate [context](#contexts) when sta
(clients-common-pitfalls)=
### Common Pitfalls
**Discoverability of the `serena`**.
**Discoverability of the `serena` command**.
Your client may not find the `serena` CLI command, even if it is on your system PATH.
In this case, a workaround is to provide the full path to the `serena` executable.
**Serena's tools not being used**.
With some clients, you may experience that Serena's tools are not being used.
This is mainly due to problems in the client itself (like a poorly implemented tool discovery). To counteract this,
Serena comes with a set of commands that can be used in _hooks_. See the sections on hooks for Claude Code and VSCode below.
**Environment Variables**.
Some language servers may require additional environment variables to be set (e.g. F# on macOS with Homebrew),
which you may need to explicitly add to the MCP server configuration.
@@ -117,22 +122,6 @@ Confirm that Claude Code is connected to Serena by running the `/mcp` command an
If Serena fails to start fast enough, you should set `MCP_TIMEOUT` to a sufficiently high value
(e.g. by adding `export MCP_TIMEOUT=60000` to your shell profile)
**Maximum Token Efficiency.** To maximize token efficiency, you may want to use Claude Code's
*on-demand tool loading* feature, which is supported since at least v2.0.74 of Claude Code.
This feature avoids sending all tool descriptions to Claude upon startup, thus saving tokens.
Instead, Claude will search for tools as needed (but there are no guarantees that it will
search optimally, of course).
To enable this feature, set the environment variable `ENABLE_TOOL_SEARCH=true`.
Depending on your shell, you can also set this on a per-session basis, e.g. using
```shell
ENABLE_TOOL_SEARCH=true claude
```
in bash/zsh, or using
```shell
set ENABLE_TOOL_SEARCH=true && claude
```
in Windows CMD to launch Claude Code.
**Hooks.**
Due to recent changes (especially dynamic tool loading) in Claude Code, the agent will often fail to make proper use
of Serena's tools, either by failing to load them in the beginning or by forgetting the instructions in a long session
-90
View File
@@ -1,90 +0,0 @@
# Lessons Learned
In this document we briefly collect what we have learned while developing and using Serena,
what works well and what doesn't.
## What Worked
### Separate Tool Logic From MCP Implementation
MCP is just another protocol, one should let the details of it creep into the application logic.
The official docs suggest using function annotations to define tools and prompts. While that may be
useful for small projects to get going fast, it is not wise for more serious projects. In Serena,
all tools are defined independently and then converted to instances of `MCPTool` using our `make_tool`
function.
### Autogenerated PromptFactory
Prompt templates are central for most LLM applications, so one needs good representations of them in the code,
while at the same time they often need to be customizable and exposed to users. In Serena we address these conflicting
needs by defining prompt templates (in jinja format) in separate yamls that users can easily modify and by autogenerated
a `PromptFactory` class with meaningful method and parameter names from these yamls. The latter is committed to our code.
We separated out the generation logic into the [interprompt](/src/interprompt/README.md) subpackage that can be used as a library.
### Tempfiles and Snapshots for Testing of Editing Tools
We test most aspects of Serena by having a small "project" for each supported language in `tests/resources`.
For the editing tools, which would change the code in these projects, we use tempfiles to copy over the code.
The pretty awesome [syrupy](https://github.com/syrupy-project/syrupy) pytest plugin helped in developing
snapshot tests.
### Dashboard and GUI for Logging
It is very useful to know what the MCP Server is doing. We collect and display logs in a GUI or a web dashboard,
which helps a lot in seeing what's going on and in identifying any issues.
### Unrestricted Bash Tool
We know it's not particularly safe to permit unlimited shell commands outside a sandbox, but we did quite some
evaluations and so far... nothing bad has happened. Seems like the current versions of the AI overlords rarely want to execute `sudo rm - rf /`.
Still, we are working on a safer approach as well as better integration with sandboxing.
### Multilspy
The [multilspy](https://github.com/microsoft/multilspy/) project helped us a lot in getting started and stands at the core of Serena.
Many more well known python implementations of language servers were subpar in code quality and design (for example, missing types).
### Developing Serena with Serena
We clearly notice that the better the tool gets, the easier it is to make it even better
## Prompting
### Shouting and Emotive Language May Be Needed
When developing the `ReplaceRegexTool` we were initially not able to make Claude 4 (in Claude Desktop) use wildcards to save on output tokens. Neither
examples nor explicit instructions helped. It was only after adding
```
IMPORTANT: REMEMBER TO USE WILDCARDS WHEN APPROPRIATE! I WILL BE VERY UNHAPPY IF YOU WRITE LONG REGEXES WITHOUT USING WILDCARDS INSTEAD!
```
to the initial instructions and to the tool description that Claude finally started following the instructions.
## What Didn't Work
### Lifespan Handling by MCP Clients
The MCP technology is clearly very green. Even though there is a lifespan context in the MCP SDK,
many clients, including Claude Desktop, fail to properly clean up, leaving zombie processes behind.
We mitigate this through the GUI window and the dashboard, so the user sees whether Serena is running
and can terminate it there.
### Trusting Asyncio
Running multiple asyncio apps led to non-deterministic
event loop contamination and deadlocks, which were very hard to debug
and understand. We solved this with a large hammer, by putting all asyncio apps into a separate
process. It made the code much more complex and slightly enhanced RAM requirements, but it seems
like that was the only way to reliably overcome asyncio deadlock issues.
### Cross-OS Tkinter GUI
Different OS have different limitations when it comes to starting a window or dealing with Tkinter
installations. This was so messy to get right that we pivoted to a web-dashboard instead
### Editing Based on Line Numbers
Not only are LLMs notoriously bad in counting, but also the line numbers change after edit operations,
and LLMs are also often too dumb to understand that they should update the line numbers information they had
received before. We pivoted to string-matching and symbol-name based editing.
-29
View File
@@ -1,29 +0,0 @@
# MCP Installation instructions
This document is mainly used as instructions for AI-assistants like Cline and others that
try to do an automatic install based on freeform instructions.
0. Make sure `uv` is installed. If not, install it using either `curl -LsSf https://astral.sh/uv/install.sh | sh` (macOS, Linux) or
`powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"` (Windows). Find the path to the `uv` executable,
you'll need it later.
1. Clone the repo with `git clone git@github.com:oraios/serena.git` and change into its dir (e.g., `cd serena`)
2. Check if `serena_config.yml` exists. If not, create it with `cp serena_config.template.yml serena_config.yml`. Read the instructions in the config.
3. In the config, check if the path to your project was added. If not, add it to the `projects` section
4. In your project, create a `.serena` if needed and check whether `project.yml` exists there.
5. If no `project.yml` was found, create it using `cp /path/to/serena/myproject.template.yml /path/to/your/project/.serena/project.yml`
6. Read the instructions in `project.yml`. Make sure the `project.yml` has the correct project language configured.
Remove the project_root entry there.
7. Finally, add the Serena MCP server config like this:
```json
{
"mcpServers": {
...
"serena": {
"command": "/abs/path/to/uv",
"args": ["run", "--directory", "/abs/path/to/serena", "serena-mcp-server", "/path/to/your/project/.serena/project.yml"]
}
}
}
```
+2 -2
View File
@@ -8,7 +8,7 @@
<li><strong>Extended symbol information:</strong> The `find_symbol` and `find_referencing_symbols` tools (and their JetBrains variants)
now can return more information about the symbol (specifically, docstrings and signatures).
</li>
<li><strong>Type hierarchy tool:</strong> A new tool &ndash; exclusive to <a href="https://oraios.github.io/serena/02-usage/025_jetbrains_plugin.html">JetBrains mode</a> &ndash;
<li><strong>Type hierarchy tool:</strong> A new tool &ndash; exclusive to <a target="_blank" href="https://oraios.github.io/serena/02-usage/025_jetbrains_plugin.html">JetBrains mode</a> &ndash;
that can fetch a symbol's hierarchy, i.e. superclasses and subclasses, which is very useful in many situations.
</li>
<li><strong>Compact overviews:</strong> The `get_symbols_overview` tools now return a much more compact
@@ -17,6 +17,6 @@
</li>
</ul>
<p>
For more detailed information, see our <a href="https://github.com/oraios/serena/blob/main/CHANGELOG.md">changelog</a>.
For more detailed information, see our <a target="_blank" href="https://github.com/oraios/serena/blob/main/CHANGELOG.md">changelog</a>.
</p>
</div>
+1 -1
View File
@@ -7,6 +7,6 @@
into topics and sharing them across projects.
</p>
<p>
For more detailed information, see the <a href="https://oraios.github.io/serena/02-usage/045_memories.html">documentation</a>.
For more detailed information, see the <a target="_blank" href="https://oraios.github.io/serena/02-usage/045_memories.html">documentation</a>.
</p>
</div>
+1 -1
View File
@@ -8,6 +8,6 @@
to other projects.
</p>
<p>
Find out more about this feature in our <a href="https://oraios.github.io/serena/02-usage/040_workflow.html#reading-from-external-projects">documentation</a>.
Find out more about this feature in our <a target="_blank" href="https://oraios.github.io/serena/02-usage/040_workflow.html#reading-from-external-projects">documentation</a>.
</p>
</div>
+3 -3
View File
@@ -4,19 +4,19 @@
<p>
<b>Installation.</b> Serena has matured and we are switching to a PyPI-based release and installation mechanism.
The recommended uv-tool-based installation decreases startup times and facilitates CLI usage.
See <a href="https://oraios.github.io/serena/02-usage/010_installation.html">updated installation instructions</a>
See <a target="_blank" href="https://oraios.github.io/serena/02-usage/010_installation.html">updated installation instructions</a>
for more details.
</p>
<p>
<b>Improving Tool Usage via Hooks.</b> To address issues with agents not using Serena's tools (agent drift), we now provide the `serena-hooks` commands and a recommended
setup for Claude Code and VSCode.
Please read the <a href="https://oraios.github.io/serena/02-usage/030_clients.html">updated documentation</a> for more details.
Please read the <a target="_blank" href="https://oraios.github.io/serena/02-usage/030_clients.html">updated documentation</a> for more details.
We <i>strongly recommend using the hooks</i>, since recent updates in Claude Code and VSCode resulted in
reduced performance, which our hook commands compensate for.
</p>
<p>
<b>Community.</b> We opened a <a href="https://discord.com/invite/cVUNQmnV4r">Discord server</a> for our community.
<b>Community.</b> We opened a <a target="_blank" href="https://discord.com/invite/cVUNQmnV4r">Discord server</a> for our community.
</p>
</div>
+1 -1
View File
@@ -4,7 +4,7 @@ requires = ["hatchling"]
[project]
name = "serena-agent"
version = "1.1.0"
version = "1.1.1"
description = ""
authors = [{ name = "Oraios AI", email = "info@oraios-ai.de" }]
readme = "README.md"
+1
View File
@@ -44,6 +44,7 @@ def bump_version(major: bool, minor: bool, patch: bool, target_version: str | No
if dry_run:
click.echo(f"Dry run complete. Version would be bumped to {new_version}")
else:
os.system("uv lock")
click.echo(f"Bumped version to {new_version}")
os.system("git add -u")
os.system(f'git commit -m "Release v{new_version}"')
+1 -1
View File
@@ -1,4 +1,4 @@
__version__ = "1.1.0"
__version__ = "1.1.1"
import logging
+1 -1
View File
@@ -419,7 +419,7 @@ class SerenaAgent:
"backend": self._language_backend.value,
}
try:
requests.get("https://www.oraios-software.de/serena_usage.php", params=params, timeout=1, verify=False)
requests.get("https://oraios-software.de/serena_usage.php", params=params, timeout=1)
except Exception as e:
log.debug(f"Failed to send usage info: {e}")
+19 -2
View File
@@ -512,16 +512,33 @@ class JetBrainsRenameTool(Tool, ToolMarkerSymbolicEdit, ToolMarkerOptional):
Renames a symbol, file or directory throughout the codebase using the JetBrains backend.
"""
def apply(self, relative_path: str, new_name: str, name_path: str | None = None) -> str:
def apply(
self,
relative_path: str,
new_name: str,
name_path: str | None = None,
rename_in_comments: bool = False,
rename_in_text_occurrences: bool = False,
) -> str:
"""
Renames a symbol, file or directory throughout the codebase.
Note: renaming in comments/text is on a best-effort basis by the IDE; if the symbol name is non-unique, further
verification is recommended.
:param relative_path: if `name_path` is passed, the relative path of the file containing the symbol.
Otherwise, the path to the directory or file to rename.
:param new_name: the new name
:param name_path: the name path of the symbol to rename or None if renaming a file or directory.
:param rename_in_comments: whether to also rename occurrences in comments. Default True.
:param rename_in_text_occurrences: whether to also rename occurrences in text. Default True.
:return: a status message
"""
code_editor = JetBrainsCodeEditor(self.project)
result = code_editor.rename_symbol(name_path=name_path, relative_path=relative_path, new_name=new_name)
result = code_editor.rename_symbol(
name_path=name_path,
relative_path=relative_path,
new_name=new_name,
rename_in_comments=rename_in_comments,
rename_in_text_occurrences=rename_in_text_occurrences,
)
return self._to_json(result)
@@ -123,7 +123,13 @@ class DartLanguageServer(SolidLanguageServer):
"""
root_uri = pathlib.Path(repository_absolute_path).as_uri()
initialize_params = {
"capabilities": {},
"capabilities": {
"textDocument": {
"documentSymbol": {
"hierarchicalDocumentSymbolSupport": True,
}
}
},
"initializationOptions": {
"onlyAnalyzeProjectsWithOpenFiles": False,
"closingLabels": False,
+49
View File
@@ -375,3 +375,52 @@ class TestDartLanguageServer:
f"Found malformed symbols: {[format_symbol_for_assert(sym) for sym in malformed_symbols]}",
pytrace=False,
)
@pytest.mark.parametrize("language_server", [Language.DART], indirect=True)
def test_symbol_body_contains_full_method(self, language_server: SolidLanguageServer) -> None:
"""Test that document symbols return the full method body range, not just the identifier.
Regression test: when hierarchicalDocumentSymbolSupport was not declared in client
capabilities, the Dart LSP returned SymbolInformation[] (flat format) where
location.range only covered the identifier name (single line), causing find_symbol
with include_body=True to return just the symbol name instead of its implementation.
"""
file_path = os.path.join("lib", "main.dart")
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
symbol_list = symbols[0] if symbols and isinstance(symbols[0], list) else symbols
# Find the 'add' method — defined across multiple lines in main.dart:
# int add(int a, int b) {
# final result = a + b;
# _history.add('$a + $b = $result');
# return result;
# }
add_symbol = None
for sym in symbol_list:
if sym.get("name") == "add":
add_symbol = sym
break
if sym.get("name") == "Calculator" and "children" in sym:
for child in sym["children"]:
if child.get("name") == "add":
add_symbol = child
break
if add_symbol:
break
assert add_symbol is not None, "Could not find 'add' method symbol in main.dart"
# The body range must span multiple lines (not just the identifier line).
# With hierarchicalDocumentSymbolSupport declared, the Dart LSP returns
# DocumentSymbol[] where range covers the full method body.
body_start = add_symbol["location"]["range"]["start"]["line"]
body_end = add_symbol["location"]["range"]["end"]["line"]
assert body_end > body_start, (
f"Expected multi-line body range for 'add' method, got start={body_start}, end={body_end}. "
f"This likely means hierarchicalDocumentSymbolSupport is not declared in client capabilities."
)
# The body text must contain the method implementation, not just the name.
if add_symbol.get("body"):
body_text = add_symbol["body"].get_text()
assert "return result" in body_text, f"Expected method body to contain implementation, got: {body_text!r}"
Generated
+1 -1
View File
@@ -2911,7 +2911,7 @@ wheels = [
[[package]]
name = "serena-agent"
version = "1.1.0"
version = "1.1.1"
source = { editable = "." }
dependencies = [
{ name = "anthropic" },