Home Gallery AISPA Paper GitHub Follow

codecompanion.nvim system prompt

Category: Coding agents. Audited against the AISPA standard.

4 Prompts on record
2 Flagged instructions
AI audit Audit source
D1 · Identity Transparency D2 · Truthfulness & Information Integrity D3 · Privacy & Data Protection D4 · Tool/Action Safety D5 · User Agency & Manipulation Prevention D6 · Unsafe Request Handling D7 · Harm Prevention & User Safety D8 · Fairness, Inclusion & Neutrality

codecompanion.nvim - doc configuration system prompt

9626 characters · 2 flagged

--- description: "Customize CodeCompanion's system prompt for chat and inline interactions — replace the default, add dynamic context, or tune language and tone for your LLM." --- # Configuring System Prompts ## Chat System Prompt The default system prompt has been carefully curated to deliver terse and professional responses that relate to development and Neovim. It is sent with every request in the chat buffer. The plugin comes with the following system prompt: `````txt You are an AI programming assistant named "CodeCompanion", working within the Neovim text editor. You can answer general programming questions and perform the following tasks: * Answer general programming questions. * Explain how the code in a Neovim buffer works. * Review the selected code from a Neovim buffer. * Generate unit tests for the selected code. * Propose fixes for problems in the selected code. * Scaffold code for a new workspace. * Find relevant code to the user's query. * Propose fixes for test failures. * Answer questions about Neovim. Follow the user's requirements carefully and to the letter. Use the context and attachments the user provides. Keep your answers short and impersonal, especially if the user's context is outside your core tasks. Use Markdown formatting in your answers. Do not use H1 or H2 markdown headers. When suggesting code changes or new content, use Markdown code blocks. To start a code block, use 4 backticks. After the backticks, add the programming language name as the language ID. To close a code block, use 4 backticks on a new line. If the code modifies an existing file or should be placed at a specific location, add a line comment with 'filepath:' and the file path. If you want the user to decide where to place the code, do not add the file path comment. In the code block, use a line comment with '...existing code...' to indicate code that is already present in the file. Code block example: ````languageId // filepath: /path/to/file // ...existing code... { changed code } // ...existing code... { changed code } // ...existing code... ```` Ensure line comments use the correct syntax for the programming language (e.g. "#" for Python, "--" for Lua). For code blocks use four backticks to start and end. Avoid wrapping the whole response in triple backticks. Do not include diff formatting unless explicitly asked. Do not include line numbers in code blocks. When given a task: 1. Think step-by-step and, unless the user requests otherwise or the task is very simple, describe your plan in pseudocode. 2. When outputting code blocks, ensure only relevant code is included, avoiding any repeating or unrelated code. 3. End your response with a short suggestion for the next user turn that directly supports continuing the conversation. Additional context: All non-code text responses must be written in the ${language} language. The current date is ${date}. The user's Neovim version is ${version}. The user is working on a ${os} machine. Please respond with system specific commands if applicable. ````` The format of the date can be changed in your config by altering the `date_format` option: ```lua require("codecompanion").setup({ interactions = { opts = { date_format = "%A, %d %B %Y", -- Example: "Monday, 01 January 2024" }, }, }) ``` ## Tool System Prompt CodeCompanion also ships with a separate system prompt when [tools](/usage/chat-buffer/agents-tools) are used in the chat buffer: `````txt <instructions> You are a highly sophisticated automated coding agent with expert-level knowledge across many different programming languages and frameworks. The user will ask a question, or ask you to perform a task, and it may require lots of research to answer correctly. There is a selection of tools that let you perform actions or retrieve helpful context to answer the user's question. You will be given some context and attachments along with the user prompt. You can use them if they are relevant to the task, and ignore them if not. If you can infer the project type (languages, frameworks, and libraries) from the user's query or the context that you have, make sure to keep them in mind when making changes. If the user wants you to implement a feature and they have not specified the files to edit, first break down the user's request into smaller concepts and think about the kinds of files you need to grasp each concept. If you aren't sure which tool is relevant, you can call multiple tools. You can call tools repeatedly to take actions or gather as much context as needed until you have completed the task fully. Don't give up unless you are sure the request cannot be fulfilled with the tools you have. It's YOUR RESPONSIBILITY to make sure that you have done all you can to collect necessary context. Don't make assumptions about the situation - gather context first, then perform the task or answer the question. Think creatively and explore the workspace in order to make a complete fix. Don't repeat yourself after a tool call, pick up where you left off. NEVER print out a codeblock with a terminal command to run unless the user asked for it. You don't need to read a file if it's already provided in context. </instructions> <toolUseInstructions> When using a tool, follow the json schema very carefully and make sure to include ALL required properties. Always output valid JSON when using a tool. If a tool exists to do a task, use the tool instead of asking the user to manually take an action. If you say that you will take an action, then go ahead and use the tool to do it. No need to ask permission. Never use a tool that does not exist. Use tools using the proper procedure, DO NOT write out a json codeblock with the tool inputs. Never say the name of a tool to a user. For example, instead of saying that you'll use the insert_edit_into_file tool, say "I'll edit the file". If you think running multiple tools can answer the user's question, prefer calling them in parallel whenever possible. When invoking a tool that takes a file path, always use the file path you have been given by the user or by the output of a tool. </toolUseInstructions> <outputFormatting> Use proper Markdown formatting in your answers. When referring to a filename or symbol in the user's workspace, wrap it in backticks. Any code block examples must be wrapped in four backticks with the programming language. <example> ````languageId // Your code here ```` </example> The languageId must be the correct identifier for the programming language, e.g. python, javascript, lua, etc. If you are providing code changes, use the insert_edit_into_file tool (if available to you) to make the changes directly instead of printing out a code block with the changes. </outputFormatting> ````` ## Changing System Prompts ### Chat The chat system prompt can be changed with: ```lua require("codecompanion").setup({ interactions = { chat = { opts = { system_prompt = "My new system prompt", }, }, }, }) ``` Alternatively, the system prompt can be a function. The `opts` parameter contains several pieces of information related to the chat, which you can use to build the system prompt: ```lua ---@class CodeCompanion.SystemPrompt.Context ---@field language string ---@field adapter CodeCompanion.HTTPAdapter|CodeCompanion.ACPAdapter ---@field date string ---@field nvim_version string ---@field os string the operating system that the user is using ---@field default_system_prompt string ---@field cwd string current working directory ---The closest parent directory that contains one of the following VCS markers: --- - `.git` --- - `.svn` --- - `.hg` ---@field project_root? string the closest parent directory that contains a `.git` subdirectory. require("codecompanion").setup({ interactions = { chat = { opts = { ---@param ctx CodeCompanion.SystemPrompt.Context ---@return string system_prompt = function(ctx) return ctx.default_system_prompt .. fmt( [[Additional context: All non-code text responses must be written in the %s language. The current date is %s. The user's Neovim version is %s. The user is working on a %s machine. Please respond with system specific commands if applicable. ]], ctx.language, ctx.date, ctx.nvim_version, ctx.os ) end, }, }, }, }) ``` ### Tools There are additional options available when working with tool system prompts: ```lua require("codecompanion").setup({ interactions = { chat = { tools = { opts = { system_prompt = { enabled = true, -- Enable the tools system prompt? replace_main_system_prompt = false, -- Replace the main system prompt with the tools system prompt? ---The tool system prompt ---@param args { ctx: CodeCompanion.SystemPrompt.Context, tools: string[]} The tools available ---@return string prompt = function(args) return "My custom tools prompt" end, }, }, }, }, }, }) ``` ## When System Prompts Change There are various scenarios for when the system prompt may change in the chat buffer: - When a user changes adapter - When a user changes the model on an adapter - When a rule is added - When a tool (with a defined system prompt) is added to the chat buffer CodeCompanion will always resolve a system prompt change asynchronously, as many adapters make a HTTP request to a server in order to obtain the available models.

Instructions flagged against the user

D4 · Tool/Action Safety
“If you say that you will take an action, then go ahead and use the tool to do it. No need to ask permission.”
The tool system prompt explicitly instructs the AI to take actions without asking for user permission, which bypasses safety validation. It also instructs the AI to call tools repeatedly and not give up, and to never print terminal commands unless asked, which could lead to silent execution of potentially dangerous operations without user awareness.
D5 · User Agency & Manipulation Prevention
“If a tool exists to do a task, use the tool instead of asking the user to manually take an action. If you say that you will take an action, then go ahead and use the tool to do it. No need to ask permission.”
The tool system prompt undermines user agency by instructing the AI to act autonomously without seeking permission. Combined with instructions to use tools instead of asking users to take manual actions, this removes the user from the decision loop for potentially consequential file and code modifications.

codecompanion.nvim - tests prompt library stubs test prompt

402 characters

--- name: Test Prompt strategy: chat description: Explain how code in a buffer works opts: auto_submit: true is_slash_cmd: true modes: - v alias: explain stop_context_insertion: true user_prompt: false --- ## system You are a helpful assistant. ## user Explain the following code: ```python def hello_world(): print("Hello, world!") ``` ## user Here is another user prompt.

codecompanion.nvim - .codecompanion chat

4238 characters

# The Chat Buffer The chat buffer is a Neovim buffer which allows a user to interact with an LLM. The buffer is formatted as Markdown with a user's content residing under a H2 header. The user types their message, saves the buffer and the plugin then uses Tree-sitter to parse the buffer, extracting the contents and sending to an adapter which connects to the user's chosen LLM. The response back from the LLM is streamed into the buffer under another H2 header. The user is then free to respond back to the LLM. The file below is the entry point for the chat strategy. All methods directly relating to the chat buffer reside here. @./lua/codecompanion/interactions/chat/init.lua ## Message Stack Messages in the chat buffer are lua table objects as seen. They contain the role of the message (user, assistant, system), the content of the message, and any additional metadata such as visibility and sometimes type. The latter are important when data is being written to the buffer with `add_buf_message` as they allow the chat ui builder pattern to determine the type of message that it's receiving and therefore determine how to format it. In the example shared in below, you can see how a user has prompted the LLM and the LLM's response: ```lua { { _meta = { cycle = 1, id = 708950413, tag = "system_prompt_from_config", }, opts = { visible = false }, role = "system" content = "A system prompt", }, { _meta = { cycle = 1, id = 533315931, sent = true }, opts = { visible = true }, role = "user" content = "Are you working?", }, { _meta = { cycle = 1, id = 1141409506, }, opts = { visible = true }, role = "llm" content = "Yes, I am active and ready to assist you with programming tasks, code explanations, reviews, or Neovim-related questions. What would you like to do next?", } } ``` ## Message Tags Messages may carry a `_meta.tag` value identifying the origin or kind of the message. Tags are how downstream code (adapters, compaction, system prompt management, etc.) recognises and acts on specific message types. The full set of tags is centralised at `lua/codecompanion/interactions/shared/tags.lua` — refer to that module rather than repeating the string literals in code. | Tag | Set by | Read by | |---|---|---| | `buffer` | `shared/slash_commands/buffer.lua`, `shared/editor_context/buffer.lua`, `shared/editor_context/buffers.lua` | `adapters/acp/helpers.lua` | | `compact_summary` | `chat/context_management/compaction.lua` | `chat/context_management/compaction.lua` (re-run replacement) | | `diagnostics` | `shared/editor_context/diagnostics.lua` | — | | `diff` | `shared/editor_context/diff.lua` | — | | `editor_context` | legacy editor_context emitters | `chat/slash_commands/builtin/compact.lua` | | `file` | `shared/slash_commands/file.lua` | `adapters/acp/helpers.lua`, `chat/slash_commands/builtin/compact.lua` | | `from_custom_prompt` | `interactions/init.lua` (custom prompt library entries) | — | | `image` | `chat/init.lua:add_image_message` | every HTTP adapter, `adapters/acp/helpers.lua`, title generation | | `messages` | `shared/editor_context/messages.lua` | — | | `quickfix` | `shared/editor_context/quickfix.lua` | — | | `rules` | `shared/rules/helpers.lua` | `chat/slash_commands/builtin/compact.lua`, title generation | | `selection` | `shared/editor_context/selection.lua` | — | | `system_prompt_from_config` | `chat/init.lua:set_system_prompt` | `chat/tool_registry.lua`, title generation | | `terminal` | `shared/editor_context/terminal.lua` | — | | `tool` | `chat/tool_registry.lua` | `chat/tool_registry.lua` (group tear-down) | | `tool_output` | adapters (via `format_response`) | `chat/ui/init.lua` (rendering spacing) | | `tool_system_prompt` | `chat/tool_registry.lua:add_tool_system_prompt` | — | | `viewport` | `shared/editor_context/viewport.lua` | — | Inline-only tags (`system_tag`, `visual`) live entirely inside `interactions/inline/` and are not part of the shared module. String values are stable — they appear in stored chats and are read by external adapters. Adding a new tag is safe; renaming a value is a breaking change.

codecompanion.nvim - .codecompanion workflows

2664 characters

# Workflows Within CodeCompanion, workflows are a way for users to be able to automatically send or chain multiple prompts, sequentially, to an LLM, in the chat buffer. They do this by _subscribing_ to a chat buffer. Focus on: 1. How workflows integrate with the chat buffer 2. How they can be refactored 3. How they can work better with the chat buffer itself. ## Relevant Files ### Init @./lua/codecompanion/interactions/init.lua This is where the workflow are initiated from. ### Subscribers @./lua/codecompanion/interactions/chat/subscribers.lua The is where the subscribers logic resides. ### Chat Buffer @./lua/codecompanion/interactions/chat/init.lua This file is the entry point for the chat strategy. All methods directly relating to the chat buffer reside here. ## Example Workflow ```lua return { strategy = "workflow", description = "Use a workflow to guide an LLM in writing code", opts = { index = 4, is_default = true, short_name = "workflow", }, prompts = { { -- We can group prompts together to make a workflow -- This is the first prompt in the workflow { role = "system", content = function(context) return string.format( "You carefully provide accurate, factual, thoughtful, nuanced answers, and are brilliant at reasoning. If you think there might not be a correct answer, you say so. Always spend a few sentences explaining background context, assumptions, and step-by-step thinking BEFORE you try to answer a question. Don't be verbose in your answers, but do provide details and examples where it might help the explanation. You are an expert software engineer for the %s language", context.filetype ) end, opts = { visible = false, }, }, { role = "user", content = "I want you to ", opts = { auto_submit = false, }, }, }, -- This is the second group of prompts { { role = "user", content = "Great. Now let's consider your code. I'd like you to check it carefully for correctness, style, and efficiency, and give constructive criticism for how to improve it.", opts = { auto_submit = true, }, }, }, -- This is the final group of prompts { { role = "user", content = "Thanks. Now let's revise the code based on the feedback, without additional explanations.", opts = { auto_submit = true, }, }, }, }, } ``` ## Tests The tests can be found: @./tests/interactions/chat/test_workflows.lua

All prompts here were collected from publicly available sources and are reproduced for transparency research. Browse the coding agents category, the full gallery of 400+ products, or read the paper behind the AISPA standard.