Creating Extensions
CodeCompanion supports extensions similar to telescope.nvim, allowing users to create functionality that can be shared with others. Extensions can either be distributed as plugins or defined locally in your configuration.
Using Extensions
Extensions are configured in your CodeCompanion setup:
-- Install the extension
{
"olimorris/codecompanion.nvim",
dependencies = {
"author/codecompanion_history.nvim" -- history extension
}
}
-- Configure in your setup
require("codecompanion").setup({
extensions = {
codecompanion_history = {
enabled = true, -- defaults to true
opts = {
history_file = vim.fn.stdpath("data") .. "/codecompanion_chats.json",
max_history = 10, -- maximum number of chats to keep
}
}
}
})
Creating Extensions
Extensions are typically distributed as plugins. Create a new plugin with the following structure:
your-extension/
├── lua/
│ └── codecompanion/
│ └── _extensions/
│ └── your_extension/
│ └── init.lua -- Main extension file
└── README.md
The init.lua file should export a module that provides setup and optional exports:
---@class CodeCompanion.Extension
---@field setup fun(opts: table) Function called when extension is loaded
---@field exports? table Functions exposed via codecompanion.extensions.your_extension
local Extension = {}
---Setup the extension
---@param opts table Configuration options
function Extension.setup(opts)
-- Initialize extension
-- Add actions, keymaps etc.
end
-- Optional: Functions exposed via codecompanion.extensions.your_extension
Extension.exports = {
clear_history = function() end
}
return Extension
Extending Chat Functionality
A common pattern is to add keymaps, slash_commands, tools to the codecompanion.config object inside setup function.
---This is called on codecompanion setup.
---You can access config via require("codecompanion.config") and chat via require("codecompanion.chat").last_chat() etc
function Extension.setup(opts)
-- Add action to chat keymaps
local chat_keymaps = require("codecompanion.config").strategies.chat.keymaps
chat_keymaps.open_saved_chats = {
modes = {
n = opts.keymap or "gh",
},
description = "Open Saved Chats",
callback = function(chat)
-- Implementation of opening saved chats
vim.notify("Opening saved chats for " .. chat.id)
end
}
end
Once configured, extension exports are accessible via:
local codecompanion = require("codecompanion")
-- Use exported functions
codecompanion.extensions.codecompanion_history.clear_history()
Local Extensions
Extensions can also be defined directly in your configuration for simpler use cases:
-- Example: Adding a message editor extension
require("codecompanion").setup({
extensions = {
editor = {
enabled = true,
opts = {},
callback = {
setup = function(ext_config)
-- Add a new action to chat keymaps
local open_editor = {
modes = {
n = "ge", -- Keymap to open editor
},
description = "Open Editor",
callback = function(chat)
-- Implementation of editor opening logic
-- You have access to the chat buffer via the chat parameter
vim.notify("Editor opened for chat " .. chat.id)
end,
}
-- Add the action to chat keymaps config
local chat_keymaps = require("codecompanion.config").strategies.chat.keymaps
chat_keymaps.open_editor = open_editor
end,
-- Optional: Expose functions
exports = {
is_editor_open = function()
return false -- Implementation
end
}
}
}
}
})
The callback can be:
- A function returning the extension table
- The extension table directly
- A string path to a module that returns the extension
Dynamic registration
Extensions can also be added dynamically using
require("codecompanion").register_extension("codecompanion_history", {
callback = {
setup = function()
end,
exports = {}
},
})
Best Practices
Namespacing:
- Use unique names for extensions to avoid conflicts
- Prefix functions and variables appropriately
Configuration:
- Provide sensible defaults
- Allow customization via opts table
- Document all options
Integration:
- Follow CodeCompanion's patterns for actions and tools
- Use existing utilities like keymaps.set_keymap
- Handle errors appropriately
Documentation:
- Document installation process
- List all available options
- Provide usage examples