Configuration
Table of contents
- Basic Options
- Storage Paths
- HTTP Server Configuration
- API Key Configuration
- File Access Control
- Context Window Configuration
- Memory System Configuration
- User Profile Configuration
- Skills Configuration
- Auto-Retry Configuration
- system_prompt Usage Examples
- Complete Configuration Example
- Configuration Notes
- Next Steps
chat.nvim provides flexible configuration options through the require('chat').setup() function. All configurations have sensible defaults.
Basic Options
| Option | Type | Default | Description |
|---|---|---|---|
width |
number | 0.8 |
Chat window width (percentage of screen width, 0.0-1.0) |
height |
number | 0.8 |
Chat window height (percentage of screen height, 0.0-1.0) |
auto_scroll |
boolean | true |
Controls automatic scrolling behavior of the result window |
border |
string | 'rounded' |
Window border style, supports all Neovim border options |
provider |
string | 'deepseek' |
Default AI provider |
model |
string | 'deepseek-v4-flash' |
Default AI model |
strftime |
string | '%m-%d %H:%M:%S' |
Time display format |
render_markdown |
boolean | true |
Enable RenderMarkdown plugin for result buffer (requires render-markdown.nvim) |
system_prompt |
string or function | '' |
Default system prompt, can be a string or a function that returns a string |
storage_dir |
string | stdpath('data') .. '/chat.nvim/' |
Base storage directory for all persistent data (sessions, plans, scheduler, etc.) |
highlights |
table | {title = 'ChatNvimTitle', title_badge = 'ChatNvimTitleBadge'} |
Highlight groups for title text and decorative badges |
winhighlight |
string | 'NormalFloat:Normal,FloatBorder:WinSeparator' |
Window highlight configuration for floating windows |
Example
require('chat').setup({
width = 0.8,
height = 0.8,
auto_scroll = true,
border = 'rounded',
provider = 'deepseek',
model = 'deepseek-v4-flash',
strftime = '%Y-%m-%d %H:%M',
})
Storage Paths
All persistent data (sessions, plans, scheduler, memory, user profiles) is stored under storage_dir. Sub-module storage directories are automatically derived from storage_dir unless explicitly overridden:
| Module | Config Key | Derived Path | Description |
|---|---|---|---|
| Sessions | — | storage_dir |
Chat session JSON files |
| Plans | — | storage_dir .. 'plans/' |
Task plan JSON files |
| Scheduler | — | storage_dir .. 'scheduler/' |
Scheduled task JSON files |
| Memory | memory.storage_dir |
storage_dir .. 'memory/' |
Three-tier memory database |
| User Profiles | user.storage_dir |
storage_dir .. 'users/' |
User profile markdown files |
To override a specific module’s storage path, set its storage_dir to a custom value:
require('chat').setup({
-- Change the base directory for everything
storage_dir = '/my/custom/path/',
-- Or override individual modules
memory = {
storage_dir = '/separate/memory/path/',
},
})
If
memory.storage_diroruser.storage_dirisnil(the default), they are automatically derived fromstorage_dir. You only need to set them if you want to use a different location for that specific module.
HTTP Server Configuration
Configure the built-in HTTP server for receiving external messages:
| Option | Type | Default | Description |
|---|---|---|---|
http.host |
string | '127.0.0.1' |
Host address for the HTTP server |
http.port |
number | 7777 |
Port number for the HTTP server |
http.api_key |
string | '' |
API key for authenticating incoming requests (must be non-empty to enable server) |
Example
http = {
host = '127.0.0.1',
port = 7777,
api_key = 'your-secret-api-key-here', -- Set to empty string to disable HTTP server
}
Notes
- The HTTP server is automatically started when
http.api_keyis not empty- Incoming requests must include the API key in the
X-API-Keyheader- Messages are queued and processed when the chat window is not busy
API Key Configuration
Configure API keys for the AI providers you plan to use:
api_key = {
deepseek = 'sk-xxxxxxxxxxxx', -- DeepSeek AI
github = 'github_pat_xxxxxxxx', -- GitHub AI
moonshot = 'sk-xxxxxxxxxxxx', -- Moonshot AI
openrouter = 'sk-or-xxxxxxxx', -- OpenRouter
qwen = 'qwen-xxxxxxxx', -- Alibaba Qwen (DashScope)
aliyuncs = 'sk-xxxxxxxxxxxx', -- Alibaba Cloud (Bailian)
siliconflow = 'xxxxxxxx-xxxx-xxxx', -- SiliconFlow
tencent = 'xxxxxxxx-xxxx-xxxx', -- Tencent Hunyuan
baidu = 'xxxxxxxx-xxxx-xxxx', -- Baidu Qianfan
bigmodel = 'xxxxxxxx-xxxx-xxxx', -- BigModel AI (Zhipu)
volcengine = 'xxxxxxxx-xxxx-xxxx', -- Volcengine AI (Doubao)
xiaomi = 'xxxxxxxx-xxxx-xxxx', -- Xiaomi MiMo
openai = 'sk-xxxxxxxxxxxx', -- OpenAI
anthropic = 'sk-ant-xxxxxxxxxxxx', -- Anthropic Claude
gemini = 'AIxxxxxxxxxxxxxxxxxxxx', -- Google Gemini
longcat = 'lc-xxxxxxxxxxxx', -- LongCat AI
cherryin = 'sk-xxxxxxxxxxxx', -- CherryIN AI
yuanjing = 'xxxxxxxx-xxxx-xxxx', -- Yuanjing AI
}
Only configure keys for providers you plan to use; others can be omitted.
File Access Control
Control which file paths tools can access for security:
-- Option 1: Disable all file access (default)
allowed_path = ''
-- Option 2: Allow a single directory
allowed_path = '/home/user/projects'
-- Option 3: Allow multiple directories
allowed_path = {
vim.fn.getcwd(), -- Current working directory
vim.fn.expand('~/.config/nvim'), -- Neovim config directory
'/etc', -- System configuration files
}
Security Recommendations
- Empty string disables all file access
- Recommended to set to your current project directory for security
- Only allow directories you trust tools to read/write
Context Window Configuration
Configure automatic context truncation to manage token usage:
context = {
enable = true, -- Enable/disable context truncation
trigger_threshold = 50, -- Number of messages to trigger truncation
keep_recent = 10, -- Keep recent N messages (not included in truncation search)
}
Notes
- When conversation exceeds
trigger_thresholdmessages, older messages may be summarized or removed - The
keep_recentparameter ensures recent context is preserved - Helps prevent token limit errors during long conversations
Memory System Configuration
chat.nvim implements a sophisticated three-tier memory system inspired by cognitive psychology.
Memory Architecture
- Working Memory ⚡ - High-priority, session-scoped memory for current tasks and decisions
- Daily Memory 📅 - Temporary memory for daily tasks and short-term goals (auto-expires)
- Long-term Memory 💾 - Permanent knowledge storage for facts, preferences, and skills
Configuration Example
memory = {
enable = true, -- Global memory system switch
-- Long-term memory: Permanent knowledge (never expires)
long_term = {
enable = true,
max_memories = 500, -- Maximum memories to store
retrieval_limit = 3, -- Maximum memories to retrieve per query
similarity_threshold = 0.3, -- Text similarity threshold (0-1)
},
-- Daily memory: Temporary tasks and goals (auto-expires)
daily = {
enable = true,
retention_days = 7, -- Days before auto-deletion
max_memories = 100, -- Maximum daily memories
similarity_threshold = 0.4,
},
-- Working memory: Current session focus (highest priority)
working = {
enable = true,
max_memories = 20, -- Maximum working memories per session
priority_weight = 2.0, -- Priority multiplier (higher = more important)
},
-- Storage location (optional, defaults to storage_dir .. 'memory/')
-- storage_dir = '/custom/memory/path/',
}
memory.storage_dirdefaults tonil, which means it is automatically derived from the top-levelstorage_dir(i.e.,storage_dir .. 'memory/'). Only set this if you want to use a different location. See Storage Paths for details.
Memory Type Characteristics
| Type | Lifetime | Priority | Use Case |
|---|---|---|---|
| Working | Session only | Highest | Current tasks, decisions, active context |
| Daily | 7-30 days | Medium | Short-term goals, today’s tasks, reminders |
| Long-term | Permanent | Normal | Facts, preferences, skills, knowledge |
Auto-Detection
The @extract_memory tool automatically detects memory type based on keywords:
- Working Memory: “当前/正在/current”, “任务/task”, “决策/decision”, “问题/issue”
- Daily Memory: “今天/明天/today/tomorrow”, “待办/todo”, “临时/temporary”
- Long-term Memory: Other persistent information
User Profile Configuration
chat.nvim supports user profiles (人物画像) for personalized AI assistance. Profiles store user preferences, skills, and background information as markdown files.
require('chat').setup({
user = {
enable = true, -- Enable user profile system
id = '', -- User ID (auto-detected from system username if empty)
-- storage_dir = '/custom/users/path/', -- Optional, defaults to storage_dir .. 'users/'
},
})
| Option | Type | Default | Description |
|---|---|---|---|
user.enable |
boolean | true |
Enable/disable user profile system |
user.id |
string | '' |
User ID (auto-detected from system username if empty) |
user.storage_dir |
string | nil (derived from storage_dir) |
Storage directory for user profile markdown files |
user.storage_dirdefaults tonil, which means it is automatically derived from the top-levelstorage_dir(i.e.,storage_dir .. 'users/'). Only set this if you want to use a different location. See Storage Paths for details.
When enabled, the AI assistant can use the @user_profile tool to read, update, and manage user profiles, providing personalized and context-aware responses.
Skills Configuration
chat.nvim includes a skill (slash command) system that lets you type /name [args] in the prompt window to invoke commands without sending to the LLM. You can register custom skills via configuration:
require('chat').setup({
skills = {
{
name = 'greet',
description = 'Say hello',
handler = function(args, ctx)
return 'Hello, ' .. (args or 'world') .. '!'
end,
},
},
})
Each skill spec contains:
| Field | Type | Description |
|---|---|---|
name |
string | Unique identifier (used as /name) |
description |
string | Short description shown in /help |
handler |
function | function(args: string, ctx: table): string|nil |
complete |
function | Optional completion function (args) -> string[] |
You can also register skills at runtime via require('chat').register_skill(spec) and unregister with require('chat').unregister_skill(name).
See Usage > Skills for the list of built-in skills.
Auto-Retry Configuration
chat.nvim automatically retries LLM requests that fail due to connection errors or timeouts. This helps maintain stable conversations even with intermittent network issues.
retry = {
max_retries = 3, -- Maximum retry attempts per request (default: 3)
retry_delay = 2000, -- Delay between retries in milliseconds (default: 2000 = 2 seconds)
}
How It Works
- When an LLM request fails with a retryable error (connection failure or timeout), an error message is appended to the session with a retry hint (e.g.,
Auto-retry 1/3 (2 remaining).) - The system then automatically schedules a retry after the configured delay
- Retry count is per-session and reset on each new user message
- During the retry delay period,
is_in_progress()returnstrue, preventing new messages from being sent - The user can cancel a pending retry with
Ctrl-C - On successful response, the retry count is immediately reset
- When all auto-retries are exhausted, the error message includes
Press r to retry manually.
Retryable Error Codes
The following curl exit codes are considered retryable:
| Code | Description |
|---|---|
| 6 | Couldn’t resolve host |
| 7 | Failed to connect to host |
| 28 | Operation timeout |
| 35 | SSL/TLS handshake failure |
| 52 | Empty reply from server |
| 56 | Failure with receiving data |
HTTP errors (e.g., 400, 429, 500) are not retried, as they indicate API-level issues rather than network problems.
system_prompt Usage Examples
Here are different ways to use the system_prompt option:
String (simple)
system_prompt = 'You are a helpful programming assistant.',
Function loading from file
system_prompt = function()
local path = vim.fn.expand('~/.config/nvim/AGENTS.md')
if vim.fn.filereadable(path) == 1 then
return table.concat(vim.fn.readfile(path), '\n')
end
return 'Default system prompt'
end
Function with project-specific prompts
system_prompt = function()
local cwd = vim.fn.getcwd()
if string.find(cwd, 'chat%.nvim') then
return 'You are a specialized assistant for chat.nvim plugin development.'
elseif string.find(cwd, 'picker%.nvim') then
return 'You are a specialized assistant for picker.nvim plugin development.'
end
return 'You are a general programming assistant.'
end
Function with time-based prompts
system_prompt = function()
local hour = tonumber(os.date("%H"))
local day = os.date("%A")
return string.format('Good %s! Today is %s. I am your AI assistant.',
hour < 12 and 'morning' or hour < 18 and 'afternoon' or 'evening',
day)
end
Complete Configuration Example
require('chat').setup({
-- Window settings
width = 0.8,
height = 0.8,
auto_scroll = true,
border = 'rounded',
-- AI provider settings
provider = 'deepseek',
model = 'deepseek-v4-flash',
api_key = {
deepseek = 'sk-xxxxxxxxxxxx',
github = 'github_pat_xxxxxxxx',
},
-- HTTP server configuration
http = {
host = '127.0.0.1',
port = 7777,
api_key = 'your-secret-key-here',
},
-- File access control
allowed_path = {
vim.fn.getcwd(),
vim.fn.expand('~/.config/nvim'),
},
-- Base storage directory for all persistent data
-- Sub-modules (memory, user, plans, scheduler) auto-derive from this
storage_dir = vim.fn.stdpath('data') .. '/chat.nvim/',
-- Time format
strftime = '%Y-%m-%d %H:%M',
-- System prompt
system_prompt = function()
local path = vim.fn.expand('./AGENTS.md')
if vim.fn.filereadable(path) == 1 then
return table.concat(vim.fn.readfile(path), '\n')
end
return 'You are a helpful programming assistant.'
end,
-- Memory system
memory = {
enable = true,
long_term = {
max_memories = 500,
retrieval_limit = 3,
},
daily = {
retention_days = 7,
max_memories = 100,
},
working = {
max_memories = 20,
priority_weight = 2.0,
},
-- storage_dir omitted: auto-derived from storage_dir .. 'memory/'
},
-- Auto-retry on connection errors and timeouts
retry = {
max_retries = 3,
retry_delay = 2000,
},
-- User profile system (人物画像)
user = {
enable = true,
id = '',
-- storage_dir omitted: auto-derived from storage_dir .. 'users/'
},
-- Custom skills (slash commands)
skills = {
{
name = 'greet',
description = 'Say hello',
handler = function(args, ctx)
return 'Hello, ' .. (args or 'world') .. '!'
end,
},
},
-- MCP servers (optional)
mcp = {
open_webSearch = {
command = 'npx',
args = { '-y', 'open-websearch@latest' },
},
},
-- IM integrations (optional)
integrations = {
discord = {
token = 'YOUR_DISCORD_BOT_TOKEN',
channel_id = 'YOUR_CHANNEL_ID',
},
},
})
Configuration Notes
- Path Security:
allowed_pathrestricts which file paths tools can access. Empty string disables all file access. Recommended to set to your current project directory for security.- API Keys: Only configure keys for providers you plan to use. Providers can be switched at runtime via the picker.
- Memory System: Enabled by default, automatically extracts facts and preferences from conversations. Can be disabled with
memory.enable = false.- HTTP Server: Configure
http.api_keyto enable the HTTP server. The server binds to localhost by default for security.- Dynamic Updates: Some configurations (like provider and model) can be changed dynamically at runtime via the picker.
- Automatic Scrolling: The
auto_scrolloption controls whether the result window automatically scrolls to show new content. When enabled (default), it only scrolls if the cursor was already at the bottom, preventing interruptions when reviewing history.- system_prompt Function Support: The
system_promptoption can be either a string or a function that returns a string. When a function is provided, it is called each time a new session is created, allowing for dynamic prompts based on time, project context, or external files. The function should handle errors gracefully and return a string value.- RenderMarkdown: The
render_markdownoption enables/disables the RenderMarkdown plugin for the result buffer. Defaults totrue. Set tofalseif you prefer plain markdown syntax highlighting without rich rendering.- Auto-Retry: The
retryoption configures automatic retry of LLM requests on connection errors and timeouts. When a retryable error occurs, an error message with retry status is appended to the session (e.g.,Auto-retry 1/3 (2 remaining).). When all retries are exhausted, the message includesPress r to retry manually.Retries are per-session and reset on each new user message. Only network-level errors are retried; HTTP errors (400, 429, 500, etc.) are not.- Storage Paths: All persistent data is stored under
storage_dir(defaults tostdpath('data')/chat.nvim/). Sub-module directories (memory.storage_dir,user.storage_dir, plans, scheduler) are automatically derived fromstorage_dirunless explicitly overridden. See Storage Paths for the full derivation table.- User Profiles: The
useroption configures the user profile system (人物画像). When enabled, the AI can use@user_profileto read and update user profiles for personalized assistance. Profiles are stored as markdown files underuser.storage_dir(auto-derived fromstorage_dirif not set).- Skills: The
skillsoption allows registering custom slash commands. Type/name [args]in the prompt window to invoke a skill without sending to the LLM. Built-in skills include/clear,/new,/model,/provider,/cwd,/pin,/title,/retry, and/help. See Usage > Skills for details.
Next Steps
- Usage Guide - Learn how to use chat.nvim
- Providers - Configure AI providers
- Tools - Explore available tools