# Codecompanion History Nvim

> A history management extension for codecompanion AI chat plugin that enables saving, browsing and restoring chat sessions.

- **Type:** MCP server
- **Install:** `agentstack add mcp-ravitemer-codecompanion-history-nvim`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [ravitemer](https://agentstack.voostack.com/s/ravitemer)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [ravitemer](https://github.com/ravitemer)
- **Source:** https://github.com/ravitemer/codecompanion-history.nvim

## Install

```sh
agentstack add mcp-ravitemer-codecompanion-history-nvim
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# CodeCompanion History Extension

[](https://neovim.io)
[](https://www.lua.org)
[](https://github.com/ravitemer/codecompanion-history.nvim/actions)
[](https://opensource.org/licenses/MIT)
[](./CONTRIBUTING.md)

A history management extension for [codecompanion.nvim](https://codecompanion.olimorris.dev/) that enables saving, browsing and restoring chat sessions.

    

## ✨ Features

### 🤖 Chat Management
- 💾 Flexible chat saving:
  - Automatic session saving (can be disabled)
  - Manual save with dedicated keymap
- 🎯 Smart title generation for chats
- 🔄 Continue from where you left
- 📚 Browse saved chats with preview
- 🔍 Multiple picker interfaces
- ⌛ Optional automatic chat expiration
- ⚡ Restore chat sessions with full context and tools state
- 🏢 **Project-aware filtering**: Filter chats by workspace/project context
- 📋 **Chat duplication**: Easily duplicate chats to create variations or backups

### 📝 Summary System
- **Manual summary generation**: Create summaries for any chat with `gcs`
- **Intelligent content processing**: Extracts meaningful conversation content while filtering noise
- **Chunked summarization**: Handles large conversations by splitting into manageable chunks
- **Customizable generation**: Configure adapter, model, and system prompts
- **Summary browsing**: Dedicated browser with `gbs` to explore all summaries

### 🧠 Memory System (@memory tool)
- **Vector-based search**: Uses VectorCode CLI to index and search through chat summaries
- **Automatic indexing**: Optionally index summaries as they are generated
- **Smart integration**: Available as `@memory` tool in new chats when VectorCode is installed

The following CodeCompanion features are preserved when saving and restoring chats:

| Feature | Status | Notes |
|---------|--------|-------|
|  System Prompts | ✅  | System prompt used in the chat |
|  Messages History | ✅  | All messages |
|  Images | ✅  | Restores images as base64 strings |
|  LLM Adapter | ✅  | The specific adapter used for the chat |
|  LLM Settings | ✅  | Model, temperature and other adapter settings |
|  Tools | ✅  | Tool schemas and their system prompts |
|  Tool Outputs | ✅  | Tool execution results |
|  Variables | ✅  | Variables used in the chat |
|  References | ✅  | Code snippets and command outputs added via slash commands |
|  Pinned References | ✅  | Pinned references |
|  Watchers | ⚠  | Saved but requires original buffer context to resume watching |

When restoring a chat:
1. The complete message history is recreated
2. All tools and references are reinitialized
3. Original LLM settings and adapter are restored
4. Previous system prompts are preserved

> **Note**: While watched buffer states are saved, they require the original buffer context to resume watching functionality.

> [!NOTE]
> As this is an extension that deeply integrates with CodeCompanion's internal APIs, occasional compatibility issues may arise when CodeCompanion updates. If you encounter any bugs or unexpected behavior, please [raise an issue](https://github.com/ravitemer/codecompanion-history.nvim/issues) to help us maintain compatibility.

## 📋 Requirements

- Neovim >= 0.8.0
- [codecompanion.nvim](https://codecompanion.olimorris.dev/)
- [VectorCode CLI](https://github.com/Davidyz/VectorCode) (optional, for `@memory` tool)
- [snacks.nvim](https://github.com/folke/snacks.nvim) (optional, for enhanced picker)
- [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim) (optional, for enhanced picker)
- [fzf-lua](https://github.com/ibhagwan/fzf-lua) (optional, for enhanced picker)

## 📦 Installation

Using [lazy.nvim](https://github.com/folke/lazy.nvim):

### First install the plugin

```lua
{
    "olimorris/codecompanion.nvim",
    dependencies = {
        --other plugins
        "ravitemer/codecompanion-history.nvim"
    }
}
```

### Add history extension to CodeCompanion config

```lua
require("codecompanion").setup({
    extensions = {
        history = {
            enabled = true,
            opts = {
                -- Keymap to open history from chat buffer (default: gh)
                keymap = "gh",
                -- Keymap to save the current chat manually (when auto_save is disabled)
                save_chat_keymap = "sc",
                -- Save all chats by default (disable to save only manually using 'sc')
                auto_save = true,
                -- Number of days after which chats are automatically deleted (0 to disable)
                expiration_days = 0,
                -- Picker interface (auto resolved to a valid picker)
                picker = "telescope", --- ("telescope", "snacks", "fzf-lua", or "default") 
                ---Optional filter function to control which chats are shown when browsing
                chat_filter = nil, -- function(chat_data) return boolean end
                -- Customize picker keymaps (optional)
                picker_keymaps = {
                    rename = { n = "r", i = "" },
                    delete = { n = "d", i = "" },
                    duplicate = { n = "", i = "" },
                },
                ---Automatically generate titles for new chats
                auto_generate_title = true,
                title_generation_opts = {
                    ---Adapter for generating titles (defaults to current chat adapter) 
                    adapter = nil, -- "copilot"
                    ---Model for generating titles (defaults to current chat model)
                    model = nil, -- "gpt-4o"
                    ---Number of user prompts after which to refresh the title (0 to disable)
                    refresh_every_n_prompts = 0, -- e.g., 3 to refresh after every 3rd user prompt
                    ---Maximum number of times to refresh the title (default: 3)
                    max_refreshes = 3,
                    format_title = function(original_title)
                        -- this can be a custom function that applies some custom
                        -- formatting to the title.
                        return original_title
                    end
                },
                ---On exiting and entering neovim, loads the last chat on opening chat
                continue_last_chat = false,
                ---When chat is cleared with `gx` delete the chat from history
                delete_on_clearing_chat = false,
                ---Directory path to save the chats
                dir_to_save = vim.fn.stdpath("data") .. "/codecompanion-history",
                ---Enable detailed logging for history extension
                enable_logging = false,

                -- Summary system
                summary = {
                    -- Keymap to generate summary for current chat (default: "gcs")
                    create_summary_keymap = "gcs",
                    -- Keymap to browse summaries (default: "gbs")
                    browse_summaries_keymap = "gbs",
                    
                    generation_opts = {
                        adapter = nil, -- defaults to current chat adapter
                        model = nil, -- defaults to current chat model
                        context_size = 90000, -- max tokens that the model supports
                        include_references = true, -- include slash command content
                        include_tool_outputs = true, -- include tool execution results
                        system_prompt = nil, -- custom system prompt (string or function)
                        format_summary = nil, -- custom function to format generated summary e.g to remove  tags from summary
                    },
                },
                
                -- Memory system (requires VectorCode CLI)
                memory = {
                    -- Automatically index summaries when they are generated
                    auto_create_memories_on_summary_generation = true,
                    -- Path to the VectorCode executable
                    vectorcode_exe = "vectorcode",
                    -- Tool configuration
                    tool_opts = { 
                        -- Default number of memories to retrieve
                        default_num = 10 
                    },
                    -- Enable notifications for indexing progress
                    notify = true,
                    -- Index all existing memories on startup
                    -- (requires VectorCode 0.6.12+ for efficient incremental indexing)
                    index_on_startup = false,
                },
            }
        }
    }
})
```

> [!WARNING]
> Title and summary generation defaults to current chat's adapter and model. Make sure to set cheaper models in `title_generation_opts` and `summary.generation_opts` to avoid using premium models.

## 🛠️ Usage

#### 🎯 Commands

- `:CodeCompanionHistory` - Open the history browser
- `:CodeCompanionSummaries` - Browse all summaries

#### ⌨️ Chat Buffer Keymaps

**History Management:**
- `gh` - Open history browser (customizable via `opts.keymap`)
- `sc` - Save current chat manually (customizable via `opts.save_chat_keymap`)

**Summary System:**
- `gcs` - Generate summary for current chat (customizable via `opts.summary.create_summary_keymap`)
- `gbs` - Browse saved summaries (customizable via `opts.summary.browse_summaries_keymap`)

#### 📚 History Browser

The history browser shows all your saved chats with:
- Title (auto-generated or custom)
- Summary indicator (📝 icon for chats with summaries)
- Token estimates and relative timestamps
- Preview of chat contents

Actions in history browser:
- `` - Open selected chat
- Normal mode:
  - `d` - Delete selected chat(s)
  - `r` - Rename selected chat
  - `` - Duplicate selected chat
- Insert mode:
  - `` (Alt+d) - Delete selected chat(s)
  - `` (Alt+r) - Rename selected chat
  - `` - Duplicate selected chat

#### 📝 Summary Browser

The summary browser shows all your generated summaries with:
- Chat title (from original conversation)
- Project context and relative timestamps
- Preview of summary content

Actions in summary browser:
- `` - Add the summary to the current chat
- Normal mode:
  - `d` - Delete selected summary(s)
- Insert mode:
  - `` (Alt+d) - Delete selected summary(s)

## The `@memory` tool

If you have installed the [VectorCode](https://github.com/Davidyz/VectorCode) CLI, 
this plugin will use VectorCode to create an index for your chat summaries and create
a tool called `@memory`. This tool gives the LLM the ability to search for
(the summary of) previous chats so that you can refer to them in a new chat.

Available options for the memory submodule:
```lua
opts.memory = {
    auto_create_memories_on_summary_generation = true,
    -- path to the `vectorcode` executable
    vectorcode_exe = "vectorcode",
    tool_opts = { 
        -- default number of memories to retrieve
        default_num = 10 
    },
    -- whether to enable notification
    notify = true,
    -- whether to automatically update the index of all existing memories on startup
    -- (requires VectorCode 0.6.12+ for efficient incremental indexing)
    index_on_startup = false,
}
```

#### 🔄 Title Refresh Feature

The extension can automatically refresh chat titles as conversations evolve:

- **`refresh_every_n_prompts`**: Set to refresh the title after every N user prompts (e.g., 3 means refresh after the 3rd, 6th, 9th user message)
- **`max_refreshes`**: Limits how many times a title can be refreshed to avoid excessive API calls
- When refreshing, the system considers recent conversation context (both user and assistant messages) and the original title
- Individual messages are truncated at 1000 characters with a `[truncated]` indicator
- Total conversation context is limited to 10,000 characters with a `[conversation truncated]` indicator

Example configuration for title refresh:
```lua
title_generation_opts = {
    refresh_every_n_prompts = 3, -- Refresh after every 3rd user prompt
    max_refreshes = 10,           -- Allow up to 10 refreshes per chat
}
```

#### 🏢 Project-Aware Chat Filtering

The extension supports flexible chat filtering to help you focus on relevant conversations:

**Configurable Filtering:**
```lua
chat_filter = function(chat_data)
    return chat_data.cwd == vim.fn.getcwd()
end

-- Recent chats only (last 7 days)
chat_filter = function(chat_data)
    local seven_days_ago = os.time() - (7 * 24 * 60 * 60)
    return chat_data.updated_at >= seven_days_ago
end
```

**Chat Index Data Structure:**
Each chat index entry (used in filtering) includes the following information:
```lua
-- ChatIndexData - lightweight metadata used for browsing and filtering
{
    save_id = "1672531200",                 -- Unique chat identifier
    title = "Debug API endpoint",           -- Chat title (auto-generated or custom)
    cwd = "/home/user/my-project",          -- Working directory when saved
    project_root = "/home/user/my-project", -- Detected project root
    adapter = "openai",                     -- LLM adapter used
    model = "gpt-4",                        -- Model name
    updated_at = 1672531200,                -- Unix timestamp of last update
    message_count = 15,                     -- Number of messages in chat
    token_estimate = 3420,                  -- Estimated token count
}
```

#### 🔧 API

The history extension exports the following functions that can be accessed via `require("codecompanion").extensions.history`:

```lua
-- Chat Management
get_location(): string?                           -- Get storage location

-- Save a chat to storage (uses last chat if none provided) 
save_chat(chat?: CodeCompanion.Chat)

-- Browse chats with custom filter function
browse_chats(filter_fn?: function(ChatIndexData): boolean)

-- Get metadata for all saved chats with optional filtering
get_chats(filter_fn?: function(ChatIndexData): boolean): table

-- Load a specific chat by its save_id
load_chat(save_id: string): ChatData?

-- Delete a chat by its save_id
delete_chat(save_id: string): boolean

-- Duplicate a chat by its save_id
duplicate_chat(save_id: string, new_title?: string): string?

-- Summary Management  
--- Generate a summary for the current chat 
generate_summary(chat?: CodeCompanion.Chat)      

--- Delete a sumamry
delete_summary(summary_id: string)      

--- Get summaries index
get_summaries(): table 

--- Load summary 
load_summary(summary_id: string): string?        
```

Example usage:
```lua
local history = require("codecompanion").extensions.history

-- Browse chats with project filter
history.browse_chats(function(chat_data)
    return chat_data.project_root == utils.find_project_root()
end)

-- Get all saved chats metadata
local chats = history.get_chats()
local chat_data = history.load_chat("some_save_id")
history.delete_chat("some_save_id")

-- Duplicate a chat with custom title
local new_save_id = history.duplicate_chat("some_save_id", "My Custom Copy")

-- Duplicate a chat with auto-generated title (appends "(1)")
local new_save_id = history.duplicate_chat("some_save_id")

-- Summary operations
history.generate_summary() -- generates for current chat

local summaries = history.get_summaries()

local summary_content = history.load_summary("some_save_id")

```

## ⚙️ How It Works

```mermaid
graph TD
    subgraph CodeCompanion Core Lifecycle
        A[CodeCompanionChatCreated Event] --> B{Chat Submitted};
        B --> C[LLM Response Received];
        subgraph Chat End
            direction RL
            D[CodeCompanionChatCleared Event];
        end
        C --> D;
        B --> D;
    end

    subgraph Extension Integration
        A -- Extension Hooks --> E[Init & Subscribe];
        E --> F[Setup Auto-Save];
        F --> G[Prepare Auto-Title];

        C -- Extension Hooks --> H[Subscriber Triggered];
        H --> H1{Auto-Save Enabled?};
        H1 -- Yes --> I[Save Chat State - Messages, Tools, Refs];
        H1 -- No --> H2[Manual Save via `sc`];
        H2 --> I;
        I --> J{No Title & Auto

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [ravitemer](https://github.com/ravitemer)
- **Source:** [ravitemer/codecompanion-history.nvim](https://github.com/ravitemer/codecompanion-history.nvim)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-ravitemer-codecompanion-history-nvim
- Seller: https://agentstack.voostack.com/s/ravitemer
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
