Skip to content

Latest commit

 

History

529 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vibing.nvim logo

vibing.nvim

Intelligent AI-Powered Code Assistant for Neovim

CI License: MIT Release

A powerful Neovim plugin that integrates Claude, Codex, and GitHub Copilot AI via CLI backends, bringing intelligent, context-aware chat conversations directly into your editor.

English | 日本語

FeaturesInstallationUsageConfigurationContributing


Table of Contents

✨ Features

Unlike chat plugins that send static context to an LLM, vibing.nvim gives the AI direct access to your Neovim instance through CLI backends and MCP integration.

  • 🤖 Neovim as an agent tool — via MCP, the AI reads and writes buffers, executes commands, and queries LSP (diagnostics, definitions, references, symbols) in your running editor
  • 🔀 Multi-backend — Claude CLI (claude -p --output-format stream-json), Codex CLI (codex exec --json), GitHub Copilot CLI (copilot -p --output-format json), or Grok Build CLI (grok --single --output-format streaming-json); switch globally via adapter or per-chat via the agent frontmatter field
  • 💾 File-based session persistence — chats are plain Markdown files with YAML frontmatter saved under .vibing/chat/: portable, resumable (full CLI session state), auditable, and version-controllable
  • 🔀 Concurrent sessions — run multiple independent chats simultaneously; start a new chat while another is still processing
  • 🛡️ Granular permissions — allow/deny/ask lists per tool, path-based rules for sensitive files, Bash command patterns, and an interactive Permission Builder UI
  • 📊 Diff viewergd on a changed file shows a before/after diff. Each turn is snapshotted as a git tree object, so a sed -i, a mv or a formatter run through Bash is tracked exactly like an Edit — with no external tool and no setup, and without touching your index
  • 🎯 Smart context — add files manually, from oil.nvim, or from a visual selection
  • ⏳ Usage-limit scheduling — while a usage limit is in force, <CR> parks your message instead of burning a doomed request, and sends it verbatim once the limit resets; :VibingSchedule 30m schedules one by hand, with or without a limit
  • 🌍 Multi-language support — configure the AI response language per chat

Consider alternatives if you

  • Need local/offline models (Ollama, etc.)
  • Prefer minimal dependencies (vibing.nvim requires Node.js for the MCP server)
  • Want a battle-tested plugin with a large community (we're still growing!)

vibing.nvim doesn't conflict with completion plugins (Copilot, Codeium) or other chat plugins — they compose well.

📦 Installation

Prerequisites

  • Neovim 0.10+ (uses vim.system())
  • Node.js 18+ (for the MCP server)
  • At least one AI CLI backend:
    • Claude CLI (claude) — npm install -g @anthropic-ai/claude-code
    • Codex CLI (codex) — npm install -g @openai/codex (0.140+; see note below)
    • GitHub Copilot CLI (copilot) — npm install -g @github/copilot (needs Node.js 22+, higher than the 18+ the MCP server itself requires)
    • Grok Build CLI (grok) — see xAI's install docs

Codex version note. vibing.nvim runs the Codex backend's lightweight calls (chat title generation, /summarize, daily summary) with --ignore-user-config --strict-config, which keeps those calls out of your MCP servers and makes them fail loudly rather than silently unfenced if Codex renames a config key. Both flags were verified present in 0.140.0 and 0.147.0, on codex exec and codex exec resume alike. Older releases were not tested; if they lack the flags, ordinary chat is unaffected but lightweight calls fail with an unknown-argument error. Upgrade Codex if you see that.

--ignore-user-config also drops model_provider, so if your config.toml points Codex at a custom or local provider, those lightweight calls go to the default OpenAI endpoint instead. Ordinary chat still uses your provider. vibing.nvim warns once per Neovim session when this applies to you, asking Codex itself (codex doctor --json) which provider is configured; it says nothing if Codex cannot answer. Set agent.codex_provider_notice.enabled = false to turn the warning and its probe off.

Using lazy.nvim

{
  "shabaraba/vibing.nvim",
  dependencies = {
    "stevearc/oil.nvim",  -- Optional: file browser integration
  },
  build = "./build.sh",  -- Builds the bundled chat parser and MCP server
  config = function()
    require("vibing").setup()
  end,
}

See Configuration for the options you can pass to setup().

use {
  "shabaraba/vibing.nvim",
  run = "./build.sh",
  config = function()
    require("vibing").setup()
  end,
}

Claude Code Plugin (MCP + Skills + Agents)

vibing.nvim ships a Claude Code plugin that bundles the vibing-nvim MCP server together with Neovim-aware skills and a read-only navigation subagent.

Nothing to install. The plugin is not registered into Claude Code's global state at all — vibing.nvim hands the CLI its own claude-plugin/ directory per session with --plugin-dir, so whichever checkout is running is the one that serves you. build.sh builds the MCP server and the small Tree-sitter parser used for chat boundaries (and, once, cleans up an install from an older version of vibing.nvim). If no C compiler is available, the parser build is skipped and chat buffers fall back to the previous whole-buffer Markdown parser.

That gives you mcp__plugin_vibing-nvim_vibing-nvim__* tools (buffer/window/cursor access, Ex commands, and LSP queries against the running Neovim instance), the bundled skills (nvim-context, nvim-lsp-navigation, vibing-chat-recall, vibing-chat-search, and the vibing-worktree-{list,create,attach,run,finish} worktree workflow), and the nvim-navigator subagent (read-only code navigation via @vibing-nvim:nvim-navigator).

You still need Neovim running with mcp = { enabled = true } (the default) for the MCP tools to have anything to connect to. The one trade-off is that a plain claude session started outside Neovim no longer sees these tools; that was never a supported way to use them.

The Codex backend gets the same plugins without a --plugin-dir of its own: the MCP server is registered per run as -c mcp_servers.vibing-nvim.* (tools named mcp__vibing-nvim__*) and the skills are listed for the model in developer_instructions. Subagents do not carry over.

Your own project plugins. Anything you drop into .vibing/plugins/<name>/ (with a .claude-plugin/plugin.json) is loaded the same way, for chats in that project only. Run :VibingReloadCommands after adding one, or :VibingCreatePlugin <name> to write a working skeleton in the first place. Note that a plugin may declare mcpServers, so a plugin in a repository you cloned can start a process on your machine — set agent.plugins.project_dir = false for repositories you do not trust. See handbook/configuration.md for agent.plugins.

Upgrading from an older vibing.nvim: build.sh removes the user-scope install and its marketplace entry for you. To do it by hand:

/plugin uninstall vibing-nvim@vibing
/plugin marketplace remove vibing

🚀 Quick Start

:VibingChat        " Open a new chat

Type your message under the ## User header and press <CR> in normal mode to send. The AI responds in the same buffer; <C-c> cancels a running request. Chats remain ordinary Markdown files that you can save, search, and edit normally. In Neovim, the small vibing Tree-sitter parser isolates chat headers and tool output, then injects the standard Markdown parser into each message body. Existing Markdown highlighting, including fenced code languages, is preserved.

🚀 Usage

Also available offline as :help vibing-commands, which carries per-command help tags.

User Commands

Command Description
:VibingChat [position|file] Create new chat with optional position (current|right|left|top|bottom|back) or open saved file
:VibingToggleChat Toggle existing chat window (preserve current conversation)
:VibingChatFork [position] Fork current chat (create branch from current conversation)
:VibingChatHandoff [position] Summarize this chat and start a new one whose first message carries the summary (cheap continuation of a long chat)
:VibingChatJumpNextUser [count] Move the cursor to the next User section in the chat buffer
:VibingChatJumpPrevUser [count] Move the cursor to the previous User section in the chat buffer
:VibingSlashCommands Show slash command picker in chat
:VibingSetFileTitle Generate AI title and rename chat file (uses an existing ## summary if present)
:VibingSummarize [--with-title] Generate AI summary of chat history and insert into buffer (--with-title then renames the file from that summary)
:VibingDeleteChats [--unrenamed] Delete chat files (use --unrenamed to delete all unrenamed files)
:VibingContext [path] Add context: oil.nvim entry, visual selection (range), path argument, or current buffer when no args
:VibingClearContext Clear all context
:VibingCancel Cancel current request
:VibingSchedule [when] Schedule this chat's unsent message (default: the recorded limit reset; or 30m, 18:30, …)
:VibingPendingResumes List chats waiting on a usage limit reset or a scheduled send
:VibingCancelResume [all] Cancel the pending auto-resume/scheduled send for this chat (or every one with all); also clears the project's recorded usage limit
:VibingReloadCommands Reload custom slash commands and completion candidates
:VibingCreatePlugin [name] Create a project-local Claude Code plugin under .vibing/plugins/
:VibingCopyUnsentUserHeader Copy ## User <!-- unsent --> to clipboard
:VibingDailySummary [YYYY-MM-DD] Generate daily summary from project chat files (default: today)
:VibingDailySummaryAll [YYYY-MM-DD] Generate daily summary from all chat files (default: today)

Command Semantics:

  • :VibingChat — always creates a fresh chat. Optionally specify a position (current / right / left / top / bottom / back) or a saved chat file path to reopen it.
  • :VibingChatFork — fork the current conversation to branch in a different direction (accepts the same positions).
  • :VibingChatHandoff — continue a long conversation in a fresh chat: the current chat is summarized, and the new chat's first message starts with that summary. Unlike a fork it does not carry the history, so every later request reads a few thousand tokens of summary instead of the whole transcript (accepts the same positions). An existing ## summary section is reused as-is; run /summarize first if it is out of date.
  • :VibingToggleChat — show/hide your current conversation, preserving its state.
  • Worktree lifecycle — handled by the bundled vibing-worktree-{list,create,attach,run,finish} Claude Code skills entirely via natural language ("split this off into a worktree"), not by editor commands.

Slash Commands (in Chat)

Command Description
/context <file> Add file to context
/clear Clear context
/save Save current chat
/summarize Summarize conversation
/model <model> Set AI model for the current backend
/effort <level> Set reasoning effort (low/medium/high/xhigh/max)
/help Show available slash commands
/permissions or /perm Interactive permission builder - configure tool allow/deny rules
/allow [tool] Add tool to allow list (-tool removes), or show current list if no args
/deny [tool] Add tool to deny list (-tool removes), or show current list if no args
/ask [tool] Ask before using tool (-tool removes), or show current list if no args
/permission [mode] Set permission mode (default/acceptEdits/bypassPermissions/plan/dontAsk/auto)
/new-session Reset session and start fresh

/allow, /deny, and /ask also accept granular patterns like Bash(git:*), Read(src/**/*.ts), and WebFetch(github.com).

Chat Keybindings

In chat buffers (all except q are configurable via keymaps — see Configuration):

Key Description
<CR> Send message (normal mode)
<C-c> Cancel current request
<C-a> Add file to context
gd Show diff for file under cursor (in Modified Files section)
gf Open file under cursor (Modified Files section, or any path in the chat)
gx Open URL on current line in browser
q Close chat window

⚙️ Configuration

require("vibing").setup() works out of the box. Commonly tweaked options:

require("vibing").setup({
  adapter = "claude",              -- "claude" | "codex" | "copilot" | "grok"
  chat = {
    window = {
      position = "current",        -- "current" | "right" | "left" | "top" | "bottom" | "back" | "float"
      width = 0.4,                 -- screen-width ratio (0-1)
    },
    save_location_type = "project", -- "project" | "user" | "custom"
  },
  agent = {
    default_model = "sonnet",      -- backend model id, e.g. "sonnet" or "gpt-5.6-terra"
    default_effort = "default",     -- "default" | "low" | "medium" | "high" | "xhigh" | "max"
    scheduled_requests = {
      enabled = true,              -- during a usage limit, <CR> schedules instead of sending
    },
  },
  permissions = {
    mode = "acceptEdits",          -- "default" | "acceptEdits" | "plan" | "auto" | "dontAsk" | "bypassPermissions"
    allow = { "Read", "Edit", "Write", "Glob", "Grep", "Skill", "StructuredOutput" },
    deny = { "Bash" },
    codex_profile_file = ".vibing/codex-permissions.toml", -- false disables loading the generated profile
    -- codex_profile_content = [[...]], -- initial TOML used only when creating the profile
    codex_allow_tracked_profile = false, -- true explicitly trusts a Git-tracked profile
  },
  language = nil,                  -- e.g. "ja", or { default = "ja", chat = "ja" }
})

The default permissions shown above are used as a template when creating new chat files; each chat file's frontmatter carries its own permissions, which are what's enforced at runtime.

For the Codex backend, vibing.nvim creates .vibing/codex-permissions.toml when it initializes a project. Its default profile permits workspace and Git metadata writes without using full bypass mode; edit the file to narrow or extend the OS sandbox. Existing files are never overwritten. Git-tracked profiles are rejected unless codex_allow_tracked_profile = true explicitly trusts the reviewed file; locally generated, untracked profiles continue to load automatically. See Project-local Codex permission profiles.

Full reference: every option (window details, UI/gradient/tool markers, diff backends, granular permission rules, MCP, Node.js executable, daily summary, ...) is documented in handbook/configuration.md.

📝 Chat File Format

Chats are saved as Markdown files (.vibing/chat/chat-<timestamp>-....md by default) with YAML frontmatter for session resumption and configuration:

---
vibing.nvim: true
session_id: <cli-session-id>
created_at: 2024-01-01T12:00:00
working_dir: .vibing/worktrees/feature-x  # Optional: working directory (relative to git root)
agent: claude  # claude | codex | copilot | grok (overrides global adapter setting for this chat)
mode: code  # code | plan | explore
model: sonnet  # Backend model id, e.g. sonnet or gpt-5.6-terra
effort: default  # CLI/model default | low | medium | high | xhigh | max
permission_mode: acceptEdits  # default | acceptEdits | bypassPermissions | plan | dontAsk | auto
permissions_allow:
  - Read
  - Edit
  - Write
  - Glob
  - Grep
permissions_deny:
  - Bash
permissions_ask: []
language: ja  # Optional: default language for AI responses
---
# Vibing Chat

## User

Hello, Claude!

## Assistant

Hello! How can I help you today?

Key Features:

  • Session Resumption — reopening a saved chat resumes the conversation via session_id
  • Fork tracking — a forked chat carries a forked_from field until its first response
  • Auditability — model, mode, and permissions are all visible in frontmatter
  • Language Support — optional language field for consistent AI response language

🏗️ Architecture

For detailed architecture documentation, see CLAUDE.md.

graph TB
    subgraph Neovim["Neovim Process"]
        Plugin["vibing.nvim<br/>(Lua Plugin)"]
        Buffer["Chat Buffer<br/>(.vibing/chat/*.md)<br/>- Markdown + YAML<br/>- Session metadata<br/>- Permission settings"]
        RPC["RPC Server<br/>(Async TCP)"]

        Plugin -->|manages| Buffer
        Plugin -->|uses| RPC
    end

    subgraph MCP["Node.js MCP Server"]
        MCPServer["MCP Server<br/>- Buffer operations<br/>- LSP queries<br/>- Command execution"]
    end

    subgraph AI["AI CLI Backends"]
        Claude["Claude CLI<br/>(claude -p --output-format stream-json)"]
        Codex["Codex CLI<br/>(codex exec --json)"]
        Copilot["Copilot CLI<br/>(copilot -p --output-format json)"]
    end

    RPC <-->|JSON-RPC| MCPServer
    Plugin -->|spawns & communicates<br/>JSON Lines| Claude
    Plugin -->|spawns & communicates<br/>JSON Lines| Codex
    Plugin -->|spawns & communicates<br/>JSON Lines| Copilot
Loading
Aspect Traditional REST API vibing.nvim (CLI Adapters)
Context Manually assembled MCP: agent requests on-demand
Editor Access None (fire & forget) Full bidirectional MCP
Session State Plugin manages CLI session with resume
Tool Execution Plugin implements CLI native tools

❓ FAQ

Which AI backends are supported?

  • Claude CLI (claude -p --output-format stream-json) — full Claude Code capabilities
  • Codex CLI (codex exec --json) — OpenAI Codex backend
  • GitHub Copilot CLI (copilot -p --output-format json) — GitHub Copilot backend
  • Grok Build CLI (grok --single --output-format streaming-json) — xAI Grok backend

Switch globally with adapter = "claude"|"codex"|"copilot"|"grok" in setup, or per-chat by adding agent: claude, agent: codex, agent: copilot, or agent: grok to a chat file's YAML frontmatter. effort: low|medium|high|xhigh|max controls reasoning for Claude, Codex, and Grok when the selected model supports that level. New chats use effort: default, which passes no override and therefore preserves the same CLI/model default used before effort was configurable. Omitting the field has the same runtime behaviour for existing chats.

Note: on the Copilot backend, permissions.mode, permissions.ask and the in-chat Tool Approval UI are enforced through a generated Copilot plugin (.vibing/copilot-plugin/) that vibing.nvim loads per run with copilot --plugin-dir. Your own ~/.copilot/ configuration and login are never touched. Copilot's static --deny-tool flags are still passed as a backstop; they cover Bash (including Bash(cmd:*) patterns), Write, Edit, WebFetch and WebSearch, and vibing.nvim warns once when it drops a tool name Copilot cannot express.

Why does it require Node.js?

Node.js is required for the MCP server, which provides AI with direct access to your running Neovim instance (buffer reads/writes, LSP queries, command execution). The AI CLI binaries themselves (claude, codex, copilot) are separate installs.

How does it compare to Claude Code CLI?

vibing.nvim provides similar capabilities to Claude Code CLI but integrated into Neovim:

  • Same claude CLI underneath
  • MCP for editor control (CLI controls terminal, vibing controls Neovim)
  • Additional Codex and GitHub Copilot backend options for non-Anthropic workflows

Think of it as "Claude Code (or Codex, or Copilot) for Neovim users."

Can I use vibing.nvim alongside other AI plugins?

Yes. vibing.nvim doesn't conflict with completion plugins (Copilot, Codeium) or other chat plugins. Use vibing.nvim for deep Claude interactions and other tools for quick completions or different providers.

🤝 Contributing

Contributions are welcome! See CONTRIBUTING.md, and feel free to submit issues or pull requests.

📄 License

MIT License - see LICENSE file for details

🔗 Links


Made with ❤️ using Claude Code!

About

Neovim plugin for AI-assisted coding: Claude CLI & Codex CLI backends with MCP-powered editor control

Topics

Resources

Contributing

Security policy

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages