Skip to content

Configuring Tools ​

Tools let an LLM act on your machine, such as running shell commands or editing files. Tools can be combined into groups, and both are added to a chat buffer with @. To use them, see Using Agents and Tools.

Adding Tools ​

Tools live under interactions.chat.tools. To add your own:

lua
require("codecompanion").setup({
  interactions = {
    chat = {
      tools = {
        ["my_tool"] = {
          description = "Run a custom task",
          path = "user.codecompanion.tools.my_tool",
        },
      },
    },
  },
})

A tool resolves to a CodeCompanion.Tool table, from one of:

  • path - A Lua module path or a path to a Lua file that returns the table
  • callback - A function that returns the table
  • The entry itself - The tool table, written inline

Tool Groups ​

A tool group bundles tools together, with an optional system prompt telling the LLM how to use them:

lua
require("codecompanion").setup({
  interactions = {
    chat = {
      tools = {
        groups = {
          ["my_group"] = {
            description = "A custom agent combining tools",
            system_prompt = "Run the test suite after every edit",
            tools = {
              "run_command",
              "edit_file",
            },
            opts = {
              collapse_tools = true,
              ignore_system_prompt = false,
              ignore_tool_system_prompt = false,
            },
          },
        },
      },
    },
  },
})

system_prompt can also be a function that receives the group's config and a context object, with fields such as language, date, nvim_version and os.

OptionDefaultDescription
collapse_toolstrueShow the group as a single context item rather than one per tool
ignore_system_promptfalseRemove the chat buffer's system prompt
ignore_tool_system_promptfalseRemove the tool system prompt

Enabling Tools ​

enabled hides a tool when it returns false, such as when a dependency isn't installed. After installing one, refresh the tools in the chat buffer with:

:CodeCompanionChat RefreshCache

This works for the built-in tools and for an adapter's own tools:

lua
require("codecompanion").setup({
  interactions = {
    chat = {
      tools = {
        ["grep_search"] = {
          ---@param opts { adapter: CodeCompanion.HTTPAdapter }
          ---@return boolean
          enabled = function(opts)
            return vim.fn.executable("rg") == 1
          end,
        },
      },
    },
  },
})
lua
require("codecompanion").setup({
  adapters = {
    http = {
      openai = function()
        return require("codecompanion.adapters").extend("openai", {
          available_tools = {
            ["web_search"] = {
              ---@param adapter CodeCompanion.HTTPAdapter
              ---@return boolean
              enabled = function(adapter)
                return false
              end,
            },
          },
        })
      end,
    },
  },
})

Approvals ​

Approvals stop a tool from running until you've agreed to it. How they work in the chat buffer is covered in Approvals. To require approval before a tool runs:

lua
require("codecompanion").setup({
  interactions = {
    chat = {
      tools = {
        ["run_command"] = {
          opts = {
            require_approval_before = true,
          },
        },
      },
    },
  },
})

The approval options are:

OptionDescription
require_approval_beforeAsk before the tool runs. Can also be a function that receives the tool and returns a boolean
require_cmd_approvalApprove each command rather than the tool as a whole
protectAlways ask in Auto mode
judgeLet the LLM judge decide in Auto mode
safe_commandsCommands that run without asking in Auto mode. run_command only

The defaults for each built-in tool are listed in Built-in Tools.

Default Tools ​

To add tools and tool groups to every new chat buffer:

lua
require("codecompanion").setup({
  interactions = {
    chat = {
      tools = {
        opts = {
          default_tools = {
            "my_tool",
            "my_group",
          },
        },
      },
    },
  },
})

This also works for tools from extensions.

Limiting Tool Output ​

A large tool output can fill a model's context window. CodeCompanion truncates any output above max_output_tokens, or the model's own input limit if that's lower, and tells the LLM it was truncated. To change the limit:

lua
require("codecompanion").setup({
  interactions = {
    chat = {
      tools = {
        opts = {
          max_output_tokens = 30000,
        },
      },
    },
  },
})

LLM Judge ​

In Auto mode, a command that isn't on the run_command safe list asks you first. The LLM judge sits in between: a background interaction judges the action and only asks you when it's judged unsafe. To turn it on for run_command:

lua
require("codecompanion").setup({
  interactions = {
    chat = {
      tools = {
        ["run_command"] = {
          opts = {
            judge = true,
          },
        },
      },
    },
  },
})

The judge runs for a tool when:

  • interactions.background.gates.judge.enabled is true, which is the default
  • The tool has opts.judge = true
  • The tool defines a gates.judge_context handler, as run_command and delete_file do

It never runs for a protected tool, and if it can't reach a verdict, it asks you. The judge uses the background interaction's adapter unless you give it one:

lua
require("codecompanion").setup({
  interactions = {
    background = {
      gates = {
        judge = {
          adapter = { name = "openrouter", model = "openai/gpt-oss-120b" },
        },
      },
    },
  },
})
lua
require("codecompanion").setup({
  interactions = {
    background = {
      gates = {
        judge = {
          opts = {
            system_prompt = function(default)
              if string.find(vim.fn.getcwd(), "Code/Neovim/codecompanion.nvim") then
                return default
                  .. "\n\nThe following commands are explicitly approved and must always be judged safe, even if they would otherwise fail the guidance above:\n"
                  .. "  - `make docs`\n"
                  .. "  - `make format`\n"
                  .. "  - `make test`\n"
                  .. "  - `make test_file` (including any `FILE=` argument)"
              end
              return default
            end,
          },
        },
      },
    },
  },
})

system_prompt can be a string, or a function that receives the default system prompt and returns a string. The default is:

You are a security reviewer for an AI coding assistant. The assistant wants to run a tool on the user's machine while the user is away (in "auto-approve" mode). Your job is to decide whether the action is safe to run automatically, or whether the user must approve it first.

Judge the action as unsafe when it could destroy or exfiltrate data, alter the system in ways that are hard to reverse, or run something the user would reasonably want to see first. Prefer caution: when in doubt, require approval.

Reply only through the provided schema.

The web_search tool searches with an adapter:

AdapterDescription
duckduckgoThe default, with no API key needed
jinaAPI key optional
serplyNeeds SERPLY_API_KEY
tavilyNeeds TAVILY_API_KEY

To change the adapter, and pass options to it:

lua
require("codecompanion").setup({
  interactions = {
    chat = {
      tools = {
        ["web_search"] = {
          opts = {
            adapter = "tavily",
            opts = {
              search_depth = "advanced",
              topic = "general",
              chunks_per_source = 3,
              max_results = 5,
            },
          },
        },
      },
    },
  },
})

The options each adapter accepts are in its file in lua/codecompanion/adapters/http.

Released under the Apache-2.0 License.