From f654e1fe25d71886fba85314d4f07a9ad14a068f Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Wed, 16 Jul 2025 14:43:53 +0200 Subject: [PATCH 1/3] Add print-system-prompt command to output InitialInstructionsTool result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This command creates a SerenaAgent instance for a project and uses the InitialInstructionsTool to output the system prompt/initial instructions. It follows the same pattern as the existing index-project command and can be run with: uv run print-system-prompt [project_path] 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- pyproject.toml | 1 + src/serena/agent.py | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 24ba0412..c0c4c813 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ dependencies = [ [project.scripts] serena-mcp-server = "serena.mcp:start_mcp_server" index-project = "serena.agent:index_project" +print-system-prompt = "serena.agent:print_system_prompt" [project.license] text = "MIT" diff --git a/src/serena/agent.py b/src/serena/agent.py index 454986f4..1fa85e90 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -124,6 +124,33 @@ def index_project(project: str, log_level: str = "INFO") -> None: print(f"Symbols saved to {ls.cache_path}") +@click.command() +@click.argument("project", type=click.Path(exists=True), required=False, default=os.getcwd()) +@click.option("--log-level", type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]), default="WARNING") +def print_system_prompt(project: str, log_level: str = "WARNING") -> None: + """ + Print the system prompt (initial instructions) for a project. + + :param project: the project to get the system prompt for. By default, the current working directory is used. + """ + log_level_int = logging.getLevelNamesMapping()[log_level.upper()] + logging.configure(level=log_level_int) + + # Create a SerenaAgent instance + agent = SerenaAgent(project=os.path.abspath(project)) + + # Get the InitialInstructionsTool instance + from serena.tools.workflow_tools import InitialInstructionsTool + + initial_instructions_tool = agent.get_tool(InitialInstructionsTool) + + # Apply the tool to get the system prompt + system_prompt = initial_instructions_tool.apply() + + # Print the system prompt + print(system_prompt) + + class SerenaAgent: def __init__( self, From a9bc2c648379e1145fc9e4226330a95ceafb40af Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Wed, 16 Jul 2025 15:48:37 +0200 Subject: [PATCH 2/3] Minor extension of print_system_prompt command, added explanation on using it to readme [ci skip] --- README.md | 8 +++++-- src/serena/agent.py | 38 +++++++++++++++++------------- src/serena/tools/workflow_tools.py | 6 ++--- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index f509fd6e..7a1cfe3d 100644 --- a/README.md +++ b/README.md @@ -354,8 +354,12 @@ For example, when using `uvx`, you would run claude mcp add serena -- uvx --from git+https://github.com/oraios/serena serena-mcp-server --context ide-assistant --project $(pwd) ``` -ℹ️ Once in Claude Code, run `/mcp__serena__initial_instructions` to load instructions for using Serena's tools. Run this command -whenever you start a new conversation and after any compacting operation to ensure Claude remains properly configured to use Serena's tools. +ℹ️ Serena comes with instructions on how to use tools, and Claude needs to read them to properly use serena's tools. + Once in Claude Code, you can ask to "read Serena's initial instructions" or to run `/mcp__serena__initial_instructions` to load instructions for using Serena's tools. + Do this whenever you start a new conversation and after any compacting operation to ensure Claude remains properly configured to use Serena's tools. + +ℹ️ **NEW**: an alternative to the above is adding the instructions as part of the system prompt, then you will not need to run the command above or to remember re-running it after compacting. + This can be achieved throug starting claude code with `cclaude --append-system-prompt $(uvx --from git+https://github.com/oraios/serena print-system-prompt)`. This is **experimental**, Claude may not understand the instructions correctly in this way. Please report any issues you encounter. ### Claude Desktop diff --git a/src/serena/agent.py b/src/serena/agent.py index 1fa85e90..ac24417f 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -127,28 +127,34 @@ def index_project(project: str, log_level: str = "INFO") -> None: @click.command() @click.argument("project", type=click.Path(exists=True), required=False, default=os.getcwd()) @click.option("--log-level", type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]), default="WARNING") -def print_system_prompt(project: str, log_level: str = "WARNING") -> None: +@click.option( + "--only-instructions", + is_flag=True, + help="If set, only print the initial instructions prompt (without prefix or postfix). The prefix and postfix are small additions that are used to" + "make the initial instructions more digestible for an LLM in the context of a system prompt, as opposed to their normal usage within a conversation.", +) +def print_system_prompt(project: str, log_level: str = "WARNING", only_instructions: bool = False) -> None: """ - Print the system prompt (initial instructions) for a project. + Print the system prompt (initial instructions with a potential pre/post-fix) for a project. + """ + prefix_to_instructions_prompt = ( + "You will receive access to Serena's symbolic tools. Below are instructions for using them, take them into account." + ) + postfix_to_instructions_prompt = "You begin the conversation by acknowledging that you understood the above instructions on the symbolic tools and are ready to receive a task. You will not need to call the tool on getting initial instructions." + + from serena.tools.workflow_tools import InitialInstructionsTool - :param project: the project to get the system prompt for. By default, the current working directory is used. - """ log_level_int = logging.getLevelNamesMapping()[log_level.upper()] logging.configure(level=log_level_int) - # Create a SerenaAgent instance - agent = SerenaAgent(project=os.path.abspath(project)) - - # Get the InitialInstructionsTool instance - from serena.tools.workflow_tools import InitialInstructionsTool - + agent = SerenaAgent(project=os.path.abspath(project), serena_config=SerenaConfig(web_dashboard=False, log_level=log_level_int)) initial_instructions_tool = agent.get_tool(InitialInstructionsTool) - - # Apply the tool to get the system prompt - system_prompt = initial_instructions_tool.apply() - - # Print the system prompt - print(system_prompt) + initial_instructions = initial_instructions_tool.apply() + if only_instructions: + print(initial_instructions) + else: + system_prompt = f"{prefix_to_instructions_prompt}\n{initial_instructions}\n{postfix_to_instructions_prompt}" + print(system_prompt) class SerenaAgent: diff --git a/src/serena/tools/workflow_tools.py b/src/serena/tools/workflow_tools.py index 2c09a202..6172cc33 100644 --- a/src/serena/tools/workflow_tools.py +++ b/src/serena/tools/workflow_tools.py @@ -132,8 +132,8 @@ class InitialInstructionsTool(Tool, ToolMarkerDoesNotRequireActiveProject): def apply(self) -> str: """ Get the initial instructions for the current coding project. - You should always call this tool before starting to work (including using any other tool) on any programming task! - The only exception is when a user asks you to activate a project, in which case you should call the `activate_project` first - instead and then call this tool. + If you haven't received instructions on how to use Serena's tools in the system prompt, + you should always call this tool before starting to work (including using any other tool) on any programming task, + the only exception being when you are asked to call `activate_project`, which you should then call before. """ return self.agent.create_system_prompt() From 04b028f90c5e2705f11ed8b3216e133fe605c0fc Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Wed, 16 Jul 2025 15:57:08 +0200 Subject: [PATCH 3/3] Typos [ci skip] --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7a1cfe3d..83aa6cc3 100644 --- a/README.md +++ b/README.md @@ -354,12 +354,12 @@ For example, when using `uvx`, you would run claude mcp add serena -- uvx --from git+https://github.com/oraios/serena serena-mcp-server --context ide-assistant --project $(pwd) ``` -ℹ️ Serena comes with instructions on how to use tools, and Claude needs to read them to properly use serena's tools. - Once in Claude Code, you can ask to "read Serena's initial instructions" or to run `/mcp__serena__initial_instructions` to load instructions for using Serena's tools. +ℹ️ Serena comes with an instruction text, and Claude needs to read it to properly use Serena's tools. + Once in Claude Code, you can ask to "read Serena's initial instructions" or run `/mcp__serena__initial_instructions` to load the instruction text. Do this whenever you start a new conversation and after any compacting operation to ensure Claude remains properly configured to use Serena's tools. ℹ️ **NEW**: an alternative to the above is adding the instructions as part of the system prompt, then you will not need to run the command above or to remember re-running it after compacting. - This can be achieved throug starting claude code with `cclaude --append-system-prompt $(uvx --from git+https://github.com/oraios/serena print-system-prompt)`. This is **experimental**, Claude may not understand the instructions correctly in this way. Please report any issues you encounter. + This can be achieved through starting claude code with `claude --append-system-prompt $(uvx --from git+https://github.com/oraios/serena print-system-prompt)`. Note that this is **experimental**, Claude may not understand the instructions correctly in this way, and we haven't thoroughly tested the resulting behavior. Please report any issues you encounter. ### Claude Desktop