From 711b1038afb75fc96923eccf5baf1fcebb999868 Mon Sep 17 00:00:00 2001 From: Samuel O'Neal Date: Tue, 13 Oct 2026 11:59:38 -0600 Subject: [PATCH 1/2] AI: replace opencode.nvim (V1-pinned) with agentic.nvim (ACP) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit opencode.nvim required the OpenCode V1 CLI and its `--port` HTTP API, which v2 removed, so the config pinned a separate V1 binary and carried a binary split plus OPENCODE_DISABLE_AUTOUPDATE. Swap it for carlos-algms/agentic.nvim, an ACP client that drives `opencode acp` (v2) straight from PATH — no pinning, no second binary. - provider defaults to opencode-acp - new sessions start in the git worktree root (session_cwd) - keep the a* layout, extended with session/provider/diagnostics - drop the go/goo operators and / (no TUI/Vim-operator API) - update README and lazy-lock accordingly --- .secrets.baseline | 4 +- README.md | 89 ++++++++++++------------ lazy-lock.json | 2 +- lua/config/keymaps.lua | 33 +-------- lua/plugins/ai.lua | 150 +++++++++++++++++++++++------------------ 5 files changed, 135 insertions(+), 143 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 865ec41..dedc4d3 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -142,7 +142,7 @@ "filename": "README.md", "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", "is_verified": false, - "line_number": 110 + "line_number": 101 } ], "lazy-lock.json": [ @@ -582,5 +582,5 @@ } ] }, - "generated_at": "2026-09-21T13:00:27Z" + "generated_at": "2026-10-13T17:59:14Z" } diff --git a/README.md b/README.md index 6f8797f..a81407b 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ CSS, JSON, YAML, Markdown, SQL, Dockerfile, Python. | Testing | neotest (Go, Python, Zig) with in-buffer pass/fail signs | | Coverage | nvim-coverage (Go) | | Task running | overseer.nvim (+ user templates) | -| AI chat | [opencode.nvim](https://github.com/nickjvandyke/opencode.nvim) (provider-agnostic) | +| AI chat | [agentic.nvim](https://github.com/carlos-algms/agentic.nvim) (ACP; OpenCode by default) | | Database | vim-dadbod + dadbod-ui + dadbod-completion | | Git | Neogit + diffview, plus LazyVim's lazygit | | Explorer/picker | snacks.nvim | @@ -70,37 +70,28 @@ CSS, JSON, YAML, Markdown, SQL, Dockerfile, Python. | Diagnostics | trouble.nvim | | Cheat sheet | which-key.nvim (hold ``) | -### AI (opencode.nvim) +### AI (agentic.nvim) -AI is intentionally **environment-agnostic**: opencode.nvim drives the external -[`opencode`](https://opencode.ai) CLI, so the model/provider (Anthropic, -OpenAI, local models, etc.) is chosen in opencode's own config rather than here. -Install the `opencode` CLI separately and configure your provider there. +AI is intentionally **environment-agnostic**: [agentic.nvim](https://github.com/carlos-algms/agentic.nvim) +is a chat front-end for any agent that speaks the +[Agent Client Protocol](https://agentclientprotocol.com) (ACP). We drive the +external [`opencode`](https://opencode.ai) CLI through `opencode acp`, so the +model/provider (Anthropic, OpenAI, local models, etc.) is chosen in opencode's +own config rather than here. Install the `opencode` CLI separately and configure +your provider there. -> [!IMPORTANT] -> This integration requires the OpenCode **V1** CLI. opencode.nvim connects to -> the API server that `opencode --port` exposes; OpenCode **v2 removed that -> flag** and replaced the server API (v2 support in opencode.nvim is tracked -> upstream in [nickjvandyke/opencode.nvim#322](https://github.com/nickjvandyke/opencode.nvim/issues/322)). -> -> **Binary split:** Neovim explicitly launches the pinned V1 binary at -> `~/.opencode/bin/opencode` (see `opencode_cmd` in `lua/plugins/ai.lua` and the -> `at` toggle in `lua/config/keymaps.lua`), so your terminal is free to -> keep using the latest `opencode` (v2) from its normal PATH. -> -> Pin V1 with the install script (replace `1.18.31` with the latest V1 release): -> -> ```sh -> curl -fsSL https://opencode.ai/install | bash -s -- --version 1.18.31 -> ``` -> -> Do **not** put `~/.opencode/bin` on your shell PATH or set -> `OPENCODE_DISABLE_AUTOUPDATE=1` globally: installing the pinned binary via the -> script above prepends `~/.opencode/bin` to `PATH` in `~/.zshrc` (remove that -> line) and a global env var would stop the terminal's v2 from auto-updating. -> Instead, the config sets `OPENCODE_DISABLE_AUTOUPDATE=1` on the spawned V1 -> process only, so the pinned binary can't replace itself with v2 while your -> terminal's opencode keeps updating. +> [!NOTE] +> Unlike the previous opencode.nvim setup, **no version pinning or binary split +> is needed**. agentic spawns `opencode acp` from your normal `PATH`, so keep +> just the one `opencode` install. Other ACP providers (Claude, Codex, Gemini, +> Cursor, …) are built in — change `provider` in `lua/plugins/ai.lua`, or switch +> at runtime with `ap`. Sessions are owned by the provider, so a chat +> started in the terminal can be pulled into Neovim and vice-versa +> (`ar`). + +New sessions start in the **git worktree root** (`session_cwd` → +`config.git-worktree.git_root`), so the agent edits the same checkout Neovim is +open in; outside a repo it falls back to Neovim's cwd. ### Database (vim-dadbod) @@ -129,14 +120,26 @@ clickable. ### AI (`a`) -| Key | Action | -| --------------------- | ---------------------------------- | -| `aa` | Ask AI about current context (n/v) | -| `ax` | Ask AI about selection | -| `at` | Toggle AI panel | -| `go` | Operator: add range to AI chat | -| `goo` | Add current line to AI chat | -| `` / `` | Scroll AI chat up/down | +| Key | Action | +| --------------------- | --------------------------------------------- | +| `aa` | Open AI chat, adding current file/selection | +| `ax` | Add current file or selection to AI context | +| `at` | Toggle AI chat | +| `an` | New AI session | +| `al` | Pick an AI session | +| `ar` | Restore an AI session (incl. terminal ones) | +| `ap` | Switch ACP provider | +| `ad` | Add cursor-line diagnostics to AI context | +| `aD` | Add buffer diagnostics to AI context | + +Inside the chat buffer agentic sets its own keys (see `:h agentic`): `` +agent mode, `m` model, `s` provider, `l` +sessions, `q` hide (session keeps running), `]]`/`[[` headings, `]c`/`[c` diff +hunks. + +> The old `go`/`goo` operators and ``/`` scroll keys are gone — +> agentic has no Vim operator, and it navigates context/diffs inside its own +> chat buffer (which is a normal Neovim buffer, not a terminal). ### Code › Go (`cg`) @@ -371,7 +374,7 @@ to anything reading it but is not printed in the statusline. │ │ ├── neotest.lua # Test runner (go/python/zig) │ │ ├── go-coverage.lua # Go coverage signs │ │ ├── overseer.lua # Task runner -│ │ ├── ai.lua # opencode.nvim +│ │ ├── ai.lua # agentic.nvim │ │ ├── dadbod.lua # Database │ │ ├── git.lua # Neogit + diffview │ │ ├── worktree.lua # Git worktree keymaps (`gw/gW/gC`) @@ -420,6 +423,8 @@ to anything reading it but is not printed in the statusline. ## Known issues (in current repo) -One quirk remains in `lua/config/keymaps.lua`'s opencode block (present before -these docs): `at` is also mapped in `t` (terminal) mode, not just `n` — -intentional, so the TUI terminal window itself can toggle the split. +- `agentic.nvim` sends `@`-mentioned files as **path references**, so the agent + reads them from disk: save the buffer before adding a file to the context. A + visual selection is inlined from the buffer, so unsaved edits there are fine. +- OpenCode's interactive `question` tool is excluded over ACP by default; enable + it with `OPENCODE_ENABLE_QUESTION_TOOL=1` if you need structured prompts. diff --git a/lazy-lock.json b/lazy-lock.json index e936fc6..ccec553 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -3,6 +3,7 @@ "LazyVim": { "branch": "main", "commit": "28db03f958d58dfff3c647ce28fdc1cb88ac158d" }, "SchemaStore.nvim": { "branch": "main", "commit": "a0fad73139f98ea1d6e9d380374c16245e562f4f" }, "aerial.nvim": { "branch": "master", "commit": "7a6a42791eb2b54a7115c7db4488981f93471770" }, + "agentic.nvim": { "branch": "main", "commit": "5ee51100ce213fed47c9307065155b87ee873141" }, "avante.nvim": { "branch": "main", "commit": "e1e70be8ee34144d3ce4b0608e9b30aab3feb701" }, "blink.cmp": { "branch": "main", "commit": "b19413d214068f316c78978b08264ed1c41830ec" }, "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, @@ -31,7 +32,6 @@ "neotest-golang": { "branch": "main", "commit": "53f06063780b0b244583d3d32b138fc2df21e162" }, "neotest-python": { "branch": "master", "commit": "b0d3a861bd85689d8ed73f0590c47963a7eb1bf9" }, "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, - "opencode.nvim": { "branch": "main", "commit": "84eabfbe65a44f452ee302fe360cea9fd9939f31" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, "nvim-colorizer.lua": { "branch": "master", "commit": "81e676d3203c9eb6e4c0ccf1eba1679296ef923f" }, "nvim-coverage": { "branch": "main", "commit": "a939e425e363319d952a6c35fb3f38b34041ded2" }, diff --git a/lua/config/keymaps.lua b/lua/config/keymaps.lua index 19fdd42..22080c0 100644 --- a/lua/config/keymaps.lua +++ b/lua/config/keymaps.lua @@ -60,38 +60,9 @@ map("n", "", ":m '>+1gv=gv", { desc = "Move selection down" }) map("n", "", ":m '<-2gv=gv", { desc = "Move selection up" }) -- ───────────────────────────────────────────────────────────────────────────── --- AI (OpenCode) +-- AI keymaps live in lua/plugins/ai.lua (agentic.nvim) so the plugin loads +-- lazily on first keypress. -- ───────────────────────────────────────────────────────────────────────────── -map({ "n", "x" }, "aa", function() - require("opencode").ask("@this: ", { submit = true }) -end, { desc = "AI Ask" }) -map({ "n", "x" }, "ax", function() - require("opencode").select() -end, { desc = "AI Ask (selection)" }) -map({ "n", "t" }, "at", function() - -- opencode.nvim v1.0.2 removed `opencode.toggle()`; toggle the TUI terminal - -- directly. Command, `env` and window opts must match `opencode_cmd` and - -- `snacks_terminal_opts` in lua/plugins/ai.lua so `snacks.terminal.tid` - -- identifies the same terminal. - require("snacks.terminal").toggle(vim.fn.expand("$HOME/.opencode/bin/opencode") .. " --port", { - env = { OPENCODE_DISABLE_AUTOUPDATE = "1" }, - win = { position = "right", enter = false }, - }) -end, { desc = "AI Toggle" }) - -map({ "n", "x" }, "go", function() - return require("opencode").operator("@this ") -end, { desc = "Add range to AI chat", expr = true }) -map("n", "goo", function() - return require("opencode").operator("@this ") .. "_" -end, { desc = "Add line to AI chat", expr = true }) - -map("n", "", function() - require("opencode").command("session.half.page.up") -end, { desc = "Scroll AI chat up" }) -map("n", "", function() - require("opencode").command("session.half.page.down") -end, { desc = "Scroll AI chat down" }) -- ───────────────────────────────────────────────────────────────────────────── -- Database (vim-dadbod) diff --git a/lua/plugins/ai.lua b/lua/plugins/ai.lua index d349d4f..db05a3d 100644 --- a/lua/plugins/ai.lua +++ b/lua/plugins/ai.lua @@ -1,75 +1,91 @@ return { { - -- Drive the OpenCode TUI from Neovim. + -- Chat front-end for AI agents that speak the Agent Client Protocol (ACP). -- - -- IMPORTANT: this integration requires the OpenCode **V1** CLI. opencode.nvim - -- connects to the HTTP API that `opencode --port` exposes; OpenCode v2 removed - -- that flag and replaced the server API, which opencode.nvim does not support - -- yet (https://github.com/nickjvandyke/opencode.nvim/issues/322). - "nickjvandyke/opencode.nvim", - version = "v1.0.2", - dependencies = { + -- We drive OpenCode through its ACP server (`opencode acp`), so this works + -- with whatever `opencode` is on PATH — no version pinning and no separate + -- pinned binary (the old opencode.nvim setup needed both, because it talked + -- to the V1 `--port` server API that v2 removed). Other ACP providers + -- (Claude, Codex, Gemini, Cursor, ...) are built in; see `provider` below. + "carlos-algms/agentic.nvim", + keys = { { - ---@module "snacks" - "folke/snacks.nvim", - optional = true, - opts = { - input = {}, -- Enhances `ask()` - picker = { -- Enhances `select()` - actions = { - opencode_send = function(picker) ---@param picker snacks.Picker - local items = vim.tbl_map(function(item) ---@param item snacks.picker.Item - return item.file - and require("opencode").format({ path = item.file, from = item.pos, to = item.end_pos }) - or item.text - end, picker:selected({ fallback = true })) - - require("opencode").prompt(table.concat(items, ", ") .. " ") - end, - }, - win = { - input = { - keys = { - [""] = { "opencode_send", mode = { "n", "i" } }, - }, - }, - }, - }, - }, + "aa", + function() + require("agentic").open() + end, + mode = { "n", "v" }, + desc = "AI Ask", + }, + { + "ax", + function() + require("agentic").add_selection_or_file_to_context() + end, + mode = { "n", "v" }, + desc = "AI Add context", + }, + { + "at", + function() + require("agentic").toggle() + end, + desc = "AI Toggle", + }, + { + "an", + function() + require("agentic").new_session() + end, + mode = { "n", "v" }, + desc = "AI New session", + }, + { + "al", + function() + require("agentic").select_session() + end, + desc = "AI Sessions", + }, + { + "ar", + function() + require("agentic").restore_session() + end, + desc = "AI Restore session", + }, + { + "ap", + function() + require("agentic").switch_provider() + end, + desc = "AI Switch provider", + }, + { + "ad", + function() + require("agentic").add_current_line_diagnostics() + end, + desc = "AI Add line diagnostics", + }, + { + "aD", + function() + require("agentic").add_buffer_diagnostics() + end, + desc = "AI Add buffer diagnostics", }, }, - config = function() - -- `--port` exposes OpenCode's HTTP API, which opencode.nvim discovers and - -- connects to. V1 CLI only; v2 removed this flag. - -- - -- Binary split: nvim explicitly uses the pinned V1 binary at - -- ~/.opencode/bin/opencode while the interactive shell keeps using the - -- latest `opencode` (v2) from its PATH. Keep this in sync with the - -- `at` toggle in lua/config/keymaps.lua. - local opencode_cmd = vim.fn.expand("$HOME/.opencode/bin/opencode") .. " --port" - ---@type snacks.terminal.Opts - local snacks_terminal_opts = { - -- V1 checks for updates on startup and would replace itself with V2; - -- disable autoupdate for this pinned binary only (does not affect the - -- terminal's v2, which keeps updating). - env = { OPENCODE_DISABLE_AUTOUPDATE = "1" }, - win = { - position = "right", - enter = false, - }, - } - - ---@type opencode.Opts - vim.g.opencode_opts = { - server = { - start = function() - require("snacks.terminal").open(opencode_cmd, snacks_terminal_opts) - end, - }, - } - - -- Reload buffers that OpenCode edits (the plugin also sets this itself) - vim.o.autoread = true -- Required for `opts.events.reload` - end, + ---@type agentic.PartialUserConfig + opts = { + -- OpenCode is the provider this config drives (agentic defaults to Claude). + provider = "opencode-acp", + -- Start new sessions in the git worktree being edited (the worktree + -- top-level, not a nested subdirectory) so the agent touches the same + -- checkout Neovim is open in. Falls back to Neovim's cwd outside a repo. + session_cwd = function(cwd) + return require("config.git-worktree").git_root(cwd) + end, + }, }, } -- 2.54.0 From e968a858224599993987a2ef998b818273f999c3 Mon Sep 17 00:00:00 2001 From: Samuel O'Neal Date: Tue, 13 Oct 2026 12:01:31 -0600 Subject: [PATCH 2/2] updated AGENTS file --- AGENTS.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..5c0062d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,5 @@ +# AGENTS.md + +## Output style + +Keep output concise and limited to answering the task or question. Only produce text for the end user when you need to explain the final decision, ask a follow-up question, or request more work. Otherwise, do not narrate your process or emit status updates or summaries. -- 2.54.0