diff --git a/.secrets.baseline b/.secrets.baseline index 34032de..865ec41 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -142,7 +142,7 @@ "filename": "README.md", "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", "is_verified": false, - "line_number": 85 + "line_number": 110 } ], "lazy-lock.json": [ @@ -582,5 +582,5 @@ } ] }, - "generated_at": "2026-06-06T21:52:58Z" + "generated_at": "2026-09-21T13:00:27Z" } diff --git a/README.md b/README.md index c227427..3a8a87d 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,31 @@ AI is intentionally **environment-agnostic**: opencode.nvim drives the external 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. + ### Database (vim-dadbod) Open the UI with `Du`. Add a connection with `Da`. Examples: @@ -353,7 +378,6 @@ project, branch, and worktree count when inside a git repo. ## Known issues (in current repo) -Two unrelated typos exist in `lua/config/keymaps.lua`'s opencode block (present -before these docs): the scroll-up command string reads `sesion.half.page.up` -(should be `session.…`), and `at` is mapped in `t` (terminal) mode where -`n`/`x` is likely intended. Documented here for accuracy; fix when convenient. +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. diff --git a/lazy-lock.json b/lazy-lock.json index 4209a75..e936fc6 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -31,6 +31,7 @@ "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 ac482ee..19fdd42 100644 --- a/lua/config/keymaps.lua +++ b/lua/config/keymaps.lua @@ -69,7 +69,14 @@ map({ "n", "x" }, "ax", function() require("opencode").select() end, { desc = "AI Ask (selection)" }) map({ "n", "t" }, "at", function() - require("opencode").toggle() + -- 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() @@ -80,7 +87,7 @@ map("n", "goo", function() end, { desc = "Add line to AI chat", expr = true }) map("n", "", function() - require("opencode").command("sesion.half.page.up") + require("opencode").command("session.half.page.up") end, { desc = "Scroll AI chat up" }) map("n", "", function() require("opencode").command("session.half.page.down") diff --git a/lua/plugins/ai.lua b/lua/plugins/ai.lua index 9d50fce..d349d4f 100644 --- a/lua/plugins/ai.lua +++ b/lua/plugins/ai.lua @@ -1,7 +1,13 @@ return { { + -- Drive the OpenCode TUI from Neovim. + -- + -- 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 = "v0.10.1", + version = "v1.0.2", dependencies = { { ---@module "snacks" @@ -11,8 +17,14 @@ return { input = {}, -- Enhances `ask()` picker = { -- Enhances `select()` actions = { - opencode_send = function(...) - return require("opencode").snacks_picker_send(...) + 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 = { @@ -27,38 +39,36 @@ return { }, }, config = function() - local opencode_cmd = "opencode --port" + -- `--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, - on_win = function(win) - -- Set up keymaps and cleanup for an arbitary terminal - require("opencode.terminal").setup(win.win) - end, }, } ---@type opencode.Opts vim.g.opencode_opts = { - -- Specific configuration around opencode server = { start = function() require("snacks.terminal").open(opencode_cmd, snacks_terminal_opts) end, - stop = function() - require("snacks.terminal").get(opencode_cmd, snacks_terminal_opts):close() - end, - toggle = function() - require("snacks.terminal").toggle(opencode_cmd, snacks_terminal_opts) - end, - }, - lsp = { - enabled = true, }, } + -- Reload buffers that OpenCode edits (the plugin also sets this itself) vim.o.autoread = true -- Required for `opts.events.reload` end, },