diff --git a/.serena/project.yml b/.serena/project.yml index e97251e5..a15a5409 100644 --- a/.serena/project.yml +++ b/.serena/project.yml @@ -1,4 +1,66 @@ -# language of the project (csharp, python, rust, java, typescript, javascript, go, or ruby) -language: python -# list of directories to ignore: either names (e.g. "temp") or relative paths (e.g. "build/foo") -ignore_all_files_in_gitignore: True +# language of the project (csharp, python, rust, java, typescript, javascript, go, cpp, or ruby) +# Special requirements: +# * csharp: Requires the presence of a .sln file in the project folder. +language: typescript + +# whether to use the project's gitignore file to ignore files +# Added on 2025-04-07 +ignore_all_files_in_gitignore: true +# list of additional paths to ignore +# same syntax as gitignore, so you can use * and ** +# Was previously called `ignored_dirs`, please update your config if you are using that. +# Added (renamed)on 2025-04-07 +ignored_paths: [] + +# whether the project is in read-only mode +# If set to true, all editing tools will be disabled and attempts to use them will result in an error +# Added on 2025-04-18 +read_only: false + + +# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details. +# Below is the complete list of tools for convenience. +# To make sure you have the latest list of tools, and to view their descriptions, +# execute `uv run scripts/print_tool_overview.py`. +# +# * `activate_project`: Activates a project by name. +# * `check_onboarding_performed`: Checks whether project onboarding was already performed. +# * `create_text_file`: Creates/overwrites a file in the project directory. +# * `delete_lines`: Deletes a range of lines within a file. +# * `delete_memory`: Deletes a memory from Serena's project-specific memory store. +# * `execute_shell_command`: Executes a shell command. +# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced. +# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type). +# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). +# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. +# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file or directory. +# * `initial_instructions`: Gets the initial instructions for the current project. +# Should only be used in settings where the system prompt cannot be set, +# e.g. in clients you have no control over, like Claude Desktop. +# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol. +# * `insert_at_line`: Inserts content at a given line in a file. +# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol. +# * `list_dir`: Lists files and directories in the given directory (optionally with recursion). +# * `list_memories`: Lists memories in Serena's project-specific memory store. +# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building). +# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context). +# * `read_file`: Reads a file within the project directory. +# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store. +# * `remove_project`: Removes a project from the Serena configuration. +# * `replace_lines`: Replaces a range of lines within a file with new content. +# * `replace_symbol_body`: Replaces the full definition of a symbol. +# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen. +# * `search_for_pattern`: Performs a search for a pattern in the project. +# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase. +# * `switch_modes`: Activates modes by providing a list of their names +# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information. +# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task. +# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed. +# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store. +excluded_tools: [] + +# initial prompt for the project. It will always be given to the LLM upon activating the project +# (contrary to the memories, which are loaded on demand). +initial_prompt: "" + +project_name: "serena" diff --git a/CHANGELOG.md b/CHANGELOG.md index 39f4cfce..573bd6d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,24 @@ # Latest -Changes prior to the next official version change will appear here. +Status of the main branch. Changes prior to the next official version change will appear here. + +## Highlights + +* **Better multi-project support and zero-config setup**: We significantly simplified the config setup, you no longer need to manually + create `project.yaml` for each project. Project activation is now always available. + Any project can now be activated by just asking the LLM to do so and passing the path to a repo. +* Dashboard as web app and possibility to shut down Serena during +* Initial prompt for project supported (has to be added manually for the moment) +* Massive performance improvement of pattern search tool # 2025-05-24 +## Highlights + Important new feature: configurability of mode and context, allowing better integration in a variety of clients. +See corresponding section in readme - Serena can now be integrated in IDE assistants in a more productive way. + +You can now also do things like switching to one-shot planning mode, ask to plan something (which will create a memory), +then switch to interactive editing mode in the next conversation and work through the plan read from the memory. Also some improvements to prompts. diff --git a/README.md b/README.md index 0274cebc..c77e2766 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,9 @@ implementation. - [What Can I Use Serena For?](#what-can-i-use-serena-for) - [Free Coding Agents with Serena](#free-coding-agents-with-serena) - [Quick Start](#quick-start) - * [Setup and Configuration](#setup-and-configuration) + * [Setup](#setup) + * [Configuration](#configuration) + * [Project Activation](#project-activation) * [MCP Server (Claude Desktop)](#mcp-server-claude-desktop) + [Troubleshooting](#troubleshooting) * [Claude Code](#claude-code) @@ -151,23 +153,31 @@ Serena can be used in various ways, below you will find instructions for selecte - If you prefer using Serena through a CLI, you can use [goose](#goose). There again almost any model is possible. - If you want to use Serena integrated in your IDE, see the section on [other MCP clients](#other-mcp-clients---cline-roo-code-cursor-windsurf-etc). -### Setup and Configuration +### Setup 1. Install `uv` (instructions [here](https://docs.astral.sh/uv/getting-started/installation/)) -2. Clone the repository to `/path/to/serena`. -3. Copy `serena_config.template.yml` to `serena_config.yml` and adjust settings. +2. Clone the repository. +3. Copy `serena_config.template.yml` to `serena_config.yml` ```shell cp serena_config.template.yml serena_config.yml ``` -4. Copy `project.template.yml` to `project.yml` and adjust the settings specific to your project - (add one such file for each project you want Serena to work on). We recommend that you copy - it to the `.serena` directory of your project, e.g., - ```shell - mkdir -p /myproject/.serena - cp project.template.yml /myproject/.serena/project.yml - ``` -6. If you want Serena to dynamically switch between projects, add the list of all project files - created in the previous step to the `projects` list in `serena_config.yml`. + +You can now add Serena to your MCP client as described below for various clients and +[activate your first project]() + +### Configuration + +Serena's behavior (like available projects, active tools and prompts) is configured in four places: + +1. The `serena_config.yml` for general settings that apply to all clients and projects +2. In the arguments passed to the `serena-mcp-server` in your client's config (see below), + which will apply to all sessions started by the respective client. In particular, the [context](#contexts) parameter + should be set appropriately for Serena to be best adjusted to existing tools and capabilities of your client. + See for a detailed explanation. +3. In the `.serena/project.yml` file within your project. This will hold project-level configuration that is used whenever + that project is activated. +4. Through the currently active set of [modes](#modes). + > ⚠️ **Note:** Serena is under active development. We are continuously adding features, improving stability and the UX. > As a result, configuration may change in a breaking manner. If you have an invalid configuration, @@ -178,32 +188,49 @@ Serena can be used in various ways, below you will find instructions for selecte After the initial setup, continue with one of the sections below, depending on how you want to use Serena. +You can just ask the LLM to show you the config of your session, Serena has a tool for it. + +### Project Activation + +The recommended way is to just ask the LLM to activate a project by providing it an absolute path to, or, +in case the project was activated in the past, by it's name. The default project name is the directory name. + +All projects that have been activated will be automatically added to your `serena_config.yml`, and for each +project, the file `.serena/project.yml` will be generated. You can adjust the latter, e.g., by changing the name +(which you refer to during the activation) or other options. Make sure to not have two different projects with the +same name. + +If you are mostly working with the same project, you can also configure to always activate a project at startup +by passing `--project ` to the `serena-mcp-server` command in your client's MCP config. + ### MCP Server (Claude Desktop) -1. Create a configuration file for your project, say `myproject.yml` based on the template in [myproject.template.yml](myproject.template.yml). -2. Configure the MCP server in your client. - For [Claude Desktop](https://claude.ai/download) (available for Windows and macOS), go to File / Settings / Developer / MCP Servers / Edit Config, - which will let you open the JSON file `claude_desktop_config.json`. Add the following (with adjusted paths) to enable Serena: +Configure the MCP server in your client. +For [Claude Desktop](https://claude.ai/download) (available for Windows and macOS), go to File / Settings / Developer / MCP Servers / Edit Config, +which will let you open the JSON file `claude_desktop_config.json`. Add the following (with adjusted paths) to enable Serena: - ```json - { - "mcpServers": { - "serena": { - "command": "/abs/path/to/uv", - "args": ["run", "--directory", "/abs/path/to/serena", "serena-mcp-server", "--project", "/abs/path/to/project"] - } - } - } - ``` - - If you are using paths containing backslashes for paths on Windows - (note that you can also just use forward slashes), be sure to escape them correctly (`\\`). +```json +{ + "mcpServers": { + "serena": { + "command": "/abs/path/to/uv", + "args": ["run", "--directory", "/abs/path/to/serena", "serena-mcp-server"] + } + } +} +``` - ℹ️ Passing the project path is optional if you have set `enable_project_activation` in your configuration, as this setting will allow you to simply instruct Claude to activate the project you want to work on. +If you are using paths containing backslashes for paths on Windows +(note that you can also just use forward slashes), be sure to escape them correctly (`\\`). - ℹ️ If you want to configure Serena to operate in a particular way, specializing it for particular types of tasks, you can make use of [modes and contexts](#modes-and-contexts) and specify additional parameters accordingly. +That's it! Save the config and then restart Claude Desktop. You are ready for activating your first project + +ℹ️ You can further customize the run command, see + +```shell +uv run serena-mcp-server --help +``` -That's it! Save the config and then restart Claude Desktop. #### Troubleshooting @@ -211,28 +238,31 @@ Some client/OS/setup configurations were reported to cause issues when using Ser If you experience such problems, you can start Serena in `sse` mode by running, e.g., ```shell -uv run --directory /path/to/serena serena-mcp-server --transport sse --port 9121 --project /path/to/project +uv run serena-mcp-server --transport sse --port 9121 ``` -(the `--project` option is optional). Then configure your client to connect to `http://localhost:9121`. + +Then configure your client to connect to `http://localhost:9121`. Note: on Windows and macOS there are official Claude Desktop applications by Anthropic, for Linux there is an [open-source community version](https://github.com/aaddrick/claude-desktop-debian). ⚠️ Be sure to fully quit the Claude Desktop application, as closing Claude will just minimize it to the system tray – at least on Windows. +⚠️ Some clients, currently including Claude Desktop, may leave behind zombie processes. You will have to find and terminate them manually then. + With Serena, you can activate the [dashboard](#serenas-logs-the-dashboard-and-gui-tool) to prevent unnoted processes and also use the dashboard + for shutting down Serena. + After restarting, you should see Serena's tools in your chat interface (notice the small hammer icon). ⚠️ Tool Names: Claude Desktop (and most MCP Clients) don't resolve the name of the server. So you shouldn't say something like "use Serena's tools". Instead, you can instruct the LLM to use symbolic tools or to -use a particular tool by referring to its name. Moreover, if you use multiple MCP Servers, you might get -**tool name collisions** which lead to undefined behavior. For example, Serena is currently incompatible with the -[Filesystem MCP Server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) due to tool name -collisions. +use a particular tool by referring to its name. Moreover, in some clients, if you use multiple MCP Servers, you might get +**tool name collisions** which lead to undefined behavior. -ℹ️ Note that MCP servers which use stdio as a protocol are somewhat unusual as far as client/server architectures go, as the server +ℹ️ Note that MCP servers which use stdio as a protocol are somewhat unusual as far as client/server architectures go, as in the the server necessarily has to be started by the client in order for communication to take place via the server's standard input/output stream. In other words, you do not need to start the server yourself. The client application (e.g. Claude Desktop) takes care of this and -therefore needs to be configured with a launch command. +therefore needs to be configured with a launch command. In SSE transport you control the lifetime of the server yourself. For more information on MCP servers with Claude Desktop, see [the official quick start guide](https://modelcontextprotocol.io/quickstart/user). @@ -243,7 +273,7 @@ several examples for that and have heard very positive feedback so far. Claude C add serena with ```shell -claude mcp add serena -- /path/to/uv "run" --directory /path/to/serena serena-mcp-server --project-file /path/to/project +claude mcp add serena -- /path/to/uv "run" --directory /path/to/serena serena-mcp-server --context ide-assistant ``` @@ -263,14 +293,6 @@ e.g., for one of the following reasons: 2. You are on Linux and don't want to use the [community-created Claude Desktop](https://github.com/aaddrick/claude-desktop-debian) 3. You want tighter integration of Serena into your IDE and don't mind paying for that -The same considerations as in using Serena for Claude Desktop (in particular, tool name collisions) -also apply here. - -When used in an IDE or extension that has inbuilt AI interactions for coding -(which is, really, all of them), Serena's full set of tools may lead to unwanted interactions with -the clients internal tools that you as the user may have no control over. This holds especially for the editing tools, which you may want to disable for this purpose. -As we are gaining more experience with Serena used within the various popular clients, we will collect and enhance best practices that enable a smooth experience. - ### Goose [goose](https://github.com/block/goose) is a standalone coding agent which has an integration for MCP servers and offers a CLI (as well as a GUI on macOS). diff --git a/project.template.yml b/project.template.yml index 7484596b..2e1e1c3f 100644 --- a/project.template.yml +++ b/project.template.yml @@ -1,7 +1,3 @@ -# absolute path to the project you want Serena to work on (where all the source code, etc. is located) -# This is optional if this file is placed in the project directory under `.serena/project.yml`. -project_root: /path/to/project - # language of the project (csharp, python, rust, java, typescript, javascript, go, cpp, or ruby) # Special requirements: # * csharp: Requires the presence of a .sln file in the project folder. @@ -36,8 +32,7 @@ read_only: false # * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced. # * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type). # * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). -# * `get_active_project`: Gets the name of the currently active project (if any) and lists existing projects -# * `get_current_config`: Prints the current configuration of the agent, including the active modes, tools, and context. +# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. # * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file or directory. # * `initial_instructions`: Gets the initial instructions for the current project. # Should only be used in settings where the system prompt cannot be set, @@ -51,6 +46,7 @@ read_only: false # * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context). # * `read_file`: Reads a file within the project directory. # * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store. +# * `remove_project`: Removes a project from the Serena configuration. # * `replace_lines`: Replaces a range of lines within a file with new content. # * `replace_symbol_body`: Replaces the full definition of a symbol. # * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen. @@ -62,3 +58,9 @@ read_only: false # * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed. # * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store. excluded_tools: [] + +# initial prompt for the project. It will always be given to the LLM upon activating the project +# (contrary to the memories, which are loaded on demand). +initial_prompt: "" + +project_name: "project_name" diff --git a/scripts/demo_run_tools.py b/scripts/demo_run_tools.py index 5d8e450d..0ae262b4 100644 --- a/scripts/demo_run_tools.py +++ b/scripts/demo_run_tools.py @@ -1,11 +1,9 @@ """ This script demonstrates how to use Serena's tools locally, useful -for testing or development. Here the config is pointing to the serena repo itself, -it assumes that you already have a serena_config.yml file setup. +for testing or development. Here the tools will be operation the serena repo itself. """ import json -from pathlib import Path from pprint import pprint from serena.agent import * diff --git a/serena_config.template.yml b/serena_config.template.yml index db921f96..206a90fe 100644 --- a/serena_config.template.yml +++ b/serena_config.template.yml @@ -15,7 +15,7 @@ gui_log_window: False # window being updated. Since we can't control how agno or Claude Desktop start Serena, # we have to live with this limitation for now. -web_dashboard: False +web_dashboard: True # Whether to open the Serena web dashboard (which will be accessible through your web browser) that # shows Serena's current session logs - as an alternative to the GUI log window which # is supported on all platforms. @@ -32,4 +32,3 @@ gui_log_level: 20 # by changing the entry in the (autogenerated) `.serena/project.yml` file. # Note: make sure there are no name collisions in the names of registered projects projects: - - /path/to/myproject diff --git a/src/serena/agent.py b/src/serena/agent.py index 3c57601d..c677fbf6 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -14,7 +14,7 @@ from abc import ABC, abstractmethod from collections import defaultdict from collections.abc import Callable, Generator, Iterable, Sequence from copy import copy, deepcopy -from dataclasses import asdict, dataclass, field +from dataclasses import dataclass, field from functools import cached_property from logging import Logger from pathlib import Path @@ -33,7 +33,7 @@ from multilspy.multilspy_logger import MultilspyLogger from multilspy.multilspy_types import SymbolKind from serena import serena_root_path, serena_version from serena.config import SerenaAgentContext, SerenaAgentMode -from serena.constants import SERENA_MANAGED_DIR_NAME +from serena.constants import PROJECT_TEMPLATE_FILE, SERENA_MANAGED_DIR_NAME from serena.dashboard import MemoryLogHandler, SerenaDashboardAPI from serena.prompt_factory import PromptFactory, SerenaPromptFactory from serena.symbol import SymbolLocation, SymbolManager @@ -117,25 +117,12 @@ class ProjectConfig(ToStringMixin): ) # find the language with the highest percentage dominant_language = max(language_composition.keys(), key=lambda lang: language_composition[lang]) - result = cls( - project_name=project_name, - language=Language(dominant_language), - ) + config_with_comments = load_yaml(PROJECT_TEMPLATE_FILE, preserve_comments=True) + config_with_comments["project_name"] = project_name + config_with_comments["language"] = dominant_language if save_to_disk: - result.save(project_root) - return result - - def save(self, project_root: str | Path) -> None: - """ - Save the project configuration to the project root. - """ - project_root = Path(project_root).resolve() - config_path = project_root / self.rel_path_to_project_yml() - config_path.parent.mkdir(parents=True, exist_ok=True) - serializable_self = asdict(self) - serializable_self["language"] = self.language.value - serializable_self["excluded_tools"] = list(self.excluded_tools) - save_yaml(str(config_path), serializable_self) + save_yaml(str(project_root / cls.rel_path_to_project_yml()), config_with_comments, preserve_comments=True) + return cls._from_yml_data(config_with_comments) @classmethod def rel_path_to_project_yml(cls) -> str: diff --git a/src/serena/constants.py b/src/serena/constants.py index ea4a7493..5b138e90 100644 --- a/src/serena/constants.py +++ b/src/serena/constants.py @@ -1,6 +1,6 @@ from pathlib import Path -_repo_root_path = Path(__file__).parent.parent.parent +_repo_root_path = Path(__file__).parent.parent.parent.resolve() REPO_ROOT = str(_repo_root_path) PROMPT_TEMPLATES_DIR = str(_repo_root_path / "config" / "prompt_templates") @@ -11,3 +11,5 @@ SERENA_MANAGED_DIR_NAME = ".serena" DEFAULT_CONTEXT = "desktop-app" DEFAULT_MODES = ("interactive", "editing") + +PROJECT_TEMPLATE_FILE = str(_repo_root_path / "project.template.yml")